Note: LucasForums Archive Project
The content here was reconstructed by scraping the Wayback Machine in an effort to restore some of what was lost when LF went down. The LucasForums Archive Project claims no ownership over the content or assets that were archived on archive.org.

This project is meant for research purposes only.

AkosView Alpha 1 - Now Available

Page: 1 of 1
 checkmate
03-03-2004, 1:51 AM
#1
The newest, windowed version of AkosView is now here, although it's an alpha version. It doesn't have all the features of the final which I will hopefully release in the near future, but it is functional, so go here (http://www.geocities.com/nosedog2003/) to get it. Have fun browsing, and I hope you find something truly interesting in all that data.
 James Isaac
03-03-2004, 2:56 PM
#2
Great. Thanks :)

Something's happening in the SCUMM Hacking forum :D
 checkmate
03-03-2004, 10:05 PM
#3
New update: AkosView Alpha 2. An off-by-one bug prevents you from viewing the first frame in the costume, so get the new version for the fix.
 jannar85
03-03-2004, 11:13 PM
#4
Hurray!

Btw... it would be easier if SOMEONE implanted it into SR, because it's hard using SR to extract the stuff, then Akos to view :P

Just a suggestion... :P
or if Akos could get the files itself ;)
 checkmate
03-04-2004, 1:20 AM
#5
Getting AkosView to extract costumes from resource files by itself is my top priority right now, followed by getting the frame's position on the screen correct, fixing palette issues in several codec 5 images, and implementing codec 16.

I believe it's also possible to get AkosView to play back animations, but I know almost nothing about the AKSQ blocks, among other things.

I once had some code written that opened SCUMM resource files and found AKOS costumes. Unfortunately, it was flakey, had trouble differentiating SCUMM V8 and V7, and crashed for no reason whatsoever...but the main problem with it is that I LOST IT!:o I'll have to write it again!

It would help if the Index File specification was cleaned up. bgbennyboy's has several innacuracies, I believe (I think it has SCUMM V7 and V8 mixed up somewhat :confused: ). But another source for information is the ScummVM source code, so I'll look into that.

Previously, I detected SCUMM V8 (which uses 32-bit data in some places which V7 used 16-bit) by reading the name of the file opened to see if it said "COMI.LA0".:o But it turns out that the size of the MAXS block is different for the two versions (V8 is 176 bytes, V7 is 138). I could use that:cool:
 checkmate
03-05-2004, 11:57 PM
#6
Now AkosView Alpha 3 is out. I've added support for codec 16 (which I vaguely understand now) and a "zoom" feature for the low-resolution games.
 bgbennyboy
03-06-2004, 10:54 AM
#7
I think my index file specs might have been wrong for DOBJ blocks but I think it was right for V7/V8. I cant check right now, but i'll have a look tomorrow if I get chance. I think I detected the difference between V7/8 in the RNAM block but I cant remember offhand :)
 checkmate
03-06-2004, 3:35 PM
#8
My main concern with your Index File Specs is the definition of the Directory Blocks. It says that SCUMM V8 Directory blocks have this structure:
Block Name (4 bytes)
Block Size (4 bytes BE)
No. of Items (4 bytes)
*Room Number (1 byte)
*Offset (2 bytes)
While the SCUMM V7 Directory blocks are equivalent to SCUMM V5, which looks like this:
Block Name (4 bytes)
Block Size (4 bytes BE)
No. of Items (2 bytes)
*Room Number (1 byte)
*Offset (4 bytes)
Are you sure that the SCUMM V7 Directory blocks use 4 bytes for the Offset field, while SCUMM V8 (which is newer) uses only 2 bytes? Seems to me rather odd...:confused:
 bgbennyboy
03-06-2004, 5:46 PM
#9
You have V7 and V8 the wrong way round there :)

