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

Jump to navigation Jump to search
Fixed a typo. Hadn't put & in front of some code where it should have been.
(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 160x200 byte buffer. The color data for each pixel
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 160x200 byte buffer to a 320x200 byte buffer so that the 256-color
AGI256 extends this 160x168 byte buffer to a 320x168 byte buffer so that the 256-color
data is held in the right 160x200 half of the buffer and the original style 16-color and
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 160x200 half of the buffer.
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);
417

edits

Navigation menu