#include "objgfx40.h" #include "defpal.inc" #include "ogDisplay_VESA.h" #include <go32.h> // for __tb #include <dpmi.h> #include <sys/movedata.h> #include <sys/farptr.h> #include <pc.h> #include <string.h> /* * * ogDisplay methods * */ void initVESAMode(uInt16 mode) { __dpmi_regs regs; regs.x.ax = 0x4f02; regs.x.bx = mode; __dpmi_int(0x10, ®s); return; } ogDisplay_VESA::ogDisplay_VESA(void) : ogSurface() { pages[0] = pages[1] = NULL; activePage = visualPage = 0; inGraphics = false; VESAInfo = new ogVESAInfo; modeInfo = new ogModeInfo; pal = new ogRGBA8[256]; attributes = new ogAttributes(); GetVESAInfo(); screenSelector = __dpmi_allocate_ldt_descriptors(1); return; } // ogDisplay_VESA::ogDisplay_VESA uInt32 ogDisplay_VESA::RawGetPixel(uInt32 x, uInt32 y) { uInt32 result; switch (bytesPerPix) { case 4: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax (screenSelector) " shl $2, %%ecx \n" // shl ecx, 2 {adjust for pixel size} // " add (%%esi,%%ebx,4), %%edi \n" // add edi, [esi + ebx*4] " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx " mov (%%edi),%%eax \n" // eax,word ptr [edi] " mov %%eax, %4 \n" // mov result, eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (screenSelector), "c" (x), "m" (result) // %2, %3, %4 ); break; case 3: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax (screenSelector) " mov %%ecx, %%eax \n" // mov eax, ecx - adjust for pixel size " add %%ecx, %%ecx \n" // add ecx, ecx - adjust for pixel size " add %%eax, %%ecx \n" // add ecx, eax - adjust for pixel size " add %%esi, %%edi \n" // add edi, esi // " add (%%esi,%%ebx,4), %%edi \n" // add edi, [esi + ebx*4] " add %%ecx, %%edi \n" // add edi, ecx " movzwl (%%edi),%%eax \n" // movzx edx,word ptr [edi] " xor %%eax, %%eax \n" " mov 2(%%edi), %%al \n" // mov al, [edi+2] " shl $16, %%eax \n" // shl eax, 16 " mov (%%edi), %%ax \n" // mov ax, [edi] " mov %%eax, %4 \n" // mov result, eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (screenSelector), "c" (x), "m" (result) // %2, %3, %4 ); break; case 2: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax (screenSelector) " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%ecx \n" // add ecx, ecx {adjust for pixel size} " add %%ecx, %%edi \n" // add edi, ecx " movzwl (%%edi),%%eax \n" // movzx edx,word ptr [edi] " mov %%eax, %4 \n" // mov result, eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (screenSelector), "c" (x), "m" (result) // %2, %3, %4 ); break; case 1: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax (screenSelector) " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx " movzbl (%%edi),%%eax \n" // movzx edx,byte ptr [edi] " mov %%eax, %4 \n" // mov result, eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (screenSelector), "c" (x), "m" (result) // %2, %3, %4 ); break; } // switch return result; } // ogDisplay_VESA::RawGetPixel void ogDisplay_VESA::RawSetPixel(uInt32 x, uInt32 y, uInt32 colour) { uInt32 newR, newG, newB, inverseA; uInt8 sR, sG, sB, sA; uInt8 dR, dG, dB; do { if (ogIsBlending()) { ogUnpack(colour, sR, sG, sB, sA); if (sA == 0) return; if (sA == 255) break; inverseA = 255 - sA; ogUnpack(RawGetPixel(x, y), dR, dG, dB); newR = (dR * inverseA + sR * sA) >> 8; newG = (dG * inverseA + sG * sA) >> 8; newB = (dB * inverseA + sB * sA) >> 8; colour = ogPack(newR, newG, newB, inverseA); } // if } while (false); switch (bytesPerPix) { case 4: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } " push %%ds \n" // push ds " mov %%dx, %%ds \n" // mov ds, dx " shl $2, %%ecx \n" // shl eax, 2 {adjust for pixel size} " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx // { Draw the pixel } " mov %%eax, (%%edi) \n" // mov [edi], eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), // %2, %3 "d" (screenSelector) // %4 ); break; case 3: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } // " add (%%esi,%%ebx,4),%%edi \n" // add edi, [esi + ebx * 4] " push %%ds \n" // push ds " mov %%dx, %%ds \n" // mov ds, dx " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx " add %%ecx, %%edi \n" // add edi, ecx {adjust for pixel size} " add %%ecx, %%edi \n" // add edi, ecx {adjust for pixel size} // { Draw the pixel } " mov %%ax, (%%edi) \n" // mov [edi], ax " shr $16, %%eax \n" // shr eax, 16 " mov %%al, 2(%%edi)\n" // mov [edi+2],al " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), // %2, %3 "d" (screenSelector) // %4 ); break; case 2: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } " push %%ds \n" // push ds " mov %%dx, %%ds \n" // mov ds, dx " add %%ecx, %%ecx \n" // add ecx, ecx {adjust for pixel size} " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx // { Draw the pixel } " mov %%ax, (%%edi) \n" // mov [edi], al " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), // %2, %3 "d" (screenSelector) // %4 ); break; case 1: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } // " add (%%esi,%%ebx,4), %%edi \n" // add edi, [esi + ebx * 4] " push %%ds \n" // push ds " mov %%dx, %%ds \n" // mov ds, dx " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx // { Draw the pixel } " mov %%al, (%%edi) \n" // mov [edi], al " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), // %2, %3 "d" (screenSelector) // %4 ); break; } // switch return; } // ogDisplay_VESA::RawSetPixel void ogDisplay_VESA::RawSetPixel(uInt32 x, uInt32 y, uInt8 r, uInt8 g, uInt8 b, uInt8 a) { uInt32 newR, newG, newB, inverseA; uInt8 dR, dG, dB; uInt32 colour; do { if (ogIsBlending()) { if (a == 0) return; if (a == 255) { colour = ogPack(r, g, b, a); break; } // if a == 255 inverseA = 255 - a; ogUnpack(RawGetPixel(x, y), dR, dG, dB); newR = (dR * inverseA + r * a) >> 8; newG = (dG * inverseA + g * a) >> 8; newB = (dB * inverseA + b * a) >> 8; colour = ogPack(newR, newG, newB, inverseA); } else colour = ogPack(r, g, b, a); } while (false); switch (bytesPerPix) { case 4: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } " push %%ds \n" // push ds " mov %%dx, %%ds \n" // mov ds, dx " shl $2, %%ecx \n" // shl eax, 2 {adjust for pixel size} " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx // { Draw the pixel } " mov %%eax, (%%edi) \n" // mov [edi], eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), // %2, %3 "d" (screenSelector) // %4 ); break; case 3: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } // " add (%%esi,%%ebx,4),%%edi \n" // add edi, [esi + ebx * 4] " push %%ds \n" // push ds " mov %%dx, %%ds \n" // mov ds, dx " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx " add %%ecx, %%edi \n" // add edi, ecx {adjust for pixel size} " add %%ecx, %%edi \n" // add edi, ecx {adjust for pixel size} // { Draw the pixel } " mov %%ax, (%%edi) \n" // mov [edi], ax " shr $16, %%eax \n" // shr eax, 16 " mov %%al, 2(%%edi)\n" // mov [edi+2],al " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), // %2, %3 "d" (screenSelector) // %4 ); break; case 2: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } " push %%ds \n" // push ds " mov %%dx, %%ds \n" // mov ds, dx " add %%ecx, %%ecx \n" // add ecx, ecx {adjust for pixel size} " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx // { Draw the pixel } " mov %%ax, (%%edi) \n" // mov [edi], al " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), // %2, %3 "d" (screenSelector) // %4 ); break; case 1: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } // " add (%%esi,%%ebx,4), %%edi \n" // add edi, [esi + ebx * 4] " push %%ds \n" // push ds " mov %%dx, %%ds \n" // mov ds, dx " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx // { Draw the pixel } " mov %%al, (%%edi) \n" // mov [edi], al " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), // %2, %3 "d" (screenSelector) // %4 ); break; } // switch return; } // ogDisplay_VESA::RawSetPixel bool ogDisplay_VESA::ogAvail(void) { return ( ((screenSelector != 0) || (buffer != NULL)) && (lineOfs != NULL)); } // ogDisplay_VESA::Avail void ogDisplay_VESA::GetModeInfo(uInt16 mode) { __dpmi_regs regs; memset(modeInfo, 0, sizeof(struct ogModeInfo)); memset(®s, 0, sizeof(regs)); dosmemput(modeInfo, sizeof(struct ogModeInfo), __tb); int ofs, seg; seg = __tb; // __tb is a buffer located in "dos memory". This buffer ofs = __tb; // is used because the vesa driver cannot acces memory // above 1 MB (your program is most likely to be located above 1MB). ofs &= 0xffff; // Make a real pointer (segment:offse = 16:16) seg &= 0xffff0000; // from the address of the buffer. seg >>= 4; regs.x.ax = 0x4f01; // Get the modeinfo of a certain vesa video mode, // this is a structure which contains. regs.x.cx = mode; // information needed by other functions below. regs.x.es = seg; regs.x.di = ofs; __dpmi_int(0x10, ®s); /* This info is located in dos memory, so it has to be moved to your * program's address space. */ dosmemget(__tb, sizeof(struct ogModeInfo), modeInfo); return; } // ogDisplay_VESA::GetModeInfo void ogDisplay_VESA::GetVESAInfo(void) { unsigned int seg, ofs; __dpmi_regs regs; if (NULL == VESAInfo) VESAInfo = new ogVESAInfo; if (NULL == VESAInfo) return; memset(VESAInfo, 0, sizeof(struct ogVESAInfo)); memset(®s, 0, sizeof(regs)); VESAInfo->VBESignature[0] = 'V'; // First off initialize the structure. VESAInfo->VBESignature[1] = 'B'; VESAInfo->VBESignature[2] = 'E'; VESAInfo->VBESignature[3] = '2'; /* Because VBE funtions operate in real mode, we first have to move the initialized structure to real-mode address space, so the structure can be filled by the vesa function in real mode. */ dosmemput(VESAInfo, sizeof(struct ogVESAInfo), __tb); seg = __tb; // Calculate real mode address of the buffer. ofs = __tb; ofs &= 0xffff; seg &= 0xffff0000; seg >>= 4; regs.x.ax = 0x4F00; regs.x.es = seg; regs.x.di = ofs; __dpmi_int(0x10, ®s); // Get vesa info. // Move the structure back to dosmemget(__tb, sizeof(struct ogVESAInfo), VESAInfo); VESAInfo->OEMStringPtr = (VESAInfo->OEMStringPtr & 0xFFFF) + ((VESAInfo->OEMStringPtr & 0xFFFF0000) >> 12); VESAInfo->OEMVendorNamePtr= (VESAInfo->OEMVendorNamePtr& 0xFFFF) + ((VESAInfo->OEMVendorNamePtr& 0xFFFF0000) >> 12); VESAInfo->OEMProductNamePtr= (VESAInfo->OEMProductNamePtr& 0xFFFF) + ((VESAInfo->OEMProductNamePtr& 0xFFFF0000) >> 12); VESAInfo->OEMProductRevPtr= (VESAInfo->OEMProductRevPtr& 0xFFFF) + ((VESAInfo->OEMProductRevPtr& 0xFFFF0000) >> 12); VESAInfo->videoModePtr = ((VESAInfo->videoModePtr & 0xFFFF0000) >> 12) + (VESAInfo->videoModePtr & 0xFFFF); return; } // ogDisplay_VESA::GetVESAInfo uInt16 ogDisplay_VESA::FindMode(uInt32 _xRes, uInt32 _yRes, uInt32 _BPP) { uInt16 mode; if ((_xRes == 320) && (_yRes == 200) && (_BPP == 8)) return 0x13; // if ((VESAInfo==NULL) || (VESAInfo->videoModePtr==NULL)) return 0; if (modeInfo == NULL) return 0; for (mode = 0x100; mode < 0x1FF; mode++) { GetModeInfo(mode); if ((modeInfo->xRes >= _xRes) && (modeInfo->yRes >= _yRes) && (modeInfo->bitsPerPixel == _BPP)) return mode; } return 0; } // ogDisplay_VESA::FindMode void ogDisplay_VESA::SetMode(uInt16 mode) { uInt32 size, count; __dpmi_meminfo mem_info; if (mode == 0x13) { xRes = 320; yRes = 200; maxX = 319; maxY = 199; BPP = 8; bytesPerPix = 1; redFieldPosition = 0; greenFieldPosition = 0; blueFieldPosition = 0; alphaFieldPosition = 0; redShifter = 0; greenShifter = 0; blueShifter = 0; alphaFieldPosition = 0; mem_info.address = 0xA0000; mem_info.size = 64000; size = 63999; buffer = NULL; __dpmi_physical_address_mapping(&mem_info); __dpmi_set_segment_base_address(screenSelector, mem_info.address); __dpmi_set_segment_limit(screenSelector, size); __dpmi_set_descriptor_access_rights(screenSelector, 0x40F3); } else { buffer = NULL; mode |= 0x4000; // attempt lfb GetModeInfo(mode); if (modeInfo->physBasePtr == 0) return; size = modeInfo->yRes*modeInfo->bytesPerLine; xRes = modeInfo->bytesPerLine; yRes = modeInfo->yRes; maxX = modeInfo->xRes-1; maxY = yRes-1; BPP = modeInfo->bitsPerPixel; bytesPerPix = (BPP + 7) >> 3; redFieldPosition = modeInfo->redFieldPosition; greenFieldPosition = modeInfo->greenFieldPosition; blueFieldPosition = modeInfo->blueFieldPosition; alphaFieldPosition = modeInfo->alphaFieldPosition; if (4 == bytesPerPix) { modeInfo->alphaMaskSize = 8; while ((alphaFieldPosition == redFieldPosition) || (alphaFieldPosition == greenFieldPosition) || (alphaFieldPosition == blueFieldPosition)) alphaFieldPosition += 8; } // if redShifter = 8-modeInfo->redMaskSize; greenShifter = 8-modeInfo->greenMaskSize; blueShifter = 8-modeInfo->blueMaskSize; alphaShifter = 8-modeInfo->alphaMaskSize; if (modeInfo->alphaMaskSize != 0) alphaMasker = ~(OG_MASKS[modeInfo->alphaMaskSize] << alphaFieldPosition); else alphaMasker = ~0; mem_info.address = modeInfo->physBasePtr; mem_info.size = size; size = ((size+4095) >> 12); __dpmi_physical_address_mapping(&mem_info); __dpmi_set_segment_base_address(screenSelector, mem_info.address); __dpmi_set_segment_limit(screenSelector,size); __dpmi_set_descriptor_access_rights(screenSelector, 0xC0F3); } // else owner = this; dataState = ogAliasing; inGraphics = true; if ((lineOfs != NULL) && (lSize != 0)) delete [] lineOfs; lSize = yRes*sizeof(uInt32); lineOfs = new uInt32[yRes];; if (lineOfs == NULL) return; lineOfs[0] = 0; for (count=1; count<yRes; count++) lineOfs[count] = lineOfs[count-1]+xRes; initVESAMode(mode); if (pal == NULL) pal = new ogRGBA8[256]; ogSetPalette(DEFAULT_PALETTE); if (1 == bytesPerPix) { pixFmtID = 0x08080808; } else { pixFmtID = (redFieldPosition) | (greenFieldPosition << 8) | (blueFieldPosition << 16) | (alphaFieldPosition << 24); } // else ogSetAntiAliasing(BPP > 8); // antiAlias=(BPP>8); if (BPP == 8) SetPal(); ogClear(ogPack(0, 0, 0)); return; } // ogDisplay_VESA::SetMode void ogDisplay_VESA::SetPal(void) { if (bytesPerPix != 1) return; outportb(0x3c8,0); for (uInt32 c = 0; c < 256; c++) { outportb(0x3c9, pal[c].red >> 2); outportb(0x3c9, pal[c].green >> 2); outportb(0x3c9, pal[c].blue >> 2); } // for return; } // ogDisplay_VESA::SetPal void ogDisplay_VESA::ogSetPalette(const ogRGBA8 newPal[256]) { ogSurface::ogSetPalette(newPal); SetPal(); return; } // ogDisplay_VESA::SetPalette; bool ogDisplay_VESA::ogAlias(ogSurface& src, uInt32 x1, uInt32 y1, uInt32 x2, uInt32 y2) { ogSetLastError(ogNoAliasing); return false; } // ogDisplay_VESA::Alias void ogDisplay_VESA::ogClear(uInt32 colour) { uInt32 height = 0; uInt32 xx, yy; uInt8 r, g, b, a; if (!ogAvail()) return; do { if (ogIsBlending()) { ogUnpack(colour, r, g, b, a); if (a == 0) return; if (a == 255) break; for (yy = 0; yy <= maxY; yy++) for (xx = 0; xx <= maxX; xx++) RawSetPixel(xx, yy, r, g, b, a); } // if } while (false); __asm__ __volatile__("cld\n"); switch (bytesPerPix) { case 4: __asm__ __volatile__( " push %%es \n" // push es " mov %6, %%ax \n" // mov ax, screenSelector " mov %%ax, %%es \n" // mov es, ax " add (%%esi), %%edi \n" // add edi, [esi] " mov %%ecx, %%esi \n" // mov esi, ecx " inc %%edx \n" // inc edx (maxX) " inc %%ebx \n" // inc ebx (maxY) " mov %5, %%eax \n" // mov eax, colour " mov %%edx, %%ecx \n" // mov ecx, edx " shl $2, %%ecx \n" // shl ecx, 2 " sub %%ecx, %%esi \n" // sub esi, ecx // adjust for pix size "loop32: \n" " mov %%edx, %%ecx \n" // mov ecx, edx " rep \n" " stosl \n" " add %%esi, %%edi \n" // add edi, esi " dec %%ebx \n" " jnz loop32 \n" " pop %%es \n" // pop es : : "D" (buffer), "S" (lineOfs), // %0, %1 "b" (maxY), "c" (xRes), "d" (maxX), // %2, %3, %4 "m" (colour), "m" (screenSelector) // %5, %6 ); break; case 3: __asm__ __volatile__( " push %%es \n" // push es " mov %7, %%ax \n" // mov ax, screenSelector " mov %%ax, %%es \n" // mov es, ax " add (%%esi), %%edi \n" // add edi, [esi] " mov %%ecx, %%esi \n" // mov esi, ecx " inc %%edx \n" // inc edx (maxX) " inc %%ebx \n" // inc ebx (maxY) " mov %5, %%eax \n" // mov eax, colour " sub %%edx, %%esi \n" // sub esi, edx // adjust for pix size " mov %%ebx, %6 \n" // mov height, ebx " sub %%edx, %%esi \n" // sub esi, edx // adjust for pix size " mov %%eax, %%ebx \n" // mov ebx, eax " sub %%edx, %%esi \n" // sub esi, edx // adjust for pix size " shr $16, %%ebx \n" // shr ebx, 16 "oloop24: \n" " mov %%edx, %%ecx \n" // mov ecx, edx "iloop24: \n" " mov %%ax,(%%edi) \n" // mov [edi],ax " movb %%bl,2(%%edi) \n" // mov [edi+2],bl " add $3, %%edi \n" // add edi, 3 " dec %%ecx \n" // dec ecx " jnz iloop24 \n" " add %%esi, %%edi \n" // add edi, esi " decl %6 \n" // dec height " jnz oloop24 \n" " pop %%es \n" // pop es : : "D" (buffer), "S" (lineOfs), // %0, %1 "b" (maxY), "c" (xRes), "d" (maxX), // %2, %3, %4 "m" (colour), "m" (height), // %5, %6 "m" (screenSelector) // %7 ); break; case 2: __asm__ __volatile__( " push %%es \n" // push es " mov %6, %%ax \n" // mov ax, screenSelector " mov %%ax, %%es \n" // mov es, ax " add (%%esi), %%edi \n" // add edi, [esi] " mov %%ecx, %%esi \n" // mov esi, ecx " inc %%edx \n" // inc edx (maxX) " inc %%ebx \n" // inc ebx (maxY) " sub %%edx, %%esi \n" // sub esi, edx " mov %5, %%eax \n" // mov eax, colour " sub %%edx, %%esi \n" // sub esi, edx // adjust for pix size " mov %%ax, %%cx \n" // mov cx, ax " shl $16, %%eax \n" // shl eax, 16 " mov %%cx, %%ax \n" // mov ax, cx "loop16: \n" " mov %%edx, %%ecx \n" // mov ecx, edx " shr $1, %%ecx \n" // shr ecx, 1 " rep \n" " stosl \n" " jnc noc16 \n" " stosw \n" "noc16: \n" " add %%esi, %%edi \n" // add edi, esi " dec %%ebx \n" " jnz loop16 \n" " pop %%es \n" : : "D" (buffer), "S" (lineOfs), // %0, %1 "b" (maxY), "c" (xRes), "d" (maxX), // %2, %3, %4 "m" (colour), "m" (screenSelector) // %5, %6 ); break; case 1: __asm__ __volatile__( " push %%es \n" // push es " mov %6, %%ax \n" // mov ax, screenSelector " mov %%ax, %%es \n" // mov es, ax " add (%%esi), %%edi \n" // add edi, [esi] " mov %%ecx, %%esi \n" // mov esi, ecx " inc %%edx \n" // inc edx (maxY) " inc %%ebx \n" // inc ebx (maxX) " mov %5, %%eax \n" // mov eax, colour " sub %%edx, %%esi \n" // sub esi, edx " mov %%al, %%ah \n" // mov ah, al " mov %%ax, %%cx \n" // mov cx, ax " shl $16, %%eax \n" // shl eax, 16 " mov %%cx, %%ax \n" // mov ax, cx "loop8: \n" " push %%edx \n" " mov %%edx, %%ecx \n" // mov ecx, edx " and $3, %%edx \n" // and edx, 3 " shr $2, %%ecx \n" // shr ecx, 2 " rep \n" " stosl \n" " mov %%edx, %%ecx \n" // mov ecx, edx " rep \n" " stosb \n" " pop %%edx \n" " add %%esi, %%edi \n" // add edi, esi " dec %%ebx \n" " jnz loop8 \n" " pop %%es \n" // pop es : : "D" (buffer), "S" (lineOfs), // %0, %1 "b" (maxY), "c" (xRes), "d" (maxX), // %2, %3, %4 "m" (colour), "m" (screenSelector) // %5, %6 ); break; } // switch return; } // ogDisplay_VESA::Clear void ogDisplay_VESA::ogCopyLineTo(uInt32 dx, uInt32 dy, const void * src, uInt32 size) { /* * ogCopyLineTo() * * Inputs: * * dx - Destination X of the target buffer * dy - Destination Y of the target buffer * src - buffer to copy * size - size in bytes *NOT* pixels * * Copies a run of pixels (of the same format) to (x,y) of a buffer * * This method is required because of the different implementations of * copying a run of pixels to a buffer * * WARNING!!! This does *NO* error checking. It is assumed that you've * done all of that. CopyLineTo and CopyLineFrom are the only * methods that don't check to make sure you're hosing things. Don't * use this method unless YOU KNOW WHAT YOU'RE DOING!!!!!!!!! */ movedata(_my_ds(),(uInt32)src, screenSelector,(uInt32)((uInt8*)buffer+(lineOfs[dy]+dx*bytesPerPix) ), size); return; } // ogSurface::ogCopyLineTo void ogDisplay_VESA::ogCopyLineFrom(uInt32 sx, uInt32 sy, void * dest, uInt32 size) { /* * CopyLineFrom() * * Inputs: * * sx - Source X of the target buffer * sy - Source Y of the target buffer * dest - where to put it * size - size in bytes *NOT* pixels * * Copies a run of pixels (of the same format) to (x,y) of a buffer * * This method is required because of the different implementations of * copying a run of pixels to a buffer * * WARNING!!! This does *NO* error checking. It is assumed that you've * done all of that. CopyLineTo and CopyLineFrom are the only * methods that don't check to make sure you're hosing things. Don't * use this method unless YOU KNOW WHAT YOU'RE DOING!!!!!!!!! */ movedata(screenSelector,(uInt32)((uInt8*)buffer+(lineOfs[sy]+sx*bytesPerPix ) ), _my_ds(),(uInt32)dest, size); return; } // ogDisplay_VESA::ogCopyLineFrom bool ogDisplay_VESA::ogCreate(uInt32 _xRes, uInt32 _yRes, ogPixelFmt _pixFormat) { uInt16 mode; mode = FindMode(_xRes, _yRes, _pixFormat.BPP); if ((mode == 0) && ((_pixFormat.BPP==24) || (_pixFormat.BPP==32))) { if (_pixFormat.BPP==24) _pixFormat.BPP=32; else _pixFormat.BPP=24; mode = FindMode(_xRes,_yRes,_pixFormat.BPP); } // if if (mode!=0) SetMode(mode); return (mode!=0); } // ogDisplay_VESA::ogCreate bool ogDisplay_VESA::ogClone(ogSurface& src) { ogSetLastError(ogNoCloning); return false; } // ogDisplay_VESA::ogClone void ogDisplay_VESA::ogCopyPalette(ogSurface& src) { ogSurface::ogCopyPalette(src); SetPal(); return; } // ogDisplay_VESA::ogCopyPalette uInt32 ogDisplay_VESA::ogGetPixel(int32 x, int32 y) { uInt32 result; if (!ogAvail()) return ogGetTransparentColor(); if (((uInt32)x>maxX) || ((uInt32)y>maxY)) return ogGetTransparentColor(); switch (bytesPerPix) { case 4: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax (screenSelector) " shl $2, %%ecx \n" // shl ecx, 2 {adjust for pixel size} // " add (%%esi,%%ebx,4), %%edi \n" // add edi, [esi + ebx*4] " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx " mov (%%edi),%%eax \n" // eax, dword ptr [edi] " mov %%eax, %4 \n" // mov result, eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (screenSelector), "c" (x), "m" (result) // %2, %3, %4 ); break; case 3: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax (screenSelector) " mov %%ecx, %%eax \n" // mov eax, ecx - adjust for pixel size " add %%ecx, %%ecx \n" // add ecx, ecx - adjust for pixel size " add %%eax, %%ecx \n" // add ecx, eax - adjust for pixel size " add %%esi, %%edi \n" // add edi, esi // " add (%%esi,%%ebx,4), %%edi \n" // add edi, [esi + ebx*4] " add %%ecx, %%edi \n" // add edi, ecx " movzwl (%%edi),%%eax \n" // movzx edx,word ptr [edi] " xor %%eax, %%eax \n" " mov 2(%%edi), %%al \n" // mov al, [edi+2] " shl $16, %%eax \n" // shl eax, 16 " mov (%%edi), %%ax \n" // mov ax, [edi] " mov %%eax, %4 \n" // mov result, eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (screenSelector), "c" (x), "m" (result) // %2, %3, %4 ); break; case 2: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax (screenSelector) " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%ecx \n" // add ecx, ecx {adjust for pixel size} " add %%ecx, %%edi \n" // add edi, ecx " movzwl (%%edi),%%eax \n" // movzx edx,word ptr [edi] " mov %%eax, %4 \n" // mov result, eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (screenSelector), "c" (x), "m" (result) // %2, %3, %4 ); break; case 1: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax (screenSelector) " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx " movzbl (%%edi),%%eax \n" // movzx edx,byte ptr [edi] " mov %%eax, %4 \n" // mov result, eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (screenSelector), "c" (x), "m" (result) // %2, %3, %4 ); break; } // switch return result; } // ogDisplay_VESA::ogGetPixel void * ogDisplay_VESA::ogGetPtr(uInt32 x, uInt32 y) { return NULL; } // ogDisplay_VESA::ogGetPtr void ogDisplay_VESA::ogHLine(int32 x1, int32 x2, int32 y, uInt32 colour) { int32 tmp; uInt8 r, g, b, a; if (!ogAvail()) return; if ((uInt32)y>maxY) return; if (x1 > x2) { tmp= x1; x1 = x2; x2 = tmp; } // if if (x1 < 0) x1 = 0; if (x2 > (int32)maxX) x2 = maxX; if (x2 < x1) return; if (ogIsBlending()) { ogUnpack(colour, r, g, b, a); if (a == 0) return; if (a == 255) { for (tmp = x1; tmp <= x2; tmp++) RawSetPixel(tmp, y, r, g, b, a); return; } // if a == 255 } // if blending __asm__ __volatile__("cld \n"); switch (bytesPerPix) { case 4: __asm__ __volatile__( " push %%es \n" // push es " mov %%dx, %%es \n" // mov es, dx " sub %%ebx, %%ecx \n" // sub ecx, ebx " add %%esi, %%edi \n" // add edi, esi " inc %%ecx \n" " shl $2, %%ebx \n" // shl ebx, 2 " add %%ebx, %%edi \n" // add edi, ebx " rep \n" " stosl \n" " pop %%es \n" // pop es : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (colour), "b" (x1), // %2, %3 "c" (x2), "d" (screenSelector) // %4, %5 ); break; case 3: __asm__ __volatile__( " push %%es \n" // push es " mov %%ax, %%es \n" // mov es, ax " mov %2, %%eax \n" " sub %%ebx, %%ecx \n" // sub ecx, ebx " add %%esi, %%edi \n" // add edi, esi " add %%ebx, %%ebx \n" // add ebx, ebx - pix size " inc %%ecx \n" // inc ecx " add %%edx, %%ebx \n" // add ebx, edx - pix size " add %%ebx, %%edi \n" // add edi, ebx " mov %%eax, %%ebx \n" // mov ebx, eax " shr $16, %%ebx \n" // shr ebx, 16 "hLlop24: \n" " mov %%ax, (%%edi) \n" // mov [edi], ax " mov %%bl, 2(%%edi)\n" // mov [edi+2], bl " add $3, %%edi \n" // add edi, 3 " dec %%ecx \n" // dec ecx " jnz hLlop24 \n" " pop %%es \n" // pop es : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "m" (colour), "b" (x1), // %2, %3 "c" (x2), "d" (x1), "a" (screenSelector) // %4, %5 ); break; case 2: __asm__ __volatile__( " push %%es \n" " mov %%dx, %%es \n" // mov es, dx " sub %%ebx, %%ecx \n" // sub ecx, ebx " add %%ebx, %%ebx \n" // add ebx, ebx - pix size " inc %%ecx \n" // inc ecx " add %%ebx, %%edi \n" // add edi, ebx " add %%esi, %%edi \n" // add edi, esi " xor %%edx, %%edx \n" // xor edx, edx " mov %%ax, %%dx \n" // mov dx, ax " shl $16, %%eax \n" // shl eax, 16 " add %%edx, %%eax \n" // add eax, edx " shr $1, %%ecx \n" // shr ecx, 1 " rep \n" " stosl \n" " jnc hLnoc16 \n" " stosw \n" "hLnoc16: \n" " pop %%es \n" : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (colour), "b" (x1), // %2, %3 "c" (x2), "d" (screenSelector) ); break; case 1: __asm__ __volatile__( " push %%es \n" // push es " mov %%dx, %%es \n" // mov es, dx " add %%ebx, %%edi \n" // add edi, ebx " add %%esi, %%edi \n" // add edi, esi " and $0xff, %%eax \n" // and eax, 0ffh " sub %%ebx, %%ecx \n" // sub ecx, ebx " mov %%al, %%ah \n" // mov ah, al " inc %%ecx \n" // inc ecx " mov %%eax, %%ebx \n" // mov ebx, eax " shl $16, %%ebx \n" // shl ebx, 16 " add %%ebx, %%eax \n" // add eax, ebx " mov %%ecx, %%edx \n" // mov edx, ecx " mov $4, %%ecx \n" // mov ecx, 4 " sub %%edi, %%ecx \n" // sub ecx, edi " and $3, %%ecx \n" // and ecx, 3 " sub %%ecx, %%edx \n" // sub edx, ecx " jle LEndBytes \n" " rep \n" " stosb \n" " mov %%edx, %%ecx \n" // mov ecx, edx " and $3, %%edx \n" // and edx, 3 " shr $2, %%ecx \n" // shr ecx, 2 " rep \n" " stosl \n" "LEndBytes: \n" " add %%edx, %%ecx \n" // add ecx, edx " rep \n" " stosb \n" " pop %%es \n" : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "a" (colour), "b" (x1), // %2, %3 "c" (x2), "d" (screenSelector) ); break; } // switch return; } // ogDisplay_VESA::ogHLine bool ogDisplay_VESA::ogLoadPalette(const char *palfile) { bool result; if ((result = ogSurface::ogLoadPalette(palfile))==true) SetPal(); return result; } // ogDisplay_VESA::ogLoadPalette void ogDisplay_VESA::ogSetPixel(int32 x, int32 y, uInt32 colour) { uInt32 newR, newG, newB, inverseA; uInt8 sR, sG, sB, sA; uInt8 dR, dG, dB; if (!ogAvail()) return; if (((uInt32)x > maxX) || ((uInt32)y > maxY)) return; do { if (ogIsBlending()) { ogUnpack(colour, sR, sG, sB, sA); if (sA == 0) return; if (sA == 255) break; inverseA = 255 - sA; ogUnpack(RawGetPixel(x, y), dR, dG, dB); newR = (dR * inverseA + sR * sA) >> 8; newG = (dG * inverseA + sG * sA) >> 8; newB = (dB * inverseA + sB * sA) >> 8; colour = ogPack(newR, newG, newB, inverseA); } // if } while (false); switch (bytesPerPix) { case 4: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } " push %%ds \n" // push ds " mov %4, %%dx \n" // mov dx, screenSelector " mov %%dx, %%ds \n" // mov ds, dx " shl $2, %%ecx \n" // shl eax, 2 {adjust for pixel size} " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx // { Draw the pixel } " mov %%eax, (%%edi)\n" // mov [edi], eax " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), "m" (screenSelector) // %2, %3, %4 ); break; case 3: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } " push %%ds \n" // push ds " mov %4, %%dx \n" // mov dx, screenSelector " mov %%dx, %%ds \n" // mov ds, dx " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx " add %%ecx, %%edi \n" // add edi, ecx {adjust for pixel size} " add %%ecx, %%edi \n" // add edi, ecx {adjust for pixel size} // { Draw the pixel } " mov %%ax, (%%edi) \n" // mov [edi], ax " shr $16, %%eax \n" // shr eax, 16 " mov %%al, 2(%%edi)\n" // mov [edi+2],al " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), "m" (screenSelector) // %2, %3, %4 ); break; case 2: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } " push %%ds \n" " mov %4, %%dx \n" " mov %%dx, %%ds \n" " add %%ecx, %%ecx \n" // add ecx, ecx {adjust for pixel size} " add %%esi, %%edi \n" // add edi, esi " mov %3, %%eax \n" // mov eax, colour " add %%ecx, %%edi \n" // add edi, ecx // { Draw the pixel } " mov %%ax, (%%edi) \n" // mov [edi], al " pop %%ds\n" : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), "m" (screenSelector) // %2, %3, %4 ); break; case 1: __asm__ __volatile__( // { Calculate offset, prepare the pixel to be drawn } " push %%ds \n" " mov %4, %%dx \n" " mov %%dx, %%ds \n" " add %%esi, %%edi \n" // add edi, esi " add %%ecx, %%edi \n" // add edi, ecx // { Draw the pixel } " mov %%al, (%%edi) \n" // mov [edi], al " pop %%ds\n" : : "D" (buffer), "S" (lineOfs[y]), // %0, %1 "c" (x), "a" (colour), "m" (screenSelector) // %2, %3, %4 ); break; } // switch return; } // ogDisplay_VESA::ogSetPixel void ogDisplay_VESA::ogSetPalette(uInt8 colour, uInt8 red, uInt8 green, uInt8 blue) { if (pal == NULL) return; ogSurface::ogSetPalette(colour,red,green,blue); outportb(0x3c8, colour); outportb(0x3c9, red >> 2); outportb(0x3c9, green >> 2); outportb(0x3c9, blue >> 2); return; } // ogDisplay_VESA::ogSetPalette void ogDisplay_VESA::ogSetPalette(uInt8 colour, uInt8 red, uInt8 green, uInt8 blue, uInt8 alpha) { if (pal == NULL) return; ogSurface::ogSetPalette(colour, red, green, blue, alpha); outportb(0x3c8, colour); outportb(0x3c9, red >> 2); outportb(0x3c9, green >> 2); outportb(0x3c9, blue >> 2); return; } // ogDisplay_VESA::ogSetPalette void ogDisplay_VESA::ogVFlip(void) { if (!ogAvail()) return; switch (bytesPerPix) { case 4: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax " add %%edi, %%esi \n" // add esi, edi "vf32lop: \n" " push %%esi \n" // push esi " push %%edi \n" // push edi "vf32lop2: \n" " mov (%%edi),%%eax \n" // mov eax, [edi] " mov (%%esi),%%ecx \n" // mov ecx, [esi] " mov %%eax,(%%esi) \n" // mov [esi], eax " mov %%ecx,(%%edi) \n" // mov [edi], ecx " add $4, %%edi \n" // add edi, 4 " sub $4, %%esi \n" // sub esi, 4 " cmp %%esi, %%edi \n" // cmp edi, esi " jbe vf32lop2 \n" " pop %%edi \n" // pop edi " pop %%esi \n" // pop esi " add %%ebx, %%esi \n" // add esi, ebx " add %%ebx, %%edi \n" // add edi, ebx " dec %%edx \n" " jnz vf32lop \n" " pop %%ds \n" // pop ds : : "D" ((char *)buffer+lineOfs[0]), "S" (maxX*4), // %0, %1 "b" (xRes), "d" (maxY+1), "a" (screenSelector) // %2, %3, %4 ); break; case 3: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax " add %%edi, %%esi \n" // add esi, edi "vf24lop: \n" " push %%esi \n" // push esi " push %%edi \n" // push edi "vf24lop2: \n" " mov (%%edi),%%ax \n" // mov ax, [edi] " mov 2(%%edi),%%dl \n" // mov dl, [edi+2] " mov (%%esi),%%cx \n" // mov cx, [esi] " mov 2(%%esi),%%dh \n" // mov dh, [esi+2] " mov %%ax,(%%esi) \n" // mov [esi], ax " mov %%dl,2(%%esi) \n" // mov [esi+2], dl " mov %%cx,(%%edi) \n" // mov [edi], cx " mov %%dh,2(%%edi) \n" // mov [edi+2], dh " add $3, %%edi \n" // add edi, 3 " sub $3, %%esi \n" // sub esi, 3 " cmp %%esi, %%edi \n" // cmp edi, esi " jbe vf24lop2 \n" " pop %%edi \n" // pop edi " pop %%esi \n" // pop esi " add %%ebx, %%esi \n" // add esi, ebx " add %%ebx, %%edi \n" // add edi, ebx " decl %3 \n" // dec height " jnz vf24lop \n" " pop %%ds \n" // pop ds : : "D" ((char *)buffer+lineOfs[0]), "S" (maxX*3), // %0, %1 "b" (xRes), "d" (maxY+1), "a" (screenSelector) // %2, %3, %4 ); break; case 2: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax " add %%edi, %%esi \n" // add esi, edi "vf16lop: \n" " push %%esi \n" // push esi " push %%edi \n" // push edi "vf16lop2: \n" " mov (%%edi),%%ax \n" // mov ax, [edi] " mov (%%esi),%%cx \n" // mov cx, [esi] " mov %%ax,(%%esi) \n" // mov [esi], ax " mov %%cx,(%%edi) \n" // mov [edi], cx " add $2, %%edi \n" // add edi, 2 " sub $2, %%esi \n" // sub esi, 2 " cmp %%esi, %%edi \n" // cmp edi, esi " jbe vf16lop2 \n" " pop %%edi \n" // pop edi " pop %%esi \n" // pop esi " add %%ebx, %%esi \n" // add esi, ebx " add %%ebx, %%edi \n" // add edi, ebx " dec %%edx \n" " jnz vf16lop \n" " pop %%ds \n" // pop ds : : "D" ((char *)buffer+lineOfs[0]), "S" (maxX*2), // %0, %1 "b" (xRes), "d" (maxY+1), "a" (screenSelector) // %2, %3, %4 ); break; case 1: __asm__ __volatile__( " push %%ds \n" // push ds " mov %%ax, %%ds \n" // mov ds, ax " add %%edi, %%esi \n" // add esi, edi "vf8lop: \n" " push %%esi \n" // push esi " push %%edi \n" // push edi "vf8lop2: \n" " mov (%%edi),%%al \n" // mov al, [edi] " mov (%%esi),%%ah \n" // mov ah, [esi] " mov %%al,(%%esi) \n" // mov [esi], al " mov %%ah,(%%edi) \n" // mov [edi], ah " inc %%edi \n" // inc edi " dec %%esi \n" // dec esi " cmp %%esi, %%edi \n" // cmp edi, esi " jbe vf8lop2 \n" " pop %%edi \n" // pop edi " pop %%esi \n" // pop esi " add %%ebx, %%esi \n" // add esi, ebx " add %%ebx, %%edi \n" // add edi, ebx " dec %%edx \n" " jnz vf8lop \n" " pop %%ds \n" // pop ds : : "D" ((char *)buffer+lineOfs[0]), "S" (maxX), // %0, %1 "b" (xRes), "d" (maxY+1), "a" (screenSelector) // %2, %3, %4 ); break; } // switch return; } // ogDisplay_VESA::ogVFlip void ogDisplay_VESA::ogVLine(int32 x, int32 y1, int32 y2, uInt32 colour) { int32 tmp; uInt8 r, g, b, a; if (!ogAvail()) return; if ((uInt32)x > maxX) return; if (y1 > y2) { tmp= y1; y1 = y2; y2 = tmp; } // if if (y1 < 0) y1 = 0; if (y2 > (int32)maxY) y2 = maxY; if (y2 < y1) return; if (ogIsBlending()) { ogUnpack(colour, r, g, b, a); if (a == 0) return; if (a != 255) { for (tmp = y1; tmp <= y2; tmp++) RawSetPixel(x, tmp, r, g, b, a); return; } // if } // if blending switch (bytesPerPix) { case 4: __asm__ __volatile__( " push %%ds \n" // push ds " add %%esi, %%edi \n" // add edi, esi " shl $2, %%ebx \n" // shl ebx, 2 - pix size " mov %7, %%si \n" // mov si, screenSelector " mov %%si, %%ds \n" // mov ds, si " mov %6, %%esi \n" // mov esi, y1 " sub %%esi, %%ecx \n" // sub ecx, esi " add %%ebx, %%edi \n" // add edi, ebx " mov %2, %%eax \n" // mov eax, colour " inc %%ecx \n" // inc ecx "vLlop32: \n" " mov %%eax, (%%edi)\n" // mov [edi], eax " add %%edx, %%edi \n" // add edi, edx " dec %%ecx \n" // dec ecx " jnz vLlop32 \n" " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y1]), // %0, %1 "m" (colour), "b" (x), // %2, %3 "c" (y2), "d" (xRes), // %4, %5 "m" (y1), "m" (screenSelector) // %6, %7 ); break; case 3: __asm__ __volatile__( " push %%ds \n" // push ds " add %%esi, %%edi \n" // add edi, esi " mov %%ebx, %%esi \n" // mov esi, ebx - pix size " add %%ebx, %%ebx \n" // add ebx, ebx - pix size " add %%esi, %%ebx \n" // add ebx, esi - pix size " mov %7, %%si \n" // mov si, screenSelector " mov %%si, %%ds \n" // mov ds, si " mov %6, %%esi \n" // mov esi, y1 " sub %%esi, %%ecx \n" // sub ecx, esi " add %%ebx, %%edi \n" // add edi, ebx " mov %2, %%eax \n" // mov eax, colour " inc %%ecx \n" // inc ecx " mov %%eax, %%ebx \n" // mov ebx, eax " shr $16, %%ebx \n" // shr ebx, 16 "vLlop24: \n" " mov %%ax, (%%edi) \n" // mov [edi], eax " mov %%bl, 2(%%edi)\n" // mov [edi+2], bl " add %%edx, %%edi \n" // add edi, edx " dec %%ecx \n" // dec ecx " jnz vLlop24 \n" " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y1]), // %0, %1 "m" (colour), "b" (x), // %2, %3 "c" (y2), "d" (xRes), // %4, %5 "m" (y1), "m" (screenSelector) // %6, %7 ); break; case 2: __asm__ __volatile__( " push %%ds \n" // push ds " add %%esi, %%edi \n" // add edi, esi " add %%ebx, %%ebx \n" // add ebx, ebx - pix size " mov %7, %%si \n" // mov si, screenSelector " mov %%si, %%ds \n" // mov ds, si " mov %6, %%esi \n" // mov esi, y1 " sub %%esi, %%ecx \n" // sub ecx, esi " add %%ebx, %%edi \n" // add edi, ebx " mov %2, %%eax \n" // mov eax, colour " inc %%ecx \n" // inc ecx "vLlop16: \n" " mov %%ax, (%%edi) \n" // mov [edi], ax " add %%edx, %%edi \n" // add edi, edx " dec %%ecx \n" // dec ecx " jnz vLlop16 \n" " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y1]), // %0, %1 "m" (colour), "b" (x), // %2, %3 "c" (y2), "d" (xRes), // %4, %5 "m" (y1), "m" (screenSelector) // %6, %7 ); break; case 1: __asm__ __volatile__( " push %%ds \n" // push ds " add %%esi, %%edi \n" // add edi, esi " mov %7, %%si \n" // mov si, screenSelector " mov %%si, %%ds \n" // mov ds, si " mov %6, %%esi \n" // mov esi, y1 " sub %%esi, %%ecx \n" // sub ecx, esi " add %%ebx, %%edi \n" // add edi, ebx " mov %2, %%eax \n" // mov eax, colour " inc %%ecx \n" // inc ecx "vLlop8: \n" " mov %%al, (%%edi) \n" // mov [edi], al " add %%edx, %%edi \n" // add edi, edx " dec %%ecx \n" // dec ecx " jnz vLlop8 \n" " pop %%ds \n" // pop ds : : "D" (buffer), "S" (lineOfs[y1]), // %0, %1 "m" (colour), "b" (x), // %2, %3 "c" (y2), "d" (xRes), // %4, %5 "m" (y1), "m" (screenSelector) // %6, %7 ); break; } // switch return; } // ogDisplay_VESA::ogVLine ogDisplay_VESA::~ogDisplay_VESA(void) { __dpmi_regs regs; if (VESAInfo != NULL) delete VESAInfo; if (modeInfo != NULL) delete modeInfo; if (attributes != NULL) delete attributes; if (inGraphics) { regs.x.ax = 3; __dpmi_int(0x10, ®s); } // if inGraphics return; }