Most blocks in V7 are the same as their V5 equivalents, except for the RNAM, MAXS and the new ANAM block. So most blocks have 2 bytes for the no of items. With V8 its 4 bytes for the no of items.

I've just had a quick look at it and as far as I know the only thing definitely wrong with the index file specs is the DOBJ stuff. The blocksize for it is correct but I dont know what data the blocks contain. I remember having a look at the scummvm source but being ignorant of c++ I got scared.

There's a newer version of the index file specs included with the source to my index file reader by the way, its on 'ere (http://quick.mixnmojo.com).

The easy way to differentiate between V7/V8 is with the RNAM block at the beginning. V8 has room name data while with V7 theres just a blank byte. So:

If blockheader=RNAM
read 4 bytes Big Endian
if those 4 bytes=9 then its v7, if not its v8
 checkmate
03-06-2004, 11:43 PM
#10
I have V7 and V8 the wrong way around? I was copying what IndexFileSpecs.txt said, which I'm pretty sure is backward...:confused: So if I got it mixed up in my previous message, then the Index File Specs does too. You should probably double-check.
 bgbennyboy
03-07-2004, 7:57 AM
#11
Wait, i see what you mean now. I was very tired last night, I thought you were talking about NoOfItems not offsets, thats what I thought I read anyway, sorry about that :~

The best way to check, would be to check those offsets with the resource files. Either both the specs are right or the 4 bytes is actually 2 sets of 2 bytes, ie. 2 bytes=offset 2 bytes=something else.

I'll have a look later when I get chance.

You are definitely right though, you'd expect V8 to use 4 bytes and V5-7 to use 2. Hmmm......
 bgbennyboy
03-07-2004, 8:56 AM
#12
Right, i'm typing this as I do it so bear with me if it looks like gibberish.

First V7 - Full Throttle
In the DSCR the last script according to my program is:

Room Number 174: Offset 38181

In room 174 (The plane hanging over the gorge) the room offset is 81109804, the offset of the last SCRP script is 81147985.

The offsets are relative to the Room's (So it's Script offset - Room offset) 81147985 - 81109804 = 38181, so the index file is right there and the offset is read correctly.

To check I did the same thing with a random costume in DCOS:
Room Number 047: Offset 366182

Room offset is 20708347. So there should be an AKOS at 20708347 + 366182

Sure enough, the 2nd of 3 AKOS' is at offset 21074529, just as the index file says :) So V7 is definately right.


Now V8 with CMI:

Again in DCOS:
Room Number 82: Offset 4207639

That puts it in Comi.LA2 according to the LOFF block in the main resource files. Room offset=70455475. 70455475 + 4207639 = 74663114 - which is WRONG. It should be the 7th costume in the block, but the 7th costume=74663106 - thats out by 8 bytes. I think thats because in V8 the LOFF references LFLF blocks, while in others it references ROOM blocks. That accounts for the 8 bytes difference anyway. Relative to the LFLF block, its correct, relative to the ROOM block its wrong by 8 bytes (the 4 bytes for the LFLF block name + the 4 bytes for the LFLF block size).

I cant check that because I dont really have proper access to my stuff right now i'm just using scummrev2, I seem to remember there being something slightly wonky with the LOFF anyway. So V8 is right too :)

If you cant be bothered to read all that then here's the synopsis: The specs are right, they dont look right, but they are. Hope that helps :)

[Edit] I hope you're going to release the source to this when its done, oh or update your AKOS specs to include codec 16 :)
 checkmate
03-07-2004, 3:36 PM
#13
Thanks!:cool: I think I'll release the source code with the full, non-Alpha version comes out.

As for codec 16, I pretty much copied some bits out of ScummVM.:o But after looking at it carefully, I've drawn up a flow-chart that should help...so with that, I wrote up an implementation by hand. Trouble is, that implementation outputs a pile of pixel gibberish.

I've written a small file that should really help with implementing Bit Streams:

// BitStream.h
// By Nolan Check

