Community

AGI Programming => AGI Development Tools => Topic started by: lance.ewing on June 28, 2026, 04:02:36 AM

Title: AGI v2.230
Post by: lance.ewing on June 28, 2026, 04:02:36 AM
Before I forget (because I did last time), I was notified about 16 months ago by Chris Benshoof that an AGI v2.230 interpreter version had been found at that time. Here is a link to the scummvm bug that relates to it:

https://bugs.scummvm.org/ticket/15764

That ticket has a link to the zip with the interpreter in it.

This version sits between 2.089 and 2.272. There is some discussion on the ticket about adding "support for v2.230 view mirror data" to scummvm, with a link to the commit:

https://github.com/scummvm/scummvm/commit/0614e80c822469293acef12f406afa0fb4818288

A comment in the code says:  2.230 (early version of xmascard): mirror data is in loop header.

Apparently the cell count field uses the upper nibble of that byte for things other than the cell count, two of those (the top two) being related to mirroring. This is what Chris Benshoof sent me regarding it:

"All the xmas views with mirroring only have two loops, and they all have the same mirror nibble: $C. The upper two bits are two distinct mirror flags; they're tested independently but I don't know their specific purpose. The lower two bits are read as a number and I'm comfortable just assuming that's the loop number."

Maybe @AGKorsson can dig out the debugger and work out why it needs two separate mirror bits, and confirm that the lower two bits really are for the loop number. I know that you'll be interested in this one, if you haven't yet seen it.
Title: Re: AGI v2.230
Post by: lskovlun on June 28, 2026, 04:25:25 AM
In GAL, the movement speed is encoded in each view. You can't set it from the script.
Title: Re: AGI v2.230
Post by: lskovlun on June 28, 2026, 04:40:03 AM
Oh, and the ScummVM patch has the following:
Code: [Select]
                // loop-header:
-               //  celCount:BYTE
+               //  celCount:BYTE [ upper nibble used as mirror data in 2.230 ]
                //  relativeCelOffset[0]:WORD
                //  relativeCelOffset[1]:WORD
                //  etc.
-               byte loopHeaderCelCount = resourceData[loopOffset];
-
-               loopData->celCount = loopHeaderCelCount;
+               byte loopHeaderCelCountByte = resourceData[loopOffset];
+               const bool isMirrorDataInLoopHeader = (getVersion() == 0x2230);
+               if (isMirrorDataInLoopHeader) {
+                       loopData->celCount = loopHeaderCelCountByte & 0x0f;
+               } else {
+                       loopData->celCount = loopHeaderCelCountByte;
+               }
So I think we can assume it's a cel count.
Title: Re: AGI v2.230
Post by: lance.ewing on June 28, 2026, 05:02:13 AM
The lower nibble of that byte is the cell count for the loop. That was the known bit, but interpreters like AGILE assume the whole byte is the cell count.

The original AGI interpreter source that we have from the SQ2 disk has this:

Code: [Select]
/* loop structure
*/
typedef struct loopstrc {
UBYTE numcels; /* number of cels in the loop */
WORD celofs[10]; /* offsets to the cels */
} LOOP;

which also implies the whole thing later became only for the cell count.

But for this earlier 2.230 version, only the bottom 4 bits were the cell count and the top 4-bits were other things, the top 2 being related to mirroring.