417
edits
(Added info about differences in AGIDATA.OVL.) |
(Fixed a typo. Hadn't put & in front of some code where it should have been.) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
In the original PC AGI interpreter v2.936 the engine holds the color and priority/control | In the original PC AGI interpreter v2.936 the engine holds the color and priority/control | ||
line information for each pixel in a | line information for each pixel in a 160x168 byte buffer. The color data for each pixel | ||
is held in the byte's lower 4 bits and the priority/control line data is held in the upper | is held in the byte's lower 4 bits and the priority/control line data is held in the upper | ||
4 bits. | 4 bits. | ||
AGI256 extends this | AGI256 extends this 160x168 byte buffer to a 320x168 byte buffer so that the 256-color | ||
data is held in the right | data is held in the right 160x168 half of the buffer and the original style 16-color and | ||
priority/control line information is held in the left | priority/control line information is held in the left 160x168 half of the buffer. | ||
When loading 256-color picture resource with the unknown170 command | |||
the picture is loaded straight into the right 160x168 half of the 320x168 memory buffer. | |||
Cel blitting routine is modified so that when sprite data would normally be written | |||
to a position (x, y) in the 16-color buffer (i.e. the left 160x168 half) it's actually | |||
written to the same position (x, y) but in the 256-color buffer (i.e. the right 160x168 half). | |||
==Used external info== | ==Used external info== | ||
Line 25: | Line 32: | ||
* AGIDATA.OVL | * 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=== | ===Differences between AGI v2.936's AGIDATA.OVL and AGI256's AGIDATA.OVL=== | ||
Line 799: | Line 920: | ||
codeseg:9DB0 jmp AO_agi256_saveArea ; savearea(struct Sprite *s) { | 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 j_AO_agi256_saveArea endp ; int srcOffset = screenOffset(s->xPos, s->yPos); | ||
codeseg:9DB0 ; uint8 *src = agi256PicSeg[srcOffset + 160]; | codeseg:9DB0 ; uint8 *src = &agi256PicSeg[srcOffset + 160]; | ||
codeseg:9DB0 ; for (int y = 0; y < s->ySize; y++) | 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 ; memcpy(s->buffer + s->xSize * y, src + 320 * y, s->xSize); | ||
Line 831: | Line 952: | ||
codeseg:9DB9 ; savearea(struct Sprite *s) { | codeseg:9DB9 ; savearea(struct Sprite *s) { | ||
codeseg:9DB9 ; int srcOffset = screenOffset(s->xPos, s->yPos); | codeseg:9DB9 ; int srcOffset = screenOffset(s->xPos, s->yPos); | ||
codeseg:9DB9 ; uint8 *src = agi256PicSeg[srcOffset + 160]; | codeseg:9DB9 ; uint8 *src = &agi256PicSeg[srcOffset + 160]; | ||
codeseg:9DB9 ; for (int y = 0; y < s->ySize; y++) | 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 ; memcpy(s->buffer + s->xSize * y, src + 320 * y, s->xSize); |
edits