#ifndef BITSTREAM_H
#define BITSTREAM_H

#include "AkosView.h"

class BitStream
{
public:
BitStream(BYTE* theBits)
{
bits = theBits;
numBits = 8;
buffer = *bits;
};

BYTE readBits(int count)
{
BYTE result = 0;
for (int i = 0; i < count; i++)
{
if (!--numBits)
{
bits++;
numBits = 8;
buffer = *bits;
}
if (buffer & 1)
{
result |= (1 << count);
}
buffer >>= 1;
}
return result;
};
private:
BYTE* bits;
int numBits;
BYTE buffer;
};

#endif

And my hand-written implementation of codec 16 looks like this:
void AKOS::codec16(BYTE* result)
{
BYTE colorBits = *currentAKCD;
BYTE color = *(currentAKCD + 1);

BitStream stream(currentAKCD + 2);

WORD height = currentAKCI->height;
while (height--)
{
*result++ = color;

if (stream.readBits(1))
{
if (stream.readBits(1))
{
BYTE code = stream.readBits(3);
if (code == 4)
{
BYTE rep = stream.readBits(8);
while (--rep)
{
*result++ = color;
}
}
else
{
color += code - 4;
}
}
else
{
color = stream.readBits(colorBits);
}
}
}
}
Remember: this implementation outputs gibberish, so it's got a bug somewhere. Would anybody like to help me find it??:)
 checkmate
03-07-2004, 4:06 PM
#14
Well, I've just found one bug in the above code. I'm going down the rows too fast. Here's another version, but it's STILL NOT QUITE RIGHT! It still outputs gibberish, though I have to admit, this gibberish is more readable than the previous version.:)
void AKOS::codec16(BYTE* result)
{
BYTE colorBits = *currentAKCD;
BYTE color = *(currentAKCD + 1);

BitStream stream(currentAKCD + 2);

WORD height = currentAKCI->height;
BYTE rep = 0;
while (height--)
{
WORD width = currentAKCI->width;
while (width--)
{
*result++ = color;

if (rep)
{
rep--;
continue;
}

if (stream.readBits(1))
{
if (stream.readBits(1))
{
BYTE code = stream.readBits(3);
if (code == 4)
{
rep = stream.readBits(8);
}
else
{
color += code - 4;
}
}
else
{
color = stream.readBits(colorBits);
}
}
}
}
}
There may also be a problem with my BitStream reader, so that deserves some scrutiny too.
 Serge
03-11-2004, 8:57 PM
#15
I'm not at all sure about this, since I haven't actually added (or looked into) codec layer 16 to the probably-never-to-be-released SCUMMRev 5, but I do know this, from looking at your code:

