417
edits
(Added info about Nick Sonneveld's IDA databases.) |
(Fixed a typo. Hadn't put & in front of some code where it should have been.) |
||
(13 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
In the original PC AGI interpreter v2.936 the engine holds the color and priority/control | In the original PC AGI interpreter v2.936 the engine holds the color and priority/control | ||
line information for each pixel in a | line information for each pixel in a 160x168 byte buffer. The color data for each pixel | ||
is held in the byte's lower 4 bits and the priority/control line data is held in the upper | is held in the byte's lower 4 bits and the priority/control line data is held in the upper | ||
4 bits. | 4 bits. | ||
AGI256 extends this | AGI256 extends this 160x168 byte buffer to a 320x168 byte buffer so that the 256-color | ||
data is held in the right | data is held in the right 160x168 half of the buffer and the original style 16-color and | ||
priority/control line information is held in the left | priority/control line information is held in the left 160x168 half of the buffer. | ||
When loading 256-color picture resource with the unknown170 command | |||
the picture is loaded straight into the right 160x168 half of the 320x168 memory buffer. | |||
Cel blitting routine is modified so that when sprite data would normally be written | |||
to a position (x, y) in the 16-color buffer (i.e. the left 160x168 half) it's actually | |||
written to the same position (x, y) but in the 256-color buffer (i.e. the right 160x168 half). | |||
==Used external info== | ==Used external info== | ||
Line 14: | Line 21: | ||
Thanks Nick. You can check out the disassemblies if you're interested at the | Thanks Nick. You can check out the disassemblies if you're interested at the | ||
[http://www.agidev.com/projects/nagi/dev.php AGI Development Site]. | [http://www.agidev.com/projects/nagi/dev.php AGI Development Site]. | ||
==Differences between AGI v2.936 and AGI256== | |||
Added files in AGI256: | |||
* AGIGRAF.OVL | |||
* AGIOBJS.OVL | |||
Differences in the following files: | |||
* AGI.EXE | |||
* AGIDATA.OVL | |||
===Reverse engineered C version of AGI256's AGIOBJS.OVL=== | |||
Things may be wrong, misleading etc. Caveat emptor. | |||
This is the cel blitting routine from AGIOBJS.OVL. | |||
<pre> | |||
struct blitStruct { | |||
uint8 b0; | |||
uint8 b1; | |||
uint8 notEgo; // Sort of a guess based on variable's usage, may also be dontUpdateEgoVisibility or something like that | |||
uint16 xPos; | |||
uint16 yPos; // Is this named correctly? | |||
uint8 b7; | |||
uint8 b8; | |||
uint8 b9; | |||
uint8 b10; | |||
uint8 b11; | |||
uint8 b12; | |||
uint8 b13; | |||
uint8 b14; | |||
uint8 b15; | |||
struct celStruct *celPtr; // Offset into segment DS really, 16 bits | |||
uint8 b18; | |||
uint8 b19; | |||
uint8 b20; | |||
uint8 b21; | |||
uint8 b22; | |||
uint8 b23; | |||
uint8 b24; | |||
uint8 b25; | |||
uint8 b26; | |||
uint8 b27; | |||
uint8 b28; | |||
uint8 b29; | |||
uint8 b30; | |||
uint8 b31; | |||
uint8 b32; | |||
uint8 b33; | |||
uint8 b34; | |||
uint8 b35; | |||
uint8 celPriority; | |||
}; | |||
struct celStruct { | |||
uint8 width; // This is a guess | |||
uint8 height; | |||
union { | |||
uint8 flags; // Uses values from enum flagsEnum | |||
uint8 transparentColor; // Only lower 4 bits | |||
}; | |||
uint8 rleData[?]; | |||
}; | |||
enum flagsEnum { | |||
F_MIRROR = 1 << 7; | |||
}; | |||
#define _WIDTH 160 | |||
#define _HEIGHT 168 | |||
uint16 screenOffset(uint8 x, uint8 y) { | |||
return y * (_WIDTH * 2) + x; | |||
} | |||
void agi256BlitCel(struct blitStruct *s) { | |||
uint8 *pic = &agi256PicSeg[0]; | |||
const uint16 endPos = (_WIDTH * 2) * (_HEIGHT - 1); // I would have put (((_WIDTH * 2) * (_HEIGHT - 1)) - _WIDTH) here | |||
bool celInvisible = true; | |||
uint8 height = s->celPtr->height; | |||
uint8 celPriority = s->celPriority; | |||
if (s->celPtr->flags & F_MIRROR) // Test for mirroring | |||
blitMirrorCell(); | |||
uint8 *rleData = s->celPtr->rleData; | |||
uint16 pos = screenOffset(s->xPos, s->yPos - height + 1); | |||
uint8 transparentColor = s->celPtr->transparentColor; | |||
do { | |||
uint16 oldPos = pos; | |||
while (uint8 rleByte = *(rleData++)) { // rleByte != 0 | |||
uint8 runColor = rleByte >> 4; | |||
uint8 runLength = rleByte & 0x0f; | |||
if (runColor == transparentColor) { // Check for transparency | |||
pos += runLength; | |||
} else do { | |||
uint8 pixelPriority = pic[pos] >> 4; // Read pixel's priority/control line info | |||
if (pixelPriority < 3) { | |||
pixelPriority = 0; | |||
for (uint16 ySearchPos = pos + _WIDTH * 2; | |||
ySearchPos < endPos && (pixelPriority = pic[ySearchPos] >> 4) < 3; | |||
ySearchPos += _WIDTH * 2); | |||
} | |||
if (celPriority >= pixelPriority) { | |||
pic[pos + _WIDTH] = runColor; | |||
celInvisible = false; | |||
} | |||
pos++; | |||
} while (--runLength > 0); | |||
} | |||
pos = oldPos + _WIDTH * 2; | |||
} while (--height > 0); | |||
if (!s->notEgo) | |||
setFlag(f1, celInvisible); | |||
} | |||
</pre> | |||
===Differences between AGI v2.936's AGIDATA.OVL and AGI256's AGIDATA.OVL=== | |||
<pre> | |||
dseg:0x08C5: dw offset CmdUnknown170 | |||
</pre> | |||
Unknown170 command's subroutine's location has been | |||
changed from the original 0x2726 to hacked 0x9975. | |||
0x9975 goes beyond what is in AGI.EXE so | |||
it goes to point to the AGIGRAF.OVL's functions. | |||
AGIGRAF.OVL is loaded into cseg:0x9800 so taking | |||
away the displacement we get 0x9975-0x9800 = 0x175. | |||
See the AGIGRAF.OVL disassembly for more details | |||
about the function that this points to. | |||
===Disassembly of AGIGRAF.OVL=== | |||
<pre> | |||
codeseg:9800 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9800 | |||
codeseg:9800 ; AGIGRAF.OVL starts here at 0x9800 | |||
codeseg:9800 ; Attributes: thunk | |||
codeseg:9800 | |||
codeseg:9800 j_AG_setGrafMode proc near ; CODE XREF: sub_5528+14�p | |||
codeseg:9800 jmp AG_setGrafMode ; In Sonneveld's Agi2917.idb there was j_EGAGrafMode here. | |||
codeseg:9800 j_AG_setGrafMode endp ; | |||
codeseg:9800 ; Sets 320x200 256 color video mode (Mode 13h), | |||
codeseg:9800 ; sets ds:[videoOfs] to 0xA000 and | |||
codeseg:9800 ; clears first 64 KiB of video memory with zeroes. | |||
codeseg:9803 | |||
codeseg:9803 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9803 | |||
codeseg:9803 ; Attributes: thunk | |||
codeseg:9803 | |||
codeseg:9803 j_AG_setTextMode proc near ; CODE XREF: cmd_text_screen_106+1E�p | |||
codeseg:9803 jmp AG_setTextMode ; In Sonneveld's Agi2917.idb there was j_EGATextMode here. | |||
codeseg:9803 j_AG_setTextMode endp ; | |||
codeseg:9803 ; Sets 40x25 16 color text mode, | |||
codeseg:9803 ; enables background intensity (Colors 8-15), | |||
codeseg:9803 ; sets some cursor stuff and | |||
codeseg:9803 ; clears the text screen using ds:[textClrAttr] attribute. | |||
codeseg:9806 | |||
codeseg:9806 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9806 | |||
codeseg:9806 ; Attributes: thunk | |||
codeseg:9806 | |||
codeseg:9806 j_AG_agi256ShowPic proc near ; CODE XREF: sub_78CB+18�p | |||
codeseg:9806 jmp AG_agi256ShowPic ; In Sonneveld's Agi2917.idb there was j_EGAShowPic here. | |||
codeseg:9806 j_AG_agi256ShowPic endp ; | |||
codeseg:9806 ; Sets the 320x200 256 color video mode, | |||
codeseg:9806 ; clears screen etc (Look at setVideoMode) | |||
codeseg:9806 ; and calls an unknown function. | |||
codeseg:9809 | |||
codeseg:9809 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9809 | |||
codeseg:9809 ; Attributes: thunk | |||
codeseg:9809 | |||
codeseg:9809 j_AG_emptyFunc4 proc near | |||
codeseg:9809 jmp AG_emptyFunc4 ; In Sonneveld's Agi2917.idb there was an empty function here too. | |||
codeseg:9809 j_AG_emptyFunc4 endp ; | |||
codeseg:9809 ; Does nothing. Don't know what functionality | |||
codeseg:9809 ; would have been here in the original AGI interpreter. | |||
codeseg:9809 ; Maybe something to do with other than EGA graphics adapters? | |||
codeseg:980C | |||
codeseg:980C ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:980C | |||
codeseg:980C ; Attributes: thunk | |||
codeseg:980C | |||
codeseg:980C j_AG_agi256PutBlock proc near ; CODE XREF: _Pic_Show+40�p | |||
codeseg:980C ; sub_560C+E�p ... | |||
codeseg:980C jmp AG_agi256PutBlock ; In Sonneveld's Agi2917.idb there was j_EGAPutBlock here. | |||
codeseg:980C j_AG_agi256PutBlock endp ; | |||
codeseg:980C ; Shows an AGI 256 picture (Puts it into video memory). | |||
codeseg:980C ; Uses x2 horizontal stretching. | |||
codeseg:980F | |||
codeseg:980F ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:980F | |||
codeseg:980F ; Attributes: thunk | |||
codeseg:980F | |||
codeseg:980F j_AG_calcHeightLUT proc near ; CODE XREF: sub_5528+E�p | |||
codeseg:980F jmp AG_calcHeightLUT ; In Sonneveld's Agi2917.idb there was j_EGAInit here. | |||
codeseg:980F j_AG_calcHeightLUT endp ; | |||
codeseg:980F ; Precalculates table for Y*320 values (0 <= y < 200) | |||
codeseg:9812 | |||
codeseg:9812 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9812 | |||
codeseg:9812 ; Attributes: thunk | |||
codeseg:9812 | |||
codeseg:9812 j_AG_agi256FilledRect proc near ; CODE XREF: _BoxNBorder+11�p | |||
codeseg:9812 ; _BoxNBorder+28�p ... | |||
codeseg:9812 jmp AG_agi256FilledRect ; In Sonneveld's Agi2917.idb there was j_EGAFilledRect here. | |||
codeseg:9812 j_AG_agi256FilledRect endp ; | |||
codeseg:9812 ; Fills a solid rectangle in video memory with a given fill color. | |||
codeseg:9812 ; Inputs: | |||
codeseg:9812 ; DL = fill color | |||
codeseg:9812 ; AL = yPos ?? (More like last row) | |||
codeseg:9812 ; AH = xPos | |||
codeseg:9812 ; BH = yLen | |||
codeseg:9812 ; BL = xLen | |||
codeseg:9815 | |||
codeseg:9815 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9815 | |||
codeseg:9815 ; In Sonneveld's Agi2917.idb there was j_EGAGrafMode here. | |||
codeseg:9815 ; | |||
codeseg:9815 ; Sets 320x200 256 color video mode (Mode 13h), | |||
codeseg:9815 ; sets ds:[videoOfs] to 0xA000 and | |||
codeseg:9815 ; clears first 64 KiB of video memory with zeroes. | |||
codeseg:9815 | |||
codeseg:9815 AG_setGrafMode proc near ; CODE XREF: j_AG_setGrafMode�j | |||
codeseg:9815 ; AG_agi256ShowPic+8�p | |||
codeseg:9815 mov ax, 13h | |||
codeseg:9818 int 10h ; - VIDEO - SET VIDEO MODE | |||
codeseg:9818 ; AL = mode | |||
codeseg:981A mov bx, 0A000h | |||
codeseg:981D mov videoSeg, bx | |||
codeseg:9821 nop | |||
codeseg:9822 nop | |||
codeseg:9823 nop | |||
codeseg:9824 nop | |||
codeseg:9825 nop | |||
codeseg:9826 nop | |||
codeseg:9827 push es | |||
codeseg:9828 mov es, videoSeg | |||
codeseg:982C xor ax, ax | |||
codeseg:982E mov di, ax | |||
codeseg:9830 mov cx, 8000h | |||
codeseg:9833 repe stosw | |||
codeseg:9835 pop es | |||
codeseg:9836 retn | |||
codeseg:9836 AG_setGrafMode endp | |||
codeseg:9836 | |||
codeseg:9837 | |||
codeseg:9837 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9837 | |||
codeseg:9837 ; In Sonneveld's Agi2917.idb there was j_EGATextMode here. | |||
codeseg:9837 ; | |||
codeseg:9837 ; Sets 40x25 16 color text mode, | |||
codeseg:9837 ; enables background intensity (Colors 8-15), | |||
codeseg:9837 ; sets some cursor stuff and | |||
codeseg:9837 ; clears the text screen using ds:[textClrAttr] attribute. | |||
codeseg:9837 ; Attributes: bp-based frame | |||
codeseg:9837 | |||
codeseg:9837 AG_setTextMode proc near ; CODE XREF: j_AG_setTextMode�j | |||
codeseg:9837 push si | |||
codeseg:9838 push di | |||
codeseg:9839 push bp | |||
codeseg:983A mov bp, sp | |||
codeseg:983C sub sp, 2 | |||
codeseg:983F mov ax, 1 ; Set 40x25 16 color text (AH = 0, AL = 1) | |||
codeseg:9842 int 10h ; - VIDEO - SET VIDEO MODE | |||
codeseg:9842 ; AL = mode | |||
codeseg:9844 mov ax, 1003h | |||
codeseg:9847 xor bx, bx ; Disable blinking i.e. enable background intensity (Colors 8-15). | |||
codeseg:9849 int 10h ; - VIDEO - TOGGLE INTENSITY/BLINKING BIT (Jr, PS, TANDY 1000, EGA, VGA) | |||
codeseg:9849 ; BL = 00h enable background intensity | |||
codeseg:9849 ; = 01h enable blink | |||
codeseg:984B mov cx, 3000h | |||
codeseg:984E mov ah, 1 | |||
codeseg:9850 int 10h ; - VIDEO - SET CURSOR CHARACTERISTICS | |||
codeseg:9850 ; CH bits 0-4 = start line for cursor in character cell | |||
codeseg:9850 ; bits 5-6 = blink attribute | |||
codeseg:9850 ; CL bits 0-4 = end line for cursor in character cell | |||
codeseg:9852 xor bh, bh | |||
codeseg:9854 xor dx, dx | |||
codeseg:9856 mov ah, 2 | |||
codeseg:9858 int 10h ; - VIDEO - SET CURSOR POSITION | |||
codeseg:9858 ; DH,DL = row, column (0,0 = upper left) | |||
codeseg:9858 ; BH = page number | |||
codeseg:985A mov bh, byte ptr textClrAttr | |||
codeseg:985E xor al, al ; AL = 0 = blank whole window | |||
codeseg:9860 xor cx, cx ; CH = row 0 | |||
codeseg:9860 ; CL = column 0 | |||
codeseg:9862 mov dx, 1827h ; DH = row 24 | |||
codeseg:9862 ; DL = column 39 | |||
codeseg:9865 mov ah, 6 | |||
codeseg:9867 int 10h ; - VIDEO - SCROLL PAGE UP | |||
codeseg:9867 ; AL = number of lines to scroll window (0 = blank whole window) | |||
codeseg:9867 ; BH = attributes to be used on blanked lines | |||
codeseg:9867 ; CH,CL = row,column of upper left corner of window to scroll | |||
codeseg:9867 ; DH,DL = row,column of lower right corner of window | |||
codeseg:9869 add sp, 2 | |||
codeseg:986C pop bp | |||
codeseg:986D pop di | |||
codeseg:986E pop si | |||
codeseg:986F retn | |||
codeseg:986F AG_setTextMode endp | |||
codeseg:986F | |||
codeseg:9870 | |||
codeseg:9870 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9870 | |||
codeseg:9870 ; In Sonneveld's Agi2917.idb there was j_EGAShowPic here. | |||
codeseg:9870 ; | |||
codeseg:9870 ; Sets the 320x200 256 color video mode, | |||
codeseg:9870 ; clears screen etc (Look at setVideoMode) | |||
codeseg:9870 ; and calls an unknown function. | |||
codeseg:9870 ; Attributes: bp-based frame | |||
codeseg:9870 | |||
codeseg:9870 AG_agi256ShowPic proc near ; CODE XREF: j_AG_agi256ShowPic�j | |||
codeseg:9870 push si | |||
codeseg:9871 push di | |||
codeseg:9872 push bp | |||
codeseg:9873 mov bp, sp | |||
codeseg:9875 sub sp, 2 | |||
codeseg:9878 call AG_setGrafMode ; In Sonneveld's Agi2917.idb there was j_EGAGrafMode here. | |||
codeseg:9878 ; | |||
codeseg:9878 ; Sets 320x200 256 color video mode (Mode 13h), | |||
codeseg:9878 ; sets ds:[videoOfs] to 0xA000 and | |||
codeseg:9878 ; clears first 64 KiB of video memory with zeroes. | |||
codeseg:987B call _Pic_Show ; Was _Pic_Show in Agi2917.idb | |||
codeseg:987E add sp, 2 | |||
codeseg:9881 pop bp | |||
codeseg:9882 pop di | |||
codeseg:9883 pop si | |||
codeseg:9884 retn | |||
codeseg:9884 AG_agi256ShowPic endp | |||
codeseg:9884 | |||
codeseg:9885 | |||
codeseg:9885 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9885 | |||
codeseg:9885 ; In Sonneveld's Agi2917.idb there was an empty function here too. | |||
codeseg:9885 ; | |||
codeseg:9885 ; Does nothing. Don't know what functionality | |||
codeseg:9885 ; would have been here in the original AGI interpreter. | |||
codeseg:9885 ; Maybe something to do with other than EGA graphics adapters? | |||
codeseg:9885 | |||
codeseg:9885 AG_emptyFunc4 proc near ; CODE XREF: j_AG_emptyFunc4�j | |||
codeseg:9885 retn | |||
codeseg:9885 AG_emptyFunc4 endp | |||
codeseg:9885 | |||
codeseg:9886 | |||
codeseg:9886 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9886 | |||
codeseg:9886 ; In Sonneveld's Agi2917.idb there was j_EGAPutBlock here. | |||
codeseg:9886 ; | |||
codeseg:9886 ; Shows an AGI 256 picture (Puts it into video memory). | |||
codeseg:9886 ; Uses x2 horizontal stretching. | |||
codeseg:9886 | |||
codeseg:9886 AG_agi256PutBlock proc near ; CODE XREF: j_AG_agi256PutBlock�j | |||
codeseg:9886 | |||
codeseg:9886 xPos = ah ; Use case: 0 | |||
codeseg:9886 yPos = al ; Use case: 167 (Is this register named correctly??) | |||
codeseg:9886 xLen = bl ; Use case: 160 | |||
codeseg:9886 yLen = bh ; Use case: 168 | |||
codeseg:9886 | |||
codeseg:9886 test xPos, 1 | |||
codeseg:9889 jz xPosEven | |||
codeseg:988B dec xPos ; xPos wasn't even, so make it even by decreasing it by one | |||
codeseg:988D inc xLen | |||
codeseg:988F | |||
codeseg:988F xPosEven: ; CODE XREF: AG_agi256PutBlock+3�j | |||
codeseg:988F inc xLen | |||
codeseg:9891 and xLen, 11111110b ; Make xLen even | |||
codeseg:9894 mov cx, bx | |||
codeseg:9896 sub yPos, yLen | |||
codeseg:9898 | |||
codeseg:9898 loc_9898: ; CODE XREF: sub_5257+14�p | |||
codeseg:9898 ; _Pic_Show+35�p ... | |||
codeseg:9898 inc yPos ; Some Hercules code used to be at codeseg:0x9899 | |||
codeseg:9898 ; but isn't anymore. It's shouldn't be called in AGI256 at all. | |||
codeseg:989A | |||
codeseg:989A loc_989A: ; Calculates the screen offset for given coordinate? Video or AGI screen offset? | |||
codeseg:989A call screenOffset ; DI = AL * 320 + AH | |||
codeseg:989A ; (Destroys BX contents (Returns with BH = 0, BL = AH)) | |||
codeseg:989A ; | |||
codeseg:989A ; Maybe not named quite correctly? | |||
codeseg:989D mov si, di | |||
codeseg:989F call agiToScreenCoords ; Calculates (baseY+Y)*320 + X*2 | |||
codeseg:989F ; | |||
codeseg:989F ; Inputs: AL = Y, AH = X | |||
codeseg:989F ; Reads from DS:[byte_B389] = baseY | |||
codeseg:989F ; (Actually reads baseY as a word, but uses it like | |||
codeseg:989F ; it can't overflow to over 8 bits when adding Y to it) | |||
codeseg:989F ; Returns: DI = heightLUT[baseY+Y] + X*2 = (baseY+Y)*320 + X*2 | |||
codeseg:989F ; (Side-effects: BH = 0, BL = AH = X) | |||
codeseg:98A2 jmp AG_convCoord ; Input: CX | |||
codeseg:98A2 AG_agi256PutBlock endp ; BH = CH = Y | |||
codeseg:98A2 ; BL = CL/2 = X / 2 | |||
codeseg:98A2 ; SI += 160 (Go to right half of the 320x168 area) | |||
codeseg:98A2 ; goto AG_stretchToScreen | |||
codeseg:98A5 ; --------------------------------------------------------------------------- | |||
codeseg:98A5 nop | |||
codeseg:98A6 | |||
codeseg:98A6 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:98A6 | |||
codeseg:98A6 ; Copies data from agi256 picture segment to video memory with x2 horizontal stretching. | |||
codeseg:98A6 ; Both source and destination buffers use a stride/pitch of 320 bytes. | |||
codeseg:98A6 ; Inputs: | |||
codeseg:98A6 ; BL = xLen | |||
codeseg:98A6 ; BH = yLen | |||
codeseg:98A6 ; SI = srcOffset | |||
codeseg:98A6 ; DI = destOffset | |||
codeseg:98A6 | |||
codeseg:98A6 AG_stretchToScreen proc near ; CODE XREF: AG_convCoord+8�j | |||
codeseg:98A6 | |||
codeseg:98A6 xLen = bl | |||
codeseg:98A6 yLen = bh | |||
codeseg:98A6 xCounterHi = ch | |||
codeseg:98A6 xCounterLo = cl | |||
codeseg:98A6 | |||
codeseg:98A6 push ds | |||
codeseg:98A7 push es | |||
codeseg:98A8 mov es, videoSeg | |||
codeseg:98AC mov ds, agi256PicSeg | |||
codeseg:98B0 | |||
codeseg:98B0 yLoop: ; CODE XREF: AG_stretchToScreen+2E�j | |||
codeseg:98B0 xor xCounterHi, xCounterHi ; Stretches source AGI 256 picture into video memory | |||
codeseg:98B0 ; (Doubles the width of the picture, so 160 becomes 320 etc). | |||
codeseg:98B0 ; BL = source width (Probably 160)? | |||
codeseg:98B0 ; BH = source height (Probably 168)? | |||
codeseg:98B2 mov xCounterLo, xLen | |||
codeseg:98B4 push di | |||
codeseg:98B5 push si | |||
codeseg:98B6 | |||
codeseg:98B6 xLoop: ; CODE XREF: AG_stretchToScreen+1E�j | |||
codeseg:98B6 lodsw ; Read word from AGI 256 picture buffer | |||
codeseg:98B7 nop | |||
codeseg:98B8 nop | |||
codeseg:98B9 nop | |||
codeseg:98BA mov dl, ah | |||
codeseg:98BC mov ah, al | |||
codeseg:98BE stosw ; Put first read byte twice into video memory | |||
codeseg:98BF mov al, dl | |||
codeseg:98C1 mov ah, al | |||
codeseg:98C3 stosw ; Put second read byte twice into video memory | |||
codeseg:98C4 loop xLoop ; Loop xCounterLo times (xCounterHi is zero) | |||
codeseg:98C6 pop si | |||
codeseg:98C7 pop di | |||
codeseg:98C8 dec yLen | |||
codeseg:98CA jz end | |||
codeseg:98CC add si, 320 ; Figuring that source image width is 160 and still its pointer | |||
codeseg:98CC ; is added by 320 rather than 160 when going to the next line... | |||
codeseg:98CC ; it might make sense if the priorities are 160 wide per row as well | |||
codeseg:98CC ; and a row of picture data is always followed by a row of priority data. | |||
codeseg:98D0 add di, 320 | |||
codeseg:98D4 jmp short yLoop ; Stretches source AGI 256 picture into video memory | |||
codeseg:98D4 ; (Doubles the width of the picture, so 160 becomes 320 etc). | |||
codeseg:98D4 ; BL = source width (Probably 160)? | |||
codeseg:98D4 ; BH = source height (Probably 168)? | |||
codeseg:98D6 ; --------------------------------------------------------------------------- | |||
codeseg:98D6 | |||
codeseg:98D6 end: ; CODE XREF: AG_stretchToScreen+24�j | |||
codeseg:98D6 pop es | |||
codeseg:98D7 pop ds | |||
codeseg:98D8 retn | |||
codeseg:98D8 AG_stretchToScreen endp | |||
codeseg:98D8 | |||
codeseg:98D9 | |||
codeseg:98D9 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:98D9 | |||
codeseg:98D9 ; In Sonneveld's Agi2917.idb there was j_EGAFilledRect here. | |||
codeseg:98D9 ; | |||
codeseg:98D9 ; Fills a solid rectangle in video memory with a given fill color. | |||
codeseg:98D9 ; Inputs: | |||
codeseg:98D9 ; DL = fill color | |||
codeseg:98D9 ; AL = yPos ?? (More like last row) | |||
codeseg:98D9 ; AH = xPos | |||
codeseg:98D9 ; BH = yLen | |||
codeseg:98D9 ; BL = xLen | |||
codeseg:98D9 | |||
codeseg:98D9 AG_agi256FilledRect proc near ; CODE XREF: j_AG_agi256FilledRect�j | |||
codeseg:98D9 | |||
codeseg:98D9 yLen = bh | |||
codeseg:98D9 xLen = bl | |||
codeseg:98D9 | |||
codeseg:98D9 push es | |||
codeseg:98DA mov es, videoSeg | |||
codeseg:98DE mov dh, dl | |||
codeseg:98E0 sub al, yLen | |||
codeseg:98E2 inc al | |||
codeseg:98E4 mov cx, bx | |||
codeseg:98E6 call agiToScreenCoords ; Calculates (baseY+Y)*320 + X*2 | |||
codeseg:98E6 ; | |||
codeseg:98E6 ; Inputs: AL = Y, AH = X | |||
codeseg:98E6 ; Reads from DS:[byte_B389] = baseY | |||
codeseg:98E6 ; (Actually reads baseY as a word, but uses it like | |||
codeseg:98E6 ; it can't overflow to over 8 bits when adding Y to it) | |||
codeseg:98E6 ; Returns: DI = heightLUT[baseY+Y] + X*2 = (baseY+Y)*320 + X*2 | |||
codeseg:98E6 ; (Side-effects: BH = 0, BL = AH = X) | |||
codeseg:98E9 mov bx, cx | |||
codeseg:98EB mov ax, dx | |||
codeseg:98ED mov dx, 320 | |||
codeseg:98F0 xor ch, ch | |||
codeseg:98F2 sub dx, cx | |||
codeseg:98F4 sub dx, cx | |||
codeseg:98F6 | |||
codeseg:98F6 xLoop: ; CODE XREF: AG_agi256FilledRect+27�j | |||
codeseg:98F6 mov cl, xLen | |||
codeseg:98F8 repe stosw | |||
codeseg:98FA dec yLen | |||
codeseg:98FC jz end | |||
codeseg:98FE add di, dx | |||
codeseg:9900 jmp short xLoop | |||
codeseg:9902 ; --------------------------------------------------------------------------- | |||
codeseg:9902 | |||
codeseg:9902 end: ; CODE XREF: AG_agi256FilledRect+23�j | |||
codeseg:9902 pop es | |||
codeseg:9903 retn | |||
codeseg:9903 AG_agi256FilledRect endp | |||
codeseg:9903 | |||
codeseg:9904 | |||
codeseg:9904 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9904 | |||
codeseg:9904 ; In Sonneveld's Agi2917.idb there was j_EGAInit here. | |||
codeseg:9904 ; | |||
codeseg:9904 ; Precalculates table for Y*320 values (0 <= y < 200) | |||
codeseg:9904 | |||
codeseg:9904 AG_calcHeightLUT proc near ; CODE XREF: j_AG_calcHeightLUT�j | |||
codeseg:9904 lea di, ds:heightLUT | |||
codeseg:9908 mov ax, 0 | |||
codeseg:990B mov dx, 200 | |||
codeseg:990E | |||
codeseg:990E mulWidthLoop: ; CODE XREF: AG_calcHeightLUT+F�j | |||
codeseg:990E stosw | |||
codeseg:990F add ax, 320 | |||
codeseg:9912 dec dx | |||
codeseg:9913 jnz mulWidthLoop | |||
codeseg:9915 retn | |||
codeseg:9915 AG_calcHeightLUT endp | |||
codeseg:9915 | |||
codeseg:9916 | |||
codeseg:9916 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9916 | |||
codeseg:9916 ; To me this seems to blink the colors on the screen | |||
codeseg:9916 ; syncronized to some event. | |||
codeseg:9916 ; | |||
codeseg:9916 ; setPalette(uint16 cx) { | |||
codeseg:9916 ; read 16 colors from video card to ds:[palette] | |||
codeseg:9916 ; | |||
codeseg:9916 ; for (int z = 0; z < cx; z++) { | |||
codeseg:9916 ; for (int y = 0; y < 20; y++) { | |||
codeseg:9916 ; for (int i=0; i < 16*3; i++) { | |||
codeseg:9916 ; ds:palette[i] ^= 0xff; // Inverts palette | |||
codeseg:9916 ; } | |||
codeseg:9916 ; write 16 colors to video card from ds:[palette] | |||
codeseg:9916 ; wait for word_A139 to change (Loop until it does) | |||
codeseg:9916 ; } | |||
codeseg:9916 ; } | |||
codeseg:9916 ; } | |||
codeseg:9916 | |||
codeseg:9916 AG_blinkScreen proc near ; CODE XREF: cmd_shake_screen_110+2F�p | |||
codeseg:9916 push bx | |||
codeseg:9917 push si | |||
codeseg:9918 push di | |||
codeseg:9919 push es | |||
codeseg:991A push dx | |||
codeseg:991B mov ax, ds | |||
codeseg:991D mov es, ax | |||
codeseg:991F push cx | |||
codeseg:9920 mov dx, offset palette | |||
codeseg:9923 xor bx, bx | |||
codeseg:9925 mov cx, 16 ; Read first 16 colors from video card | |||
codeseg:9928 mov al, 17h | |||
codeseg:992A mov ah, 10h | |||
codeseg:992C int 10h ; - VIDEO - READ BLOCK OF DAC REGISTERS (EGA, VGA/MCGA) | |||
codeseg:992C ; BX = starting palette register, CX = number of palette registers to read | |||
codeseg:992C ; ES:DX -> buffer (3 * CX bytes in size) | |||
codeseg:992C ; Return: CX number of red, green and blue triples in buffer | |||
codeseg:992E pop cx | |||
codeseg:992F | |||
codeseg:992F outerLoop: ; CODE XREF: AG_blinkScreen+4C�j | |||
codeseg:992F push cx ; At first run, CX's value at function start is pushed | |||
codeseg:9930 mov cx, 20 | |||
codeseg:9933 | |||
codeseg:9933 loop20Times: ; CODE XREF: AG_blinkScreen+49�j | |||
codeseg:9933 push cx ; At first run, 20 is pushed | |||
codeseg:9934 mov bx, 47 ; 48/3 = 16 (Dealing with triples here) | |||
codeseg:9937 mov al, 0FFh | |||
codeseg:9939 | |||
codeseg:9939 invertPalette: ; CODE XREF: AG_blinkScreen+28�j | |||
codeseg:9939 xor palette[bx], al ; Inverts 16 colors in palette and writes them to video card DAC | |||
codeseg:993D dec bx | |||
codeseg:993E jns invertPalette ; Inverts 16 colors in palette and writes them to video card DAC | |||
codeseg:9940 mov dx, offset palette | |||
codeseg:9943 xor bx, bx | |||
codeseg:9945 mov cx, 16 | |||
codeseg:9948 mov al, 12h | |||
codeseg:994A mov ah, 10h | |||
codeseg:994C int 10h ; - VIDEO - SET BLOCK OF DAC REGISTERS (EGA, VGA/MCGA) | |||
codeseg:994C ; BX = starting color register, CX = number of registers to set | |||
codeseg:994C ; ES:DX -> table of 3*CX bytes where each 3 byte group represents one | |||
codeseg:994C ; byte each of red, green and blue (0-63) | |||
codeseg:994E mov cx, 1 | |||
codeseg:9951 | |||
codeseg:9951 neverLoopsHere: ; CODE XREF: AG_blinkScreen+46�j | |||
codeseg:9951 mov bx, word_A139 | |||
codeseg:9955 | |||
codeseg:9955 waitForChange: ; CODE XREF: AG_blinkScreen+43�j | |||
codeseg:9955 cmp bx, word_A139 | |||
codeseg:9959 jz waitForChange | |||
codeseg:995B dec cx | |||
codeseg:995C jnz neverLoopsHere ; This seems to never loop, so why is it here at all? | |||
codeseg:995E pop cx | |||
codeseg:995F loop loop20Times ; At first run, 20 is pushed | |||
codeseg:9961 pop cx | |||
codeseg:9962 loop outerLoop ; At first run, CX's value at function start is pushed | |||
codeseg:9964 pop dx | |||
codeseg:9965 pop es | |||
codeseg:9966 pop di | |||
codeseg:9967 pop si | |||
codeseg:9968 pop bx | |||
codeseg:9969 retn | |||
codeseg:9969 AG_blinkScreen endp | |||
codeseg:9969 | |||
codeseg:996A | |||
codeseg:996A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:996A | |||
codeseg:996A ; Input: CX | |||
codeseg:996A ; BH = CH = Y | |||
codeseg:996A ; BL = CL/2 = X / 2 | |||
codeseg:996A ; SI += 160 (Go to right half of the 320x168 area) | |||
codeseg:996A ; goto AG_stretchToScreen | |||
codeseg:996A | |||
codeseg:996A AG_convCoord proc near ; CODE XREF: AG_agi256PutBlock+1C�j | |||
codeseg:996A mov bx, cx | |||
codeseg:996C shr bl, 1 | |||
codeseg:996E add si, 160 | |||
codeseg:9972 jmp AG_stretchToScreen ; Copies data from agi256 picture segment to video memory with x2 horizontal stretching. | |||
codeseg:9972 AG_convCoord endp ; Both source and destination buffers use a stride/pitch of 320 bytes. | |||
codeseg:9972 ; Inputs: | |||
codeseg:9972 ; BL = xLen | |||
codeseg:9972 ; BH = yLen | |||
codeseg:9972 ; SI = srcOffset | |||
codeseg:9972 ; DI = destOffset | |||
codeseg:9975 | |||
codeseg:9975 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9975 | |||
codeseg:9975 ; Command unknown 170 | |||
codeseg:9975 ; | |||
codeseg:9975 ; In AGIDATA.OVL at offset 0x08C5 there's | |||
codeseg:9975 ; dw offset CmdUnknown170 and now | |||
codeseg:9975 ; it's 0x9975 which points to 0x9800 + 0x175, | |||
codeseg:9975 ; so it's 0x175 in this file. So it points to this function. | |||
codeseg:9975 ; | |||
codeseg:9975 ; uint16 *cmdUnknown170(uint16 *varNum) { | |||
codeseg:9975 ; uint8 var = agiVar[*varNum]; | |||
codeseg:9975 ; AG_readAgi256Pic(var); | |||
codeseg:9975 ; return ++varNum; | |||
codeseg:9975 ; } | |||
codeseg:9975 ; Attributes: bp-based frame | |||
codeseg:9975 | |||
codeseg:9975 AG_cmd_set_simple_170 proc near ; DATA XREF: dataseg:08C5�o | |||
codeseg:9975 | |||
codeseg:9975 varNum = word ptr 8 | |||
codeseg:9975 | |||
codeseg:9975 push si | |||
codeseg:9976 push di | |||
codeseg:9977 push bp | |||
codeseg:9978 mov bp, sp | |||
codeseg:997A mov di, [bp+varNum] ; DI = varNum | |||
codeseg:997D inc [bp+varNum] ; varNum++ | |||
codeseg:9980 mov al, [di] ; AL = [DS:DI] = [old varNum] | |||
codeseg:9982 sub ah, ah ; AX = zero_extend(AL) | |||
codeseg:9984 mov di, ax ; DI = [old varNum] | |||
codeseg:9986 mov al, agiVar[di] ; AL = agiVar[[old varNum]] | |||
codeseg:998A sub ah, ah | |||
codeseg:998C push ax | |||
codeseg:998D call AG_readAgi256Pic ; Reads an AGI 256 picture with the given number to | |||
codeseg:998D ; agi256PicSeg so that the picture is a 160x168 picture in | |||
codeseg:998D ; a 320x168 area, but in the right half of it | |||
codeseg:998D ; (i.e. 168 <= x < 320 and 0 <= y < 168) | |||
codeseg:9990 add sp, 2 | |||
codeseg:9993 mov ax, [bp+varNum] | |||
codeseg:9996 pop bp | |||
codeseg:9997 pop di | |||
codeseg:9998 pop si | |||
codeseg:9999 retn | |||
codeseg:9999 AG_cmd_set_simple_170 endp | |||
codeseg:9999 | |||
codeseg:999A | |||
codeseg:999A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:999A | |||
codeseg:999A ; Reads an AGI 256 picture with the given number to | |||
codeseg:999A ; agi256PicSeg so that the picture is a 160x168 picture in | |||
codeseg:999A ; a 320x168 area, but in the right half of it | |||
codeseg:999A ; (i.e. 168 <= x < 320 and 0 <= y < 168) | |||
codeseg:999A ; Attributes: bp-based frame | |||
codeseg:999A | |||
codeseg:999A AG_readAgi256Pic proc near ; CODE XREF: AG_cmd_set_simple_170+18�p | |||
codeseg:999A | |||
codeseg:999A picNum = word ptr 4 | |||
codeseg:999A | |||
codeseg:999A push bp | |||
codeseg:999B mov bp, sp | |||
codeseg:999D jmp jumpOverData | |||
codeseg:999D ; --------------------------------------------------------------------------- | |||
codeseg:99A0 aPicdir db 'PICDIR',0 | |||
codeseg:99A7 aVol_0 db 'VOL.0',0 | |||
codeseg:99AD tempBuf db 3 dup(0F0h) | |||
codeseg:99B0 ; --------------------------------------------------------------------------- | |||
codeseg:99B0 | |||
codeseg:99B0 jumpOverData: ; CODE XREF: AG_readAgi256Pic+3�j | |||
codeseg:99B0 push ds | |||
codeseg:99B1 mov cx, cs | |||
codeseg:99B3 mov ds, cx | |||
codeseg:99B5 assume ds:codeseg | |||
codeseg:99B5 call $+3 | |||
codeseg:99B8 | |||
codeseg:99B8 loc_99B8: ; CODE XREF: cmd_shake_screen_110+17�p | |||
codeseg:99B8 pop dx ; At first run, if called from 0x99B5 | |||
codeseg:99B8 ; DX = IP from the stack, which in turn is 0x99B8 | |||
codeseg:99B8 ; as it was the IP for the next instruction as call $+3 at 0x99B5 was made. | |||
codeseg:99B9 sub dx, 18h ; Subtract 0x18 from given value. | |||
codeseg:99B9 ; On first run it's 0x99B8 - 0x18 = 0x99A0 = offset "PICDIR" | |||
codeseg:99BC mov ax, 3D00h | |||
codeseg:99BF int 21h ; DOS - 2+ - OPEN DISK FILE WITH HANDLE | |||
codeseg:99BF ; DS:DX -> ASCIZ filename | |||
codeseg:99BF ; AL = access mode | |||
codeseg:99BF ; 0 - read | |||
codeseg:99C1 jnb fileOpenSuccess ; JNB = JNC | |||
codeseg:99C1 ; AX = file handle if CF not set, | |||
codeseg:99C1 ; AX = error code if CF is set | |||
codeseg:99C3 | |||
codeseg:99C3 error: ; CODE XREF: AG_readAgi256Pic+3D�j | |||
codeseg:99C3 ; AG_readAgi256Pic+4D�j ... | |||
codeseg:99C3 pop ds | |||
codeseg:99C4 assume ds:dataseg | |||
codeseg:99C4 retn | |||
codeseg:99C5 ; --------------------------------------------------------------------------- | |||
codeseg:99C5 | |||
codeseg:99C5 fileOpenSuccess: ; CODE XREF: AG_readAgi256Pic+27�j | |||
codeseg:99C5 mov bx, ax ; BX = AX = file handle of the picture directory file | |||
codeseg:99C7 mov dx, [bp+picNum] | |||
codeseg:99CA mov al, 3 | |||
codeseg:99CC mul dl ; AX = AL*DL = DL*3 = picNum*3 | |||
codeseg:99CE mov dx, ax ; DX = AX = picNum*3 | |||
codeseg:99D0 xor cx, cx ; Seek to position picNum*3 from beginning of file | |||
codeseg:99D2 mov ax, 4200h ; Inputs: BX = file handle, | |||
codeseg:99D2 ; CX = 16-bit MSB of bytes to move, | |||
codeseg:99D2 ; DX = 16-bit LSB of bytes to move | |||
codeseg:99D2 ; Returns: | |||
codeseg:99D2 ; DX:AX = new pointer location if CF not set | |||
codeseg:99D5 int 21h ; DOS - 2+ - MOVE FILE READ/WRITE POINTER (LSEEK) | |||
codeseg:99D5 ; AL = method: offset from beginning of file | |||
codeseg:99D7 jb error ; JC error | |||
codeseg:99D9 call $+3 | |||
codeseg:99DC pop dx | |||
codeseg:99DD sub dx, 2Fh ; '/' ; If called from 0x99D9 then after this subtraction | |||
codeseg:99DD ; DX will be 0x99DC - 0x2F = 0x99AD = offset tempBuf | |||
codeseg:99E0 mov cx, 3 ; Read three bytes from position picNum*3 | |||
codeseg:99E3 mov ah, 3Fh | |||
codeseg:99E5 int 21h ; DOS - 2+ - READ FROM FILE WITH HANDLE | |||
codeseg:99E5 ; BX = file handle, CX = number of bytes to read | |||
codeseg:99E5 ; DS:DX -> buffer | |||
codeseg:99E7 jb error | |||
codeseg:99E9 mov ah, 3Eh | |||
codeseg:99EB int 21h ; DOS - 2+ - CLOSE A FILE WITH HANDLE | |||
codeseg:99EB ; BX = file handle | |||
codeseg:99ED mov di, dx | |||
codeseg:99EF mov al, [di] | |||
codeseg:99F1 shr al, 4 ; AL = tempBuf[0]/16 | |||
codeseg:99F4 sub di, 2 | |||
codeseg:99F7 add [di], al ; Add tempBuf[0]/16 to "VOL.0" string's suffix (i.e. '0') | |||
codeseg:99F7 ; so that it may become "VOL.0" - "VOL.9". | |||
codeseg:99F9 sub dx, 6 ; DX = offset aVol_0 | |||
codeseg:99FC mov ax, 3D00h ; Open correct volume file (Some of "VOL.0" to "VOL.9") | |||
codeseg:99FF int 21h ; DOS - 2+ - OPEN DISK FILE WITH HANDLE | |||
codeseg:99FF ; DS:DX -> ASCIZ filename | |||
codeseg:99FF ; AL = access mode | |||
codeseg:99FF ; 0 - read | |||
codeseg:9A01 jb error | |||
codeseg:9A03 mov bx, ax ; BX = AX = file handle of the volume file | |||
codeseg:9A05 mov di, dx | |||
codeseg:9A07 add di, 6 ; DI = offset tempBuf | |||
codeseg:9A0A xor ch, ch | |||
codeseg:9A0C mov cl, [di] | |||
codeseg:9A0E and cl, 0Fh ; CL = tempBuf[0] % 16 | |||
codeseg:9A11 inc di | |||
codeseg:9A12 mov dh, [di] ; DH = tempBuf[1] | |||
codeseg:9A14 inc di | |||
codeseg:9A15 mov dl, [di] ; DL = tempBuf[2] | |||
codeseg:9A17 mov ax, 4200h ; Inputs: BX = file handle, | |||
codeseg:9A17 ; CX = 16-bit MSB of bytes to move, | |||
codeseg:9A17 ; DX = 16-bit LSB of bytes to move | |||
codeseg:9A17 ; Returns: | |||
codeseg:9A17 ; DX:AX = new pointer location if CF not set | |||
codeseg:9A1A int 21h ; DOS - 2+ - MOVE FILE READ/WRITE POINTER (LSEEK) | |||
codeseg:9A1A ; AL = method: offset from beginning of file | |||
codeseg:9A1C jb error | |||
codeseg:9A1E mov ax, 4201h | |||
codeseg:9A21 xor cx, cx | |||
codeseg:9A23 mov dx, 5 ; Move 5 bytes onwards from current seeking location | |||
codeseg:9A26 int 21h ; DOS - 2+ - MOVE FILE READ/WRITE POINTER (LSEEK) | |||
codeseg:9A26 ; AL = method: offset from present location | |||
codeseg:9A28 jb error | |||
codeseg:9A2A pop ds | |||
codeseg:9A2B push ds | |||
codeseg:9A2C mov dx, agi256PicSeg | |||
codeseg:9A30 mov ds, dx | |||
codeseg:9A32 mov dx, 160 ; Start reading to agi256PicSeg:[160] | |||
codeseg:9A35 mov cx, 168 | |||
codeseg:9A38 | |||
codeseg:9A38 readRow: ; CODE XREF: AG_readAgi256Pic+AB�j | |||
codeseg:9A38 push cx ; Read 168 rows of 160 bytes each. | |||
codeseg:9A39 mov cx, 160 | |||
codeseg:9A3C mov ah, 3Fh | |||
codeseg:9A3E int 21h ; DOS - 2+ - READ FROM FILE WITH HANDLE | |||
codeseg:9A3E ; BX = file handle, CX = number of bytes to read | |||
codeseg:9A3E ; DS:DX -> buffer | |||
codeseg:9A40 add dx, 320 ; Go to next row by adding 320 to destination pointer | |||
codeseg:9A44 pop cx | |||
codeseg:9A45 loop readRow ; Read 168 rows of 160 bytes each. | |||
codeseg:9A47 mov ah, 3Eh | |||
codeseg:9A49 int 21h ; DOS - 2+ - CLOSE A FILE WITH HANDLE | |||
codeseg:9A49 ; BX = file handle | |||
codeseg:9A4B pop ds | |||
codeseg:9A4C pop bp | |||
codeseg:9A4D retn | |||
codeseg:9A4D AG_readAgi256Pic endp | |||
codeseg:9A4D | |||
codeseg:9A4E ; --------------------------------------------------------------------------- | |||
codeseg:9A4E | |||
codeseg:9A4E loc_9A4E: | |||
codeseg:9A4E nop | |||
codeseg:9A4F | |||
codeseg:9A4F ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9A4F | |||
codeseg:9A4F ; Sets and/or clears current pixel bits | |||
codeseg:9A4F ; AL = ES:[DI] = PIXEL | |||
codeseg:9A4F ; (PIXEL |= BH) &= BL | |||
codeseg:9A4F | |||
codeseg:9A4F AG_setClrCurrPixel proc near ; CODE XREF: _SBuffXLine+2A�p | |||
codeseg:9A4F ; _SBuffYLine+3C�p ... | |||
codeseg:9A4F mov al, es:[di] | |||
codeseg:9A52 or al, bh | |||
codeseg:9A54 and al, bl | |||
codeseg:9A56 mov es:[di], al | |||
codeseg:9A59 retn | |||
codeseg:9A59 AG_setClrCurrPixel endp | |||
codeseg:9A59 | |||
codeseg:9A5A | |||
codeseg:9A5A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9A5A | |||
codeseg:9A5A ; Was _WindowLineClr in Sonneveld's Agi2917.idb | |||
codeseg:9A5A ; | |||
codeseg:9A5A ; Clears first 8 rows (320*8 bytes) of video memory | |||
codeseg:9A5A ; with white pixels (Color 15). | |||
codeseg:9A5A | |||
codeseg:9A5A AG_setWhiteMenuBar proc near ; CODE XREF: _StatLineWrite+1A�p | |||
codeseg:9A5A ; sub_93D1+1C�p | |||
codeseg:9A5A push cx | |||
codeseg:9A5B push es | |||
codeseg:9A5C push di | |||
codeseg:9A5D push ax | |||
codeseg:9A5E mov ax, 0A000h | |||
codeseg:9A61 mov es, ax | |||
codeseg:9A63 assume es:nothing | |||
codeseg:9A63 xor di, di | |||
codeseg:9A65 mov ax, 0F0Fh | |||
codeseg:9A68 mov cx, (320*8)/2 | |||
codeseg:9A6B repe stosw | |||
codeseg:9A6D pop ax | |||
codeseg:9A6E pop di | |||
codeseg:9A6F pop es | |||
codeseg:9A70 assume es:dataseg | |||
codeseg:9A70 pop cx | |||
codeseg:9A71 retn | |||
codeseg:9A71 AG_setWhiteMenuBar endp | |||
codeseg:9A71 | |||
codeseg:9A71 ; --------------------------------------------------------------------------- | |||
codeseg:9A72 byte_9A72 db 33Eh dup(0) | |||
</pre> | |||
===Disassembly of AGIOBJS.OVL=== | |||
<pre> | |||
codeseg:9DB0 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9DB0 | |||
codeseg:9DB0 ; AGIOBJS.OVL starts here at 0x9DB0 | |||
codeseg:9DB0 ; Attributes: thunk | |||
codeseg:9DB0 | |||
codeseg:9DB0 j_AO_agi256_saveArea proc near ; CODE XREF: sub_45E+15�p | |||
codeseg:9DB0 ; sub_5EDB+E4�p | |||
codeseg:9DB0 jmp AO_agi256_saveArea ; savearea(struct Sprite *s) { | |||
codeseg:9DB0 j_AO_agi256_saveArea endp ; int srcOffset = screenOffset(s->xPos, s->yPos); | |||
codeseg:9DB0 ; uint8 *src = &agi256PicSeg[srcOffset + 160]; | |||
codeseg:9DB0 ; for (int y = 0; y < s->ySize; y++) | |||
codeseg:9DB0 ; memcpy(s->buffer + s->xSize * y, src + 320 * y, s->xSize); | |||
codeseg:9DB0 ; } | |||
codeseg:9DB3 | |||
codeseg:9DB3 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9DB3 | |||
codeseg:9DB3 ; Attributes: thunk | |||
codeseg:9DB3 | |||
codeseg:9DB3 j_AO_agi256_restoreArea proc near ; CODE XREF: sub_307+13�p | |||
codeseg:9DB3 ; sub_5EDB+121�p | |||
codeseg:9DB3 jmp AO_agi256_restoreArea ; restoreArea(struct Sprite *s) { | |||
codeseg:9DB3 j_AO_agi256_restoreArea endp ; int destOffset = screenOffset(s->xPos, s->yPos); | |||
codeseg:9DB3 ; uint8 *dest = &agi256PicSeg[destOffset + 160]; | |||
codeseg:9DB3 ; for (int y = 0; y < s->ySize; y++) | |||
codeseg:9DB3 ; memcpy(dest + 320 * y, s->buffer + s->xSize * y, s->xSize); | |||
codeseg:9DB3 ; } | |||
codeseg:9DB6 | |||
codeseg:9DB6 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9DB6 | |||
codeseg:9DB6 ; Attributes: thunk | |||
codeseg:9DB6 | |||
codeseg:9DB6 j_AO_agi256_blit proc near ; CODE XREF: sub_45E+1E�p | |||
codeseg:9DB6 ; sub_57CF+22�p ... | |||
codeseg:9DB6 jmp AO_agi256_blit | |||
codeseg:9DB6 j_AO_agi256_blit endp | |||
codeseg:9DB6 | |||
codeseg:9DB9 | |||
codeseg:9DB9 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9DB9 | |||
codeseg:9DB9 ; savearea(struct Sprite *s) { | |||
codeseg:9DB9 ; int srcOffset = screenOffset(s->xPos, s->yPos); | |||
codeseg:9DB9 ; uint8 *src = &agi256PicSeg[srcOffset + 160]; | |||
codeseg:9DB9 ; for (int y = 0; y < s->ySize; y++) | |||
codeseg:9DB9 ; memcpy(s->buffer + s->xSize * y, src + 320 * y, s->xSize); | |||
codeseg:9DB9 ; } | |||
codeseg:9DB9 ; Attributes: bp-based frame | |||
codeseg:9DB9 | |||
codeseg:9DB9 AO_agi256_saveArea proc near ; CODE XREF: j_AO_agi256_saveArea�j | |||
codeseg:9DB9 | |||
codeseg:9DB9 spritePtr = word ptr 8 | |||
codeseg:9DB9 | |||
codeseg:9DB9 push si | |||
codeseg:9DBA push di | |||
codeseg:9DBB push bp | |||
codeseg:9DBC mov bp, sp | |||
codeseg:9DBE sub sp, 2 | |||
codeseg:9DC1 mov bp, [bp+spritePtr] | |||
codeseg:9DC4 mov al, byte ptr [bp+Sprite.yPos] ; At some places only lowest 8 bits are used | |||
codeseg:9DC7 mov ah, byte ptr [bp+Sprite.xPos] ; At some places only lowest 8 bits are used | |||
codeseg:9DCA call screenOffset ; Calculates the screen offset for given coordinate? Video or AGI screen offset? | |||
codeseg:9DCA ; DI = AL * 320 + AH | |||
codeseg:9DCA ; (Destroys BX contents (Returns with BH = 0, BL = AH)) | |||
codeseg:9DCA ; | |||
codeseg:9DCA ; Maybe not named quite correctly? | |||
codeseg:9DCD mov si, di | |||
codeseg:9DCF mov ah, byte ptr [bp+Sprite.ySize] ; At some places only lowest 8 bits are used | |||
codeseg:9DD2 mov al, byte ptr [bp+Sprite.xSize] ; At some places only lowest 8 bits are used | |||
codeseg:9DD5 mov di, [bp+Sprite.buffer] | |||
codeseg:9DD8 push ds | |||
codeseg:9DD9 mov ds, agi256PicSeg | |||
codeseg:9DDD xor dx, dx | |||
codeseg:9DDF mov cx, dx | |||
codeseg:9DE1 jmp AO_agi256_saveArea_loop_init ; DX = 320 - Sprite.xSize (AL) | |||
codeseg:9DE1 AO_agi256_saveArea endp ; SI += 160 (This is done in part 2 of the loop init, actually) | |||
codeseg:9DE1 ; This is elsewhere than directly inside AO_agi256_saveArea | |||
codeseg:9DE1 ; probably because it didn't fit otherwise. Returns to AO_agi256_saveArea_loop | |||
codeseg:9DE1 ; (Although calls AO_agi256_saveArea_loop_init_part2 first) | |||
codeseg:9DE4 ; --------------------------------------------------------------------------- | |||
codeseg:9DE4 nop | |||
codeseg:9DE5 nop | |||
codeseg:9DE6 | |||
codeseg:9DE6 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9DE6 | |||
codeseg:9DE6 ; Loop in pseudo C: | |||
codeseg:9DE6 ; for (int y = 0; y < Sprite.ySize; y++) { | |||
codeseg:9DE6 ; memcpy(ES:DI, DS:SI, Sprite.xSize); | |||
codeseg:9DE6 ; SI += 320; | |||
codeseg:9DE6 ; DI += Sprite.xSize; | |||
codeseg:9DE6 ; } | |||
codeseg:9DE6 | |||
codeseg:9DE6 AO_agi256_saveArea_loop proc near ; CODE XREF: AO_agi256_saveArea_loop+8�j | |||
codeseg:9DE6 ; AO_agi256_saveArea_loop_init_part2+4�j | |||
codeseg:9DE6 mov cl, al ; Move Sprite.xSize bytes per row | |||
codeseg:9DE8 repe movsb ; Move the bytes from DS:SI to ES:DI | |||
codeseg:9DEA add si, dx ; Move to the next row | |||
codeseg:9DEA ; repe movsb added Sprite.xSize to SI | |||
codeseg:9DEA ; add si,dx adds (320 - Sprite.xSize) to SI | |||
codeseg:9DEA ; so the addition is Sprite.xSize + (320 - Sprite.xSize) = 320 | |||
codeseg:9DEC dec ah ; Loop Sprite.ySize times | |||
codeseg:9DEE jnz AO_agi256_saveArea_loop ; Loop in pseudo C: | |||
codeseg:9DEE ; for (int y = 0; y < Sprite.ySize; y++) { | |||
codeseg:9DEE ; memcpy(ES:DI, DS:SI, Sprite.xSize); | |||
codeseg:9DEE ; SI += 320; | |||
codeseg:9DEE ; DI += Sprite.xSize; | |||
codeseg:9DEE ; } | |||
codeseg:9DF0 pop ds | |||
codeseg:9DF1 add sp, 2 | |||
codeseg:9DF4 pop bp | |||
codeseg:9DF5 pop di | |||
codeseg:9DF6 pop si | |||
codeseg:9DF7 retn | |||
codeseg:9DF7 AO_agi256_saveArea_loop endp ; sp = 0Ah | |||
codeseg:9DF7 | |||
codeseg:9DF8 | |||
codeseg:9DF8 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9DF8 | |||
codeseg:9DF8 ; restoreArea(struct Sprite *s) { | |||
codeseg:9DF8 ; int destOffset = screenOffset(s->xPos, s->yPos); | |||
codeseg:9DF8 ; uint8 *dest = &agi256PicSeg[destOffset + 160]; | |||
codeseg:9DF8 ; for (int y = 0; y < s->ySize; y++) | |||
codeseg:9DF8 ; memcpy(dest + 320 * y, s->buffer + s->xSize * y, s->xSize); | |||
codeseg:9DF8 ; } | |||
codeseg:9DF8 ; Attributes: bp-based frame | |||
codeseg:9DF8 | |||
codeseg:9DF8 AO_agi256_restoreArea proc near ; CODE XREF: j_AO_agi256_restoreArea�j | |||
codeseg:9DF8 | |||
codeseg:9DF8 spritePtr = word ptr 8 | |||
codeseg:9DF8 | |||
codeseg:9DF8 push si | |||
codeseg:9DF9 push di | |||
codeseg:9DFA push bp | |||
codeseg:9DFB mov bp, sp | |||
codeseg:9DFD sub sp, 2 | |||
codeseg:9E00 mov bp, [bp+spritePtr] | |||
codeseg:9E03 mov al, byte ptr [bp+Sprite.yPos] ; At some places only lowest 8 bits are used | |||
codeseg:9E06 mov ah, byte ptr [bp+Sprite.xPos] ; At some places only lowest 8 bits are used | |||
codeseg:9E09 call screenOffset ; Calculates the screen offset for given coordinate? Video or AGI screen offset? | |||
codeseg:9E09 ; DI = AL * 320 + AH | |||
codeseg:9E09 ; (Destroys BX contents (Returns with BH = 0, BL = AH)) | |||
codeseg:9E09 ; | |||
codeseg:9E09 ; Maybe not named quite correctly? | |||
codeseg:9E0C mov si, [bp+Sprite.buffer] | |||
codeseg:9E0F mov ah, byte ptr [bp+Sprite.ySize] ; At some places only lowest 8 bits are used | |||
codeseg:9E12 mov al, byte ptr [bp+Sprite.xSize] ; At some places only lowest 8 bits are used | |||
codeseg:9E15 push es | |||
codeseg:9E16 mov es, agi256PicSeg | |||
codeseg:9E1A xor dx, dx | |||
codeseg:9E1C mov cx, dx | |||
codeseg:9E1E jmp AO_agi256_restoreArea_loop_init ; DX = 320 - Sprite.xSize (AL) | |||
codeseg:9E1E AO_agi256_restoreArea endp ; DI += 160 | |||
codeseg:9E1E ; This is elsewhere than directly inside AO_agi256_restoreArea | |||
codeseg:9E1E ; probably because it didn't fit otherwise. Returns to AO_agi256_restoreArea_loop | |||
codeseg:9E21 ; --------------------------------------------------------------------------- | |||
codeseg:9E21 nop | |||
codeseg:9E22 nop | |||
codeseg:9E23 | |||
codeseg:9E23 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9E23 | |||
codeseg:9E23 ; Loop in pseudo C: | |||
codeseg:9E23 ; for (int y = 0; y < Sprite.ySize; y++) { | |||
codeseg:9E23 ; memcpy(ES:DI, DS:SI, Sprite.xSize); | |||
codeseg:9E23 ; DI += 320; | |||
codeseg:9E23 ; SI += Sprite.xSize; | |||
codeseg:9E23 ; } | |||
codeseg:9E23 | |||
codeseg:9E23 AO_agi256_restoreArea_loop proc near ; CODE XREF: AO_agi256_restoreArea_loop+8�j | |||
codeseg:9E23 ; AO_agi256_restoreArea_loop_init+D�j | |||
codeseg:9E23 mov cl, al ; Move Sprite.xSize bytes per row | |||
codeseg:9E25 repe movsb ; Move the bytes from DS:SI to ES:DI | |||
codeseg:9E27 add di, dx ; Move to the next row | |||
codeseg:9E27 ; repe movsb added Sprite.xSize to DI | |||
codeseg:9E27 ; add di,dx adds (320 - Sprite.xSize) to DI | |||
codeseg:9E27 ; so the addition is Sprite.xSize + (320 - Sprite.xSize) = 320 | |||
codeseg:9E29 dec ah | |||
codeseg:9E2B jnz AO_agi256_restoreArea_loop ; Loop in pseudo C: | |||
codeseg:9E2B ; for (int y = 0; y < Sprite.ySize; y++) { | |||
codeseg:9E2B ; memcpy(ES:DI, DS:SI, Sprite.xSize); | |||
codeseg:9E2B ; DI += 320; | |||
codeseg:9E2B ; SI += Sprite.xSize; | |||
codeseg:9E2B ; } | |||
codeseg:9E2D pop es | |||
codeseg:9E2E add sp, 2 | |||
codeseg:9E31 pop bp | |||
codeseg:9E32 pop di | |||
codeseg:9E33 pop si | |||
codeseg:9E34 retn | |||
codeseg:9E34 AO_agi256_restoreArea_loop endp ; sp = 0Ah | |||
codeseg:9E34 | |||
codeseg:9E35 | |||
codeseg:9E35 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9E35 | |||
codeseg:9E35 ; Attributes: bp-based frame | |||
codeseg:9E35 | |||
codeseg:9E35 AO_agi256_blit proc near ; CODE XREF: j_AO_agi256_blit�j | |||
codeseg:9E35 | |||
codeseg:9E35 structPtr = word ptr 8 | |||
codeseg:9E35 arg_1C = byte ptr 24h | |||
codeseg:9E35 | |||
codeseg:9E35 push si | |||
codeseg:9E36 push di | |||
codeseg:9E37 push bp | |||
codeseg:9E38 mov bp, sp | |||
codeseg:9E3A sub sp, 2 | |||
codeseg:9E3D mov bp, [bp+structPtr] | |||
codeseg:9E40 mov al, [bp+2] | |||
codeseg:9E43 push ax | |||
codeseg:9E44 mov si, [bp+10h] | |||
codeseg:9E47 test byte ptr [si+2], 80h | |||
codeseg:9E4B jz dontMirror | |||
codeseg:9E4D push bp | |||
codeseg:9E4E call _BlitMirrorCell | |||
codeseg:9E51 pop bp | |||
codeseg:9E52 mov si, [bp+10h] | |||
codeseg:9E55 | |||
codeseg:9E55 dontMirror: ; CODE XREF: AO_agi256_blit+16�j | |||
codeseg:9E55 inc si | |||
codeseg:9E56 lodsw | |||
codeseg:9E57 mov dx, ax | |||
codeseg:9E59 mov ah, byte ptr [bp+blitStruc.xPos] | |||
codeseg:9E5C mov al, byte ptr [bp+blitStruc.yPos] | |||
codeseg:9E5F sub al, dl | |||
codeseg:9E61 inc al | |||
codeseg:9E63 call screenOffset ; Calculates the screen offset for given coordinate? Video or AGI screen offset? | |||
codeseg:9E63 ; DI = AL * 320 + AH | |||
codeseg:9E63 ; (Destroys BX contents (Returns with BH = 0, BL = AH)) | |||
codeseg:9E63 ; | |||
codeseg:9E63 ; Maybe not named quite correctly? | |||
codeseg:9E66 shl dh, 1 | |||
codeseg:9E68 shl dh, 1 | |||
codeseg:9E6A shl dh, 1 | |||
codeseg:9E6C shl dh, 1 ; DH *= 16 | |||
codeseg:9E6E push es | |||
codeseg:9E6F mov es, agi256PicSeg | |||
codeseg:9E73 mov bl, 1 | |||
codeseg:9E75 mov bh, [bp+arg_1C] | |||
codeseg:9E78 shl bh, 1 | |||
codeseg:9E7A shl bh, 1 | |||
codeseg:9E7C shl bh, 1 | |||
codeseg:9E7E shl bh, 1 ; BH *= 16 | |||
codeseg:9E80 mov bp, di | |||
codeseg:9E82 xor cx, cx | |||
codeseg:9E84 jmp short startBlit ; Read byte from DS:[SI++] | |||
codeseg:9E86 ; --------------------------------------------------------------------------- | |||
codeseg:9E86 nop | |||
codeseg:9E87 | |||
codeseg:9E87 ah_eq_dh: ; CODE XREF: AO_agi256_blit+61�j | |||
codeseg:9E87 cbw ; Sign extend AL to AX (0 <= AL <= 0x0F, so AH = 0) | |||
codeseg:9E88 add di, ax ; DI += AX | |||
codeseg:9E8A | |||
codeseg:9E8A startBlit: ; CODE XREF: AO_agi256_blit+4F�j | |||
codeseg:9E8A ; AO_agi256_blit+83�j ... | |||
codeseg:9E8A lodsb ; Read byte from DS:[SI++] | |||
codeseg:9E8B or al, al | |||
codeseg:9E8D jz zeroByte ; Jump if it's zero | |||
codeseg:9E8F mov ah, al ; Double the pixel | |||
codeseg:9E91 and ax, 0F00Fh ; Make lower nibble of AL contain pixel's color info and | |||
codeseg:9E91 ; upper nibble of AH contain pixel's priority/control info | |||
codeseg:9E94 cmp ah, dh | |||
codeseg:9E96 jz ah_eq_dh ; Sign extend AL to AX (0 <= AL <= 0x0F, so AH = 0) | |||
codeseg:9E98 mov cl, al | |||
codeseg:9E9A shr ah, 1 | |||
codeseg:9E9C shr ah, 1 | |||
codeseg:9E9E shr ah, 1 | |||
codeseg:9EA0 shr ah, 1 ; Bring priority/control info to lower nibble of AH | |||
codeseg:9EA2 | |||
codeseg:9EA2 xLoop: ; CODE XREF: AO_agi256_blit+81�j | |||
codeseg:9EA2 ; AO_agi256_blit+B1�j | |||
codeseg:9EA2 mov al, es:[di] ; Read pixel | |||
codeseg:9EA5 and al, 0F0h ; Leave only the priority/control info | |||
codeseg:9EA7 cmp al, 2 shl 4 | |||
codeseg:9EA9 jbe controlByte012 ; Jump if pixel's control info is 0, 1 or 2 | |||
codeseg:9EAB cmp al, bh | |||
codeseg:9EAD ja priGreaterThanBH | |||
codeseg:9EAF mov al, bh ; AL <= BH so | |||
codeseg:9EAF ; AL = BH <=> AL = MAX(AL, BH) | |||
codeseg:9EB1 | |||
codeseg:9EB1 loc_9EB1: ; CODE XREF: AO_agi256_blit+AE�j | |||
codeseg:9EB1 or al, ah ; AL |= AH | |||
codeseg:9EB3 jmp AO_agi256_blit_sub ; ES:[160 + DI++] = AL & 0x0F; | |||
codeseg:9EB3 ; BL = 0; | |||
codeseg:9EB6 ; --------------------------------------------------------------------------- | |||
codeseg:9EB6 | |||
codeseg:9EB6 afterBlitSubCall: ; CODE XREF: AO_agi256_blit_sub+D�j | |||
codeseg:9EB6 loop xLoop ; Read pixel | |||
codeseg:9EB8 jmp short startBlit ; Read byte from DS:[SI++] | |||
codeseg:9EBA ; --------------------------------------------------------------------------- | |||
codeseg:9EBA | |||
codeseg:9EBA zeroByte: ; CODE XREF: AO_agi256_blit+58�j | |||
codeseg:9EBA dec dl ; DL-- | |||
codeseg:9EBC jz zeroDL | |||
codeseg:9EBE add bp, 320 | |||
codeseg:9EC2 mov di, bp | |||
codeseg:9EC4 jmp short startBlit ; Read byte from DS:[SI++] | |||
codeseg:9EC6 ; --------------------------------------------------------------------------- | |||
codeseg:9EC6 | |||
codeseg:9EC6 controlByte012: ; CODE XREF: AO_agi256_blit+74�j | |||
codeseg:9EC6 push di | |||
codeseg:9EC7 xor ch, ch | |||
codeseg:9EC9 | |||
codeseg:9EC9 loc_9EC9: ; CODE XREF: AO_agi256_blit+A7�j | |||
codeseg:9EC9 cmp di, 0D0C0h | |||
codeseg:9ECD jnb loc_9EDE | |||
codeseg:9ECF add di, 320 | |||
codeseg:9ED3 mov ch, es:[di] | |||
codeseg:9ED6 and ch, 0F0h | |||
codeseg:9ED9 cmp ch, 20h ; ' ' | |||
codeseg:9EDC jbe loc_9EC9 | |||
codeseg:9EDE | |||
codeseg:9EDE loc_9EDE: ; CODE XREF: AO_agi256_blit+98�j | |||
codeseg:9EDE pop di | |||
codeseg:9EDF cmp ch, bh | |||
codeseg:9EE1 mov ch, 0 | |||
codeseg:9EE3 jbe loc_9EB1 ; AL |= AH | |||
codeseg:9EE5 | |||
codeseg:9EE5 priGreaterThanBH: ; CODE XREF: AO_agi256_blit+78�j | |||
codeseg:9EE5 inc di | |||
codeseg:9EE6 loop xLoop ; Read pixel | |||
codeseg:9EE8 jmp short startBlit ; Read byte from DS:[SI++] | |||
codeseg:9EEA ; --------------------------------------------------------------------------- | |||
codeseg:9EEA | |||
codeseg:9EEA zeroDL: ; CODE XREF: AO_agi256_blit+87�j | |||
codeseg:9EEA pop es | |||
codeseg:9EEB pop ax | |||
codeseg:9EEC or al, al | |||
codeseg:9EEE jnz zeroDL_notZeroAL | |||
codeseg:9EF0 mov al, 1 ; f1 = Ego is invisible on the screen (Completely obscured by another object) | |||
codeseg:9EF2 test bl, bl | |||
codeseg:9EF4 jnz notZeroBL ; Hide ego (Set ego as invisible) | |||
codeseg:9EF6 call _ResetFlagAL ; Show ego (Set ego as visible i.e. not invisible) | |||
codeseg:9EF9 jmp short zeroDL_notZeroAL | |||
codeseg:9EFB ; --------------------------------------------------------------------------- | |||
codeseg:9EFB | |||
codeseg:9EFB notZeroBL: ; CODE XREF: AO_agi256_blit+BF�j | |||
codeseg:9EFB call _SetFlagAL ; Hide ego (Set ego as invisible) | |||
codeseg:9EFE | |||
codeseg:9EFE zeroDL_notZeroAL: ; CODE XREF: AO_agi256_blit+B9�j | |||
codeseg:9EFE ; AO_agi256_blit+C4�j | |||
codeseg:9EFE add sp, 2 | |||
codeseg:9F01 pop bp | |||
codeseg:9F02 pop di | |||
codeseg:9F03 pop si | |||
codeseg:9F04 retn | |||
codeseg:9F04 AO_agi256_blit endp | |||
codeseg:9F04 | |||
codeseg:9F05 | |||
codeseg:9F05 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9F05 | |||
codeseg:9F05 ; DX = 320 - Sprite.xSize (AL) | |||
codeseg:9F05 ; SI += 160 (This is done in part 2 of the loop init, actually) | |||
codeseg:9F05 ; This is elsewhere than directly inside AO_agi256_saveArea | |||
codeseg:9F05 ; probably because it didn't fit otherwise. Returns to AO_agi256_saveArea_loop | |||
codeseg:9F05 ; (Although calls AO_agi256_saveArea_loop_init_part2 first) | |||
codeseg:9F05 | |||
codeseg:9F05 AO_agi256_saveArea_loop_init proc near ; CODE XREF: AO_agi256_saveArea+28�j | |||
codeseg:9F05 mov dx, 320 | |||
codeseg:9F08 push ax | |||
codeseg:9F09 xor ah, ah | |||
codeseg:9F0B sub dx, ax ; DX = 320 - Sprite.xSize | |||
codeseg:9F0D pop ax | |||
codeseg:9F0E jmp AO_agi256_saveArea_loop_init_part2 ; This is elsewhere than directly inside AO_agi256_saveArea_loop_init | |||
codeseg:9F0E AO_agi256_saveArea_loop_init endp ; probably because it didn't fit otherwise. Returns to AO_agi256_saveArea_loop | |||
codeseg:9F0E | |||
codeseg:9F11 | |||
codeseg:9F11 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9F11 | |||
codeseg:9F11 ; DX = 320 - Sprite.xSize (AL) | |||
codeseg:9F11 ; DI += 160 | |||
codeseg:9F11 ; This is elsewhere than directly inside AO_agi256_restoreArea | |||
codeseg:9F11 ; probably because it didn't fit otherwise. Returns to AO_agi256_restoreArea_loop | |||
codeseg:9F11 | |||
codeseg:9F11 AO_agi256_restoreArea_loop_init proc near | |||
codeseg:9F11 ; CODE XREF: AO_agi256_restoreArea+26�j | |||
codeseg:9F11 mov dx, 320 | |||
codeseg:9F14 push ax | |||
codeseg:9F15 xor ah, ah | |||
codeseg:9F17 sub dx, ax | |||
codeseg:9F19 pop ax | |||
codeseg:9F1A add di, 160 | |||
codeseg:9F1E jmp AO_agi256_restoreArea_loop ; Loop in pseudo C: | |||
codeseg:9F1E AO_agi256_restoreArea_loop_init endp ; for (int y = 0; y < Sprite.ySize; y++) { | |||
codeseg:9F1E ; memcpy(ES:DI, DS:SI, Sprite.xSize); | |||
codeseg:9F1E ; DI += 320; | |||
codeseg:9F1E ; SI += Sprite.xSize; | |||
codeseg:9F1E ; } | |||
codeseg:9F21 | |||
codeseg:9F21 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9F21 | |||
codeseg:9F21 ; This is elsewhere than directly inside AO_agi256_saveArea_loop_init | |||
codeseg:9F21 ; probably because it didn't fit otherwise. Returns to AO_agi256_saveArea_loop | |||
codeseg:9F21 | |||
codeseg:9F21 AO_agi256_saveArea_loop_init_part2 proc near | |||
codeseg:9F21 ; CODE XREF: AO_agi256_saveArea_loop_init+9�j | |||
codeseg:9F21 add si, 160 | |||
codeseg:9F25 jmp AO_agi256_saveArea_loop ; Loop in pseudo C: | |||
codeseg:9F25 AO_agi256_saveArea_loop_init_part2 endp ; for (int y = 0; y < Sprite.ySize; y++) { | |||
codeseg:9F25 ; memcpy(ES:DI, DS:SI, Sprite.xSize); | |||
codeseg:9F25 ; SI += 320; | |||
codeseg:9F25 ; DI += Sprite.xSize; | |||
codeseg:9F25 ; } | |||
codeseg:9F28 | |||
codeseg:9F28 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ | |||
codeseg:9F28 | |||
codeseg:9F28 ; ES:[160 + DI++] = AL & 0x0F; | |||
codeseg:9F28 ; BL = 0; | |||
codeseg:9F28 | |||
codeseg:9F28 AO_agi256_blit_sub proc near ; CODE XREF: AO_agi256_blit+7E�j | |||
codeseg:9F28 add di, 160 | |||
codeseg:9F2C and al, 0Fh | |||
codeseg:9F2E stosb | |||
codeseg:9F2F sub di, 160 | |||
codeseg:9F33 xor bl, bl | |||
codeseg:9F35 jmp afterBlitSubCall | |||
codeseg:9F35 AO_agi256_blit_sub endp | |||
codeseg:9F35 | |||
codeseg:9F35 ; --------------------------------------------------------------------------- | |||
codeseg:9F38 db 0D8h dup(0) | |||
codeseg:9F38 codeseg ends | |||
codeseg:9F38 | |||
</pre> | |||
===Differences between AGI v2.936's AGI.EXE and AGI256's hacked AGI.EXE=== | |||
====Disclaimer==== | |||
This is a raw info dump from a personal file so things may be funny, wrong, | |||
weird or <insert your favorite adjective here> but there are details to be sure: | |||
====The raw info dump==== | |||
<pre> | |||
Differences between original Sierra On-Line's AGI interpreter version 2.936 | |||
and the hacked AGI256's AGI.EXE: | |||
///////////////////////////////////////////////////////////////////////////// | |||
Copyright string changed and some other bytes... | |||
not 100% sure if they are used or not... let's see. | |||
If changed bytes from seg000:0065 to seg000:0077 to all zeroes and to all semirandomly | |||
typed in numbers and all it did was that it made the AGI256 demo have some white color | |||
pixels where they shouldn't be in the Larry's bar screen. So... it may very well be that they're used. | |||
NOTE THAT: E8 49 00 = call sub_C4 = db 'FI',0 | |||
AND there's a real subroutine starting at seg000:00C4 so it might be used as code! | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:0000 aAdventureGameI db 'Adventure Game Interpreter',0Dh,0Ah | |||
seg000:0000 ; DATA XREF: seg001:0000�o | |||
seg000:0000 ; sub_401D+59�r ... | |||
seg000:0000 db 'Copyright (C) 1984, 1985, 1986 Sierra On-Line, Inc.',0Dh,0Ah | |||
seg000:0000 db 'Authors: Jeff Stephenson & Chris Iden',0Dh,0Ah | |||
seg000:0000 db 'FI',0 | |||
-> AGI256 INTERPRETER: | |||
seg000:0000 aAgi256ColorsCS db 'AGI 256 colors ',0Dh,0Ah ; DATA XREF: seg001:0000�o | |||
seg000:0000 ; sub_401D+59�r ... | |||
seg000:0000 db '(C) Sierra On-Line - by Jeff Stephenson and Chris Iden',0Dh,0Ah | |||
seg000:0000 db 'Hacked by Dark Minister',0Dh,0Ah | |||
seg000:0000 db 'FI',0 | |||
seg000:0065 db 87h ; Unknown data from 0x0065 to 0x0077 | |||
seg000:0066 db 49h ; I | |||
seg000:0067 db 29h ; ) | |||
seg000:0068 db 23h ; # ; DATA XREF: sub_4125+12�r | |||
seg000:0068 ; sub_4125+27�r ... | |||
seg000:0069 db 92h | |||
seg000:006A db 99h | |||
seg000:006B db 99h | |||
seg000:006C db 11h | |||
seg000:006D db 11h ; | |||
seg000:006E db 11h | |||
seg000:006F db 19h ; | |||
seg000:0070 db 88h | |||
seg000:0071 db 37h ; 7 | |||
seg000:0072 db 83h | |||
seg000:0073 db 83h ; â | |||
seg000:0074 db 73h ; s | |||
seg000:0075 db 87h ; ç | |||
seg000:0076 db 38h ; 8 | |||
seg000:0077 db 83h ; â | |||
///////////////////////////////////////////////////////////////////////////// | |||
In function _StatLineWrite (Function name taken from Agi2917.idb): | |||
Changes _WindowLineClr call to setWhiteMenuBar call | |||
which clears first 8 rows of video memory with white. | |||
So changes the code that clears the status line before writing to it. | |||
Rationale: | |||
Probably because of wanting VGA support. | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:34D7 E8 CC F6 call sub_2BA6 ; _WindowLineClr in Agi2917.idb | |||
-> AGI256 INTERPRETER: | |||
seg000:34D7 E8 80 65 call near ptr 9A5Ah | |||
0x9A5A - 0x9800 = 0x025A in the AGIGRAF.OVL: | |||
seg000:025A ; Clears first 8 rows (320*8 bytes) of video memory | |||
seg000:025A ; with white pixels (Color 15). | |||
seg000:025A | |||
seg000:025A setWhiteMenuBar proc near | |||
seg000:025A push cx | |||
seg000:025B push es | |||
seg000:025C push di | |||
seg000:025D push ax | |||
seg000:025E mov ax, 0A000h | |||
seg000:0261 mov es, ax | |||
seg000:0263 assume es:nothing | |||
seg000:0263 xor di, di | |||
seg000:0265 mov ax, 0F0Fh | |||
seg000:0268 mov cx, 500h | |||
seg000:026B repe stosw | |||
seg000:026D pop ax | |||
seg000:026E pop di | |||
seg000:026F pop es | |||
seg000:0270 assume es:nothing | |||
seg000:0270 pop cx | |||
seg000:0271 retn | |||
seg000:0271 setWhiteMenuBar endp | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _ArrangeMem (Name from Agi2917.idb): | |||
Changed to allocating twice the memory than with the original interpreter. | |||
Saves the allocated memory's segment to SBuff_Seg in Agi2917.idb and | |||
to agi256PicSeg in AGI256's disassembly. | |||
Rationale: | |||
Need another screen besides the 16 color & control line & priority info screen | |||
for 256 color info so that doubles the memory need. | |||
0x690 in paragraphs (16 bytes) is 160*168 bytes. | |||
0xD20 is twice that. | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:4240 mov bx, 690h | |||
-> AGI256 INTERPRETER: | |||
seg000:4240 mov bx, 0D20h | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _ArrangeMem (Name from Agi2917.idb): | |||
Changed to allocating twice the memory than with the original interpreter. | |||
Saves the allocated memory's segment to wHGCFontData in Agi2917.idb. | |||
Rationale: | |||
Don't really know. Maybe not needed at all? Or it's also possible that the | |||
wHGCFontData is not a correct name for the variable and/or the allocate | |||
area is used for something else and Hercules font data. | |||
0x690 in paragraphs (16 bytes) is 160*168 bytes. | |||
0xD20 is twice that. | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:4259 add ax, 690h | |||
-> AGI256 INTERPRETER: | |||
seg000:4259 add ax, 0D20h | |||
///////////////////////////////////////////////////////////////////////////// | |||
In an AGI screen buffer filling function (_SBuffClear in Agi2917.idb): | |||
Fills the AGI screen buffer with AX contents. Filling space doubled in AGI256. | |||
(There's some obsolete Hercules code in this function, but it's not used so | |||
it doesn't matter). | |||
Use cases: | |||
AX = 0x4040 (Fill with lowest priority i.e. 4 and black color i.e. 0). | |||
AX = 0x4F4F (Fill with lowest priority i.e. 4 and white color i.e. 15). | |||
Rationale: | |||
Needed because the 256 color screen and the normal 16 color screen are | |||
horizontally adjacent. Probably only needed for clearing the 16 color | |||
screen because the 256 color screen is always fully filled when loading | |||
an AGI256 picture resource into it. | |||
160*168 = 0x3480 * 2 | |||
160*168*2 = 0x6900 * 2 | |||
There's a repe stosw using cx after this instruction. | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:525E mov cx, 3480h | |||
-> AGI256 INTERPRETER: | |||
seg000:525E mov cx, 6900h | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _SBuffXLine (Name from Agi2917.idb): | |||
Changes direct pixel manipulation code to a function call. | |||
Functionally changes nothing as the called function is functionally | |||
identical to the code that was replaced. | |||
Rationale: | |||
Maybe not needed at all? Maybe some leftover modification that wasn't used | |||
after all? | |||
0x9A4F must be pointing to: | |||
seg000:024E ; Sets and/or clears current pixel bits | |||
seg000:024E ; AL = ES:[DI] = PIXEL | |||
seg000:024E ; (PIXEL |= BH) &= BL | |||
seg000:024E | |||
seg000:024E setClrCurrPixel proc near | |||
seg000:024E nop | |||
seg000:024F mov al, es:[di] | |||
seg000:0252 or al, bh | |||
seg000:0254 and al, bl | |||
seg000:0256 mov es:[di], al | |||
seg000:0259 retn | |||
seg000:0259 setClrCurrPixel endp | |||
in AGIGRAF.OVL! So that makes their relocation value 0x9A4F - 0x24E = 0x9801... | |||
wait... that's not even... let's see, there's a nop in setClrCurrPixel's start. | |||
Let's throw that away so we'd jump right into 0x24F so the relocation value | |||
would be 0x9A4F - 0x24E = 0x9800... now that's better :-). | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:5298 loc_5298: ; CODE XREF: sub_526F+34�j | |||
seg000:5298 inc di | |||
seg000:5299 mov al, es:[di] ; CHANGED | |||
seg000:529C or al, bh ; CHANGED | |||
seg000:529E and al, bl ; CHANGED | |||
seg000:52A0 mov es:[di], al ; CHANGED | |||
seg000:52A3 loop loc_5298 | |||
-> AGI256 INTERPRETER: | |||
seg000:5298 loc_5298: ; CODE XREF: sub_526F+34�j | |||
seg000:5298 inc di | |||
seg000:5299 call near ptr 9A4Fh ; CHANGED | |||
seg000:52A3 loop loc_5298 | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _SBuffYLine (Name from Agi2917.idb): | |||
This converts the vertical drawing loop to use 320 rather than 160 as the | |||
offset between rows. Also changes direct pixel manipulation code to a | |||
function call with functionally identical code in it. | |||
Rationale: | |||
As there are now two AGI screens horizontally adjacent to each other (Left | |||
160x168 one is the normal 16 color screen and the right 160x168 one is the | |||
new 256 color screen) the vertical line drawing loop has to use 320 as the | |||
offset between rows rather than 160. The pixel manipulation code replacement | |||
with a function call is probably not needed as it doesn't functionally change | |||
anything. | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:52E3 loc_52E3: ; CODE XREF: sub_52AB+34�j | |||
seg000:52E3 add di, 0A0h ; 'á' | |||
seg000:52E7 mov al, es:[di] | |||
seg000:52EA or al, bh | |||
seg000:52EC and al, bl | |||
seg000:52EE mov es:[di], al | |||
seg000:52F1 loop loc_52E1 | |||
-> AGI256 INTERPRETER: | |||
seg000:52E3 loc_52E3: ; CODE XREF: sub_52AB+34�j | |||
seg000:52E3 add di, 140h | |||
seg000:52E7 call near ptr 9A4Fh | |||
seg000:52F1 loop loc_52E1 | |||
which is effectively the same as: | |||
seg000:52E3 loc_52E3: ; CODE XREF: sub_52AB+34�j | |||
seg000:52E3 add di, 140h | |||
seg000:024F mov al, es:[di] | |||
seg000:0252 or al, bh | |||
seg000:0254 and al, bl | |||
seg000:0256 mov es:[di], al | |||
seg000:52F1 loop loc_52E1 | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _SBuffPlotPixel (Name from Agi2917.idb): | |||
Changes multiplication from 160 to 320 in calculation x + y * 320. | |||
(16 to 32 really but they're multiplied by 10 before these changes). | |||
Rationale: | |||
As there are now two AGI screens horizontally adjacent to each other (Left | |||
160x168 one is the normal 16 color screen and the right 160x168 one is the | |||
new 256 color screen) the pixel plotting code has to use 320 as the offset | |||
between rows rather than 160. | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:5311 shl di, 1 | |||
seg000:5313 shl di, 1 | |||
seg000:5315 shl di, 1 | |||
seg000:5317 shl di, 1 | |||
-> AGI256 INTERPRETER: | |||
seg000:5311 shl di, 4 | |||
seg000:5314 shl di, 1 | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _SBuffPlotPixel (Name from Agi2917.idb): | |||
Changes direct pixel manipulation code to a function call. | |||
Functionally changes nothing as the called function is functionally | |||
identical to the code that was replaced. | |||
Rationale: | |||
Maybe not needed at all? Maybe some leftover modification that wasn't used | |||
after all? | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:532F mov al, es:[di] | |||
seg000:5332 or al, bh | |||
seg000:5334 and al, bl | |||
seg000:5336 mov es:[di], al | |||
-> AGI256 INTERPRETER: | |||
seg000:532F call near ptr 9A4Fh | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _SBuffPicFill (Name from Agi2917.idb): | |||
Changes multiplication from 160 to 320 in calculation x + y * 320. | |||
(16 to 32 really but they're multiplied by 10 before these changes). | |||
Rationale: | |||
As there are now two AGI screens horizontally adjacent to each other (Left | |||
160x168 one is the normal 16 color screen and the right 160x168 one is the | |||
new 256 color screen) the pixel plotting code has to use 320 as the offset | |||
between rows rather than 160. | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:5483 shl di, 1 | |||
seg000:5485 shl di, 1 | |||
seg000:5487 shl di, 1 | |||
seg000:5489 shl di, 1 | |||
-> AGI256 INTERPRETER: | |||
seg000:5483 shl di, 4 | |||
seg000:5486 shl di, 1 | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _Pic_Show (Name from Agi2917.idb): | |||
Before calling j_EGAPutBlock (Name from Agi2917.idb) or j_AG_agi256PutBlock | |||
(Name from AGI256's disassembly) rotate the AGI screen buffers' pixels right | |||
by four in place (Writes the rotated values back to the buffer, that is) | |||
if a certain variable is one (rotate_sbuff). Probably exchanges the places | |||
of color and priority information. | |||
Rationale: | |||
As there are now two AGI screens horizontally adjacent to each other (Left | |||
160x168 one is the normal 16 color screen and the right 160x168 one is the | |||
new 256 color screen) priority screen showing code needs to use 320 as the | |||
offset between rows rather than 160. But because the code is just a single | |||
loop for rotating the whole screen and rotating the 256 color values (If | |||
they aren't shown) doesn't matter (As presumably they are rotated back to | |||
their normal values afterwards) it is easier to just rotate both screens. | |||
160*168 = 0x6900 | |||
160*168*2 = 0xD200 | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:5563 mov cx, 6900h | |||
-> AGI256 INTERPRETER: | |||
seg000:5563 mov cx, 0D200h | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _FBuffOffset (Agi2917.idb), agiToScreenCoords (AGI256 disassembly): | |||
Changes graphics driver dependent (CGA, EGA, Hercules etc) specific | |||
switches to a single VGA specific code. | |||
Rationale: | |||
AGI256 requires VGA so there's no need for the other switches. | |||
// The original 2.936 interpreter's part in pseudo C: | |||
{ | |||
uint16 display = *(ds:0x1130); // enum {CGA, Tandy, HGC, EGA, VGA?}; | |||
uint16 computer = *(ds:0x112e); // enum { IBM_PC?, PCJr?, Tandy?, ...?} | |||
if (display == VGA) | |||
x *= 2; | |||
if (computer == IBM_PC) { | |||
x /= 2; | |||
if (display == EGA) | |||
x /= 2; | |||
} | |||
if (computer == Tandy) { | |||
if (display == EGA) | |||
x /= 4; | |||
} | |||
offset += x; | |||
retn; | |||
} | |||
// AGI256 interpreter's part in pseudo C: | |||
di += bx * 2; | |||
retn; | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:5636 cmp word ptr ds:1130h, 4 | |||
seg000:563B jnz loc_563F | |||
seg000:563D shl bx, 1 | |||
seg000:563F | |||
seg000:563F loc_563F: ; CODE XREF: seg000:563B�j | |||
seg000:563F cmp word ptr ds:112Eh, 0 | |||
seg000:5644 jnz loc_5651 | |||
seg000:5646 shr bx, 1 | |||
seg000:5648 cmp word ptr ds:1130h, 3 | |||
seg000:564D jnz loc_5651 | |||
seg000:564F shr bx, 1 | |||
seg000:5651 | |||
seg000:5651 loc_5651: ; CODE XREF: seg000:5644�j | |||
seg000:5651 ; seg000:564D�j | |||
seg000:5651 cmp word ptr ds:112Eh, 2 | |||
seg000:5656 jnz loc_5663 | |||
seg000:5658 cmp word ptr ds:1130h, 3 | |||
seg000:565D jnz loc_5663 | |||
seg000:565F shr bx, 1 | |||
seg000:5661 shr bx, 1 | |||
seg000:5663 | |||
seg000:5663 loc_5663: ; CODE XREF: seg000:5656�j | |||
seg000:5663 ; seg000:565D�j | |||
seg000:5663 add di, bx | |||
seg000:5665 retn | |||
-> AGI256 INTERPRETER: | |||
seg000:5636 shl bx, 1 | |||
seg000:5638 add di, bx | |||
seg000:563A retn | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _PicBuffOffset (Agi2917.idb), screenOffset (AGI256 disassembly): | |||
Changes multiplication from 160 to 320 in calculation x + y * 320. | |||
(16 to 32 really but they're multiplied by 10 before these changes). | |||
Rationale: | |||
As there are now two AGI screens horizontally adjacent to each other (Left | |||
160x168 one is the normal 16 color screen and the right 160x168 one is the | |||
new 256 color screen) the AGI screen pixel position calculation has to use | |||
320 as the offset between rows rather than 160. | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:5676 shl di, 1 | |||
seg000:5678 shl di, 1 | |||
seg000:567A shl di, 1 | |||
seg000:567C shl di, 1 | |||
-> AGI256 INTERPRETER: | |||
seg000:5676 shl di, 4 | |||
seg000:5679 shl di, 1 | |||
seg000:567B nop | |||
seg000:567C nop | |||
seg000:567D nop | |||
///////////////////////////////////////////////////////////////////////////// | |||
Function that is called near the _EnablePicDraw's beginning in Agi2917.idb: | |||
If the relocation value 0x9800 works here too (Why wouldn't it?) then | |||
we're changing jump from ???GRAF.OVL's first subroutine (Not from the | |||
jump table in its head but after that at 0x0015 is the first subroutine) | |||
to a straight return. The first subroutine the the ???GRAF.OVL is the video | |||
mode setting routine. At least in AGIGRAF.OVL it sets 320x200 256 color video | |||
mode (Mode 13h), sets ds:[videoOfs] to 0xA000 and clears first 64 KiB of video | |||
memory with zeroes. | |||
Rationale: | |||
So this basically throws away some video mode specific stuff and replaces | |||
it with a VGA specific "nothing needed here" code :). | |||
// The original 2.936 interpreter's part in pseudo C: | |||
{ | |||
uint16 display = *(ds:0x1130); // enum {CGA, Tandy, HGC, EGA, VGA?}; | |||
uint16 computer = *(ds:0x112e); // enum { IBM_PC?, PCJr?, Tandy?, ...?} | |||
if (computer == IBM_PC && display != HGC && display != EGA) | |||
setVideoMode(); // goto near ptr 0x9815; | |||
else | |||
retn; | |||
} | |||
// AGI256 interpreter's part in pseudo C (Eh :)): | |||
retn; | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:569F jmp near ptr 9815h | |||
-> AGI256 INTERPRETER: | |||
seg000:569F retn | |||
///////////////////////////////////////////////////////////////////////////// | |||
If the relocation value 0x9800 works here too (Why wouldn't it?) then | |||
we're changing jump from ???GRAF.OVL's second subroutine (Not from the | |||
jump table in its head but after that at 0x0037 is the second subroutine) | |||
to a straight return. The second subroutine the the ???GRAF.OVL is the text | |||
mode setting routine. At least in AGIGRAF.OVL it sets 40x25 16 color text mode, | |||
enables background intensity (Colors 8-15), sets some cursor stuff and | |||
clears the text screen using some attribute. | |||
So this basically throws away some video mode specific stuff and replaces | |||
it with a VGA specific "nothing needed here" code :). | |||
// The original 2.936 interpreter's part in pseudo C: | |||
{ | |||
uint16 display = *(ds:0x1130); // enum {CGA, Tandy, HGC, EGA, VGA?}; | |||
uint16 computer = *(ds:0x112e); // enum { IBM_PC?, PCJr?, Tandy?, ...?} | |||
if (computer == IBM_PC && display != HGC && display != EGA) | |||
setTextMode(); // goto near ptr 0x9837; | |||
else | |||
retn; | |||
} | |||
// AGI256 interpreter's part in pseudo C (Eh :)): | |||
retn; | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:5937 jmp near ptr 9837h | |||
-> AGI256 INTERPRETER: | |||
seg000:5937 retn | |||
///////////////////////////////////////////////////////////////////////////// | |||
'GAMEID' -string's (No trailing zero btw) start is turned into 'DM', 0 | |||
Rationale: | |||
DM is probably short for "Dark Minister" who was the hacker who made the | |||
AGI256 hack. Is this modification needed? Is this checked as the game ID | |||
or something? Don't know... | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:5B6C 'GAMEID' (A string without the trailing zero) | |||
-> AGI256 INTERPRETER: | |||
seg000:5B6C 'DM', 0 (, 'eID') | |||
///////////////////////////////////////////////////////////////////////////// | |||
In _MenuInput (Agi2917.idb): | |||
Changes _WindowLineClr (Agi2917.idb) call near the function's beginning to | |||
AGIGRAF.OVL's setWhiteMenuBar which clears first 8 rows (320*8 bytes) of | |||
video memory with white pixels (Color 15). | |||
Rationale: | |||
Probably needed for VGA support when handling the menu/status line. | |||
- ORIGINAL 2.936 INTERPRETER: | |||
seg000:93ED call sub_2BA6 | |||
-> AGI256 INTERPRETER: | |||
seg000:93ED call near ptr 9A5Ah | |||
///////////////////////////////////////////////////////////////////////////// | |||
- ORIGINAL 2.936 INTERPRETER & AGI256 INTERPRETER -info combined: | |||
seg001:0000 dd 0 ; | |||
seg001:0004 db 0 ; | |||
seg001:0005 db 0 ; | |||
seg001:0006 dd unk_9800 | |||
seg001:000A dw seg seg006 | |||
seg001:000C db 86h ; å | |||
seg001:000D db 0 ; | |||
seg001:000E db 0 ; | |||
seg001:000F db 0 ; | |||
seg001:0010 db 0 ; | |||
seg001:0011 db 0 ; | |||
seg001:0012 db 2Bh ; + | |||
seg001:0013 db 0 ; | |||
seg001:0014 db 0 ; | |||
seg001:0015 db 0 ; | |||
seg001:0016 dd unk_9800 | |||
seg001:001A dw seg seg004 | |||
seg001:001C db 93h ; ô | |||
seg001:001D db 0 ; | |||
seg001:001E db 0 ; | |||
seg001:001F db 0 ; | |||
seg001:0020 db 0 ; | |||
seg001:0021 db 0 ; | |||
seg001:0022 db 1Eh ; | |||
seg001:0023 db 0 ; | |||
seg001:0024 db 0 ; | |||
seg001:0025 db 0 ; | |||
seg001:0026 dd unk_9800 | |||
seg001:002A dw seg seg005 | |||
seg001:002C db 159 | |||
seg001:002D db 0 ; | |||
seg001:002E db 0 ; | |||
seg001:002F db 0 ; | |||
seg001:0030 db 0 ; | |||
seg001:0031 db 0 ; | |||
seg001:0032 db 37 ; Changed 0x25 (37) -> 0x28 (40) in AGI256 hack, size in paragraphs | |||
seg001:0033 db 0 ; | |||
seg001:0034 db 0 ; | |||
seg001:0035 db 0 ; | |||
seg001:0036 dd unk_9800 | |||
seg001:003A dw seg seg007 | |||
seg001:003C db 172 | |||
seg001:003D db 0 ; | |||
seg001:003E db 0 ; | |||
seg001:003F db 0 ; | |||
seg001:0040 db 0 ; | |||
seg001:0041 db 0 ; | |||
seg001:0042 db 91 | |||
seg001:0043 db 0 ; | |||
seg001:0044 db 0 ; | |||
seg001:0045 db 0 ; | |||
seg001:0046 dd unk_9800 | |||
seg001:004A dw seg seg003 | |||
seg001:004C db 185 | |||
seg001:004D db 0 ; | |||
seg001:004E db 0 ; | |||
seg001:004F db 0 ; | |||
seg001:0050 db 0 ; | |||
seg001:0051 db 0 ; | |||
seg001:0052 db 23 ; Changed 0x17 (23) -> 0x28 (40) in AGI256 hack, size in paragraphs | |||
seg001:0053 db 0 ; | |||
seg001:0054 db 0 ; | |||
seg001:0055 db 0 ; | |||
seg001:0056 dd unk_9DB0 | |||
seg001:005A dw seg seg008 | |||
seg001:005C db 197 | |||
seg001:005D db 0 ; | |||
seg001:005E db 0 ; | |||
seg001:005F db 0 ; | |||
seg001:0060 db 0 ; | |||
seg001:0061 db 0 ; | |||
seg001:0062 db 22 ; Changed 0x16 (22) -> 0x19 (25) in AGI256 hack, size in paragraphs | |||
seg001:0063 db 0 ; | |||
seg001:0064 db 0 ; | |||
seg001:0065 db 0 ; | |||
seg001:0066 dd unk_9DB0 | |||
seg001:006A dw seg seg009 | |||
seg001:006C dw 210 | |||
seg001:006E db 0 ; | |||
seg001:006F db 0 ; | |||
seg001:0070 db 0 ; | |||
seg001:0071 db 0 ; | |||
seg001:0072 dw 38 | |||
seg001:0074 db 0 ; | |||
seg001:0075 db 40h | |||
seg001:0076 db 0 ; | |||
seg001:0077 db 0 ; | |||
seg001:0078 dd seg seg009+0BF10000h | |||
seg001:007C dw 0DFh | |||
seg001:007E db 0 ; | |||
seg001:007F db 0 ; | |||
seg001:0080 db 0 ; | |||
seg001:0081 db 0 ; | |||
seg001:0082 db 0E8h ; F | |||
seg001:0083 db 1 ; | |||
seg001:0084 db 0FFh ; | |||
seg001:0085 db 0FFh ; | |||
seg001:0086 aCga_graf_ovl db 'CGA_GRAF.OVL',0 ; Changed to an empty string in AGI256 hack | |||
seg001:0093 aJr_graf_ovl db 'JR_GRAF.OVL',0 ; Changed to an empty string in AGI256 hack | |||
seg001:009F aEga_graf_ovl db 'EGA_GRAF.OVL',0 ; Changed to 'AGIGRAF.OVL',0 in AGI256 hack | |||
seg001:00AC aHgc_graf_ovl db 'HGC_GRAF.OVL',0 ; Changed to an empty string in AGI256 hack | |||
seg001:00B9 aVg_graf_ovl db 'VG_GRAF.OVL',0 ; Changed to an empty string in AGI256 hack | |||
seg001:00C5 aIbm_objs_ovl db 'IBM_OBJS.OVL',0 ; Changed to 'AGIOBJS.OVL',0 in AGI256 hack | |||
seg001:00D2 aHgc_objs_ovl db 'HGC_OBJS.OVL',0 ; Changed to an empty string in AGI256 hack | |||
seg001:00DF aAgidata_ovl db 'AGIDATA.OVL',0 | |||
seg001:00EB aAgi_exe db 'AGI.EXE',0 | |||
///////////////////////////////////////////////////////////////////////////// | |||
</pre> |
edits