Difference between revisions of "AGI/Specifications/Other/AGI256/Implementation Details"

From ScummVM :: Wiki
Jump to navigation Jump to search
(Added AGIGRAF.OVL disassembly.)
(Fixed a typo. Hadn't put & in front of some code where it should have been.)
 
(10 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
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
4 bits.


AGI256 extends this 160x168 byte buffer to a 320x168 byte buffer so that the 256-color
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 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==
I used Nick Sonneveld's disassemblies of various PC AGI interpreter versions when trying
to figure out AGI256. Those IDA databases were highly useful for understanding.
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].
==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>

Latest revision as of 08:46, 18 July 2007

In the original PC AGI interpreter v2.936 the engine holds the color and priority/control 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 4 bits.

AGI256 extends this 160x168 byte buffer to a 320x168 byte buffer so that the 256-color 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 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

I used Nick Sonneveld's disassemblies of various PC AGI interpreter versions when trying to figure out AGI256. Those IDA databases were highly useful for understanding. Thanks Nick. You can check out the disassemblies if you're interested at the 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.

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);
}

Differences between AGI v2.936's AGIDATA.OVL and AGI256's AGIDATA.OVL

dseg:0x08C5: dw offset CmdUnknown170

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

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)

Disassembly of AGIOBJS.OVL

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 

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

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

/////////////////////////////////////////////////////////////////////////////