Layer 16 is similar to MMucus layer 0x40-0x44. Looking quickly over the code (haven't tested it to actually see the output) and comparing to the MMucus code for SR5, you might need to subtract 1 from rep, i.e. rep = stream.readBits(8) - 1;

If the image is skewed in some weird way, that would be it. Since "rep" indicates the number of pixels to repeat the colour for, 1 rep means 1 pixel, which you draw no matter what (*result++ = color;). At least, that's actually how MMucus 0x40 works. I may look a bit more into it.

- Serge
 checkmate
03-12-2004, 8:53 PM
#16
Well, I'm convinced there's a problem with the bitstream reader...that was confusing in the ScummVM source code. This is an implementation that was copied and slightly modified from ScummVM. The Alpha 3 version uses this implementation; it actually works:
#define AKOS16_FILL_BITS() \
if (numBits <= 8) \
{ \
bits |= (*dataPtr++) << numBits; \
numBits += 8; \
}

#define AKOS16_EAT_BITS(n) \
numBits -= n; \
bits >>= n;

void AKOS::codec16(BYTE* result)
{
BYTE* src = currentAKCD;

BYTE unk5 = 0;
int unk6 = 0;
BYTE mask = (1 << *src) - 1;
BYTE color = *(src + 1);
BYTE shift = *src;
WORD bits = (*(src + 2) | *(src + 3) << 8);
BYTE numBits = 16;
BYTE* dataPtr = src + 4;

WORD height = currentAKCI->height;
while (height--)
{
BYTE* curDst = result;

WORD width = currentAKCI->width;
while (width--)
{
WORD lineBits;

*curDst++ = color;

if (!unk5)
{
AKOS16_FILL_BITS()
lineBits = bits & 3;
if (lineBits & 1)
{
AKOS16_EAT_BITS(2)
if (lineBits & 2)
{
WORD tmpBits = bits & 7;
AKOS16_EAT_BITS(3)
if (tmpBits != 4)
{
color += tmpBits - 4;
}
else
{
unk5 = 1;
AKOS16_FILL_BITS()
unk6 = (bits & 0xFF) - 1;
AKOS16_EAT_BITS(8)
AKOS16_FILL_BITS()
}
}
else
{
AKOS16_FILL_BITS()
color = ((BYTE)bits) & mask;
AKOS16_EAT_BITS(shift)
AKOS16_FILL_BITS()
}
}
else
{
AKOS16_EAT_BITS(1)
}
}
else
{
if (!--unk6)
{
unk5 = 0;
}
}
}

result += currentAKCI->width;
}
}
The AKOS16_FILL_BITS and AKOS16_EAT_BITS are rather odd...I'm not sure how the bits are structured in the data.

The implementation I wrote (which doesn't work) reads bits in this order ("1" is the least-significant bit):
Byte 1: 8 7 6 5 4 3 2 1
Byte 2: 16 15 14 13 12 11 10 9
...etc...
 Serge
03-12-2004, 9:14 PM
#17
Originally posted by checkmate
<snip>
The implementation I wrote (which doesn't work) reads bits in this order ("1" is the least-significant bit):
Byte 1: 8 7 6 5 4 3 2 1
Byte 2: 16 15 14 13 12 11 10 9
...etc...

Yes, that would be wrong. Least significant bit should be read first.

AKOS16_FILL_BITS does this:
If there are less than 9 bits left in the bitbuffer, it reads 8 new bits, and places them after (i.e., above in significance) the remaining bits in the buffer, example:

Before FILL_BITS:
Buffer: 0000 0000 0101 0111
BitCount: 8
=>
After FILL_BITS:
---new--- ---old---
Buffer: 1010 1010 0101 0111
BitCount: 16

AKOS16_EAT_BITS quite simply discards n bits from the buffer, as if they'd been read (i.e., the n least significant bits).

Also notice that, yes, you subtract one from the rep variable:
unk6 = (bits & 0xFF) - 1;

- Serge
 Serge
03-12-2004, 9:25 PM
#18
In more simple terms, you just read the bitstream byte by byte, and fetch the bits with the least significant bit first, so in the above example you should get the bits in the following order:

1110 1010 0101 0101

(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...)
 Ender
03-13-2004, 12:43 AM
#19
Originally posted by checkmate
Well, I'm convinced there's a problem with the bitstream reader...that was confusing in the ScummVM source code. This is an implementation that was copied and slightly modified from ScummVM. The Alpha 3 version uses this implementation; it actually works:
[/CODE]

And remember, if you borrow any code from ScummVM, you must GPL your own program :)

I need to add AKOS viewing functionality to ScummEx.
 checkmate
03-13-2004, 7:10 PM
#20
It's not like I just copied the whole thing over from ScummVM, just that it's too similar for my liking...and it still doesn't help me understand it.
 Serge
03-13-2004, 9:46 PM
#21
Well, did my length posts help anything? Since I'll gladly help more, if needed. May not be the best explanation in the world, I gave.

- Serge
 checkmate
03-14-2004, 12:23 AM
#22
Ai-yai-yai! I understand your post, now I'm just trying to make the BitStream reader go "in reverse"! Unfortunately, it's more difficult than I thought...

This obviously isn't correct (it still outputs trash), but it's what I've got so far:
BYTE readBits(int count)
{
BYTE result = 0;
for (int i = 0; i < count; i++)
{
if (!--numBits)
{
bits++;
numBits = 8;
buffer = *bits;
}
if (buffer & 0x80)
{
result |= (1 << (count - (i + 1)));
}
buffer <<= 1;
}
return result;
};
 Serge
03-14-2004, 1:17 PM
#23
Yeah, that's still the wrong order - don't know if I misinterpreted you in the previous post or not...

You need to read the bits right to left (which is also simpler), so (I'm not C-literate, there may be errors inhere):

BYTE readBits(int count)
{
BYTE result = 0;
for (int i = 0; i < count; i++)
{
if (!--numBits)
{
bits++;
numBits = 8;
buffer = *bits;
}
if (buffer & 1)
{
result |= (1 << i);
}
buffer >>= 1;
}
return result;
};


Quickly edited, this, so I may be thinking wrong, but try it... Also, it's not optimized. It might be faster to ensure enough bits are in the buffer, and then drop the for-loop, and simply do something like:
byte mask = (1 << count) - 1; // (1 << x) - 1 yields a result of (in binary) x 1's,
// so for a count of 4: 1 << 4 = 10000b. 10000b - 1 = 1111b
result = buffer & mask; // so now we have a mask for the number of bits we need.
buffer >>= count; // ... and we just shift right by count to get rid of the read bits.
 checkmate
03-14-2004, 3:53 PM
#24
Hooray!:D Thanks for your help. I misinterpreted your post and thought the bits were supposed to be read in reverse order...wrong.

And I also discovered a bug in the code I had to start with...I was doing (1 << count) instead of (1 << i). Why didn't that just jump out at me??:o Could've saved us a lot of trouble.

Codec 16, it turns out, is actually one of the Background Image codecs.
 Serge
03-15-2004, 1:46 AM
#25
Yes, it's a background image codec, as I mentioned:

Originally posted by Serge
I'm not at all sure about this, since I haven't actually added (or looked into) codec layer 16 to the probably-never-to-be-released SCUMMRev 5, but I do know this, from looking at your code:

Layer 16 is similar to MMucus layer 0x40-0x44.
 Mr Flibble
03-16-2004, 8:54 PM
#26
Sorry to detract from the intelligent conversation but, how do you save or copy the cels?
I know with the original, you press F1, but the original doesn't work for me.
Is this some fault of mine, or a feature overlooked.

*Prepares for harsh jibes, mockery*
 checkmate
03-16-2004, 10:53 PM
#27
I haven't added a "save as bitmap" feature yet.:o I guess I'd better get to work on it!
 checkmate
03-17-2004, 9:48 PM
#28
I didn't realize anybody needed it anytime soon. But if you wanted it, Mr. Flibble, you got it! AkosView Alpha 4 adds support for image saving (as PNG rather than BMP).
 Mr Flibble
03-19-2004, 9:59 AM
#29
Ah, thank you.
Blast fax kudos all round.
Now...my plan can come to fullition! MWA HA HA HA!

*coughs politely*
I mean thank you.

You can tell I'm from the MI board can't you?
 checkmate
03-25-2004, 4:27 PM
#30
New version (Alpha 5), and I've released the source code!
 checkmate
03-27-2004, 1:00 AM
#31
Yo! Would anybody like to comment on the source release?:D
 bgbennyboy
04-02-2004, 4:31 PM
#32
Nice one Nolan, its always great when people release the source :)

It helps everyone in the long run and helps new people to get involved, well done :)
 checkmate
04-04-2004, 4:02 PM
#33
You'll notice that I have a skeleton for an index file reader. Gotta complete it sometime...
Page: 1 of 1