Author Topic: KAWAI Opcode  (Read 5736 times)

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
KAWAI Opcode
« on: 2006-06-24 19:19:11 »
It has come to my attention that the KAWAI fieldscript opcode is most likely transcoded wrong. (The fieldscript dumper seems to have it set at 255 bytes)

Can someone root through the FF7 binairy and figure out what the correct egument length is? I would do it, but I'm noodleing with the PSX version and have no R3000 debugger. As far as my PC version goes, I run linux and sorely lack debuging tools on my windows PC.

Also, as a side mention.

I can't seem to "unlzs" the SCEAP.LZS without it bombing. Am I using an old version of lzs? Anyone heard of this bug? I'm cerious to see what's in that.

Cyberman

  • *
  • Posts: 1572
    • View Profile
Re: KAWAI Opcode
« Reply #1 on: 2006-06-24 20:16:27 »
I've a debugger emulator for PCSX I did work on a GUI for it. Not the best but it did work.. sort of :D

It's for Windoze howsumever. It also requires the gnu_gettext.dll (shrug).

Anyhow I have to find the debugger program I made for it if it is to be of much use.

I'll see if I can find where to get the old specs for it, otherwise you need to use telnet to a specific socket to connect to the debugger.

Cyb

dziugo

  • *
  • Posts: 1470
    • View Profile
    • A new copy of FF7 thanks to Salk. Pack (zip/rar/etc) your saved game before sending it to me.
Re: KAWAI Opcode
« Reply #2 on: 2006-06-24 20:58:40 »
The byte after the opcode looks like a size to me. KAWAI... What is it used for anyway?

« Last Edit: 2006-06-24 21:42:52 by halkun »

ChaosControl

  • *
  • Posts: 741
  • ยค
    • View Profile
Re: KAWAI Opcode
« Reply #3 on: 2006-06-24 21:37:58 »
I read KAWAII so thought there was some "cute"-code or something.
Yeah, I am known for my isseus.

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
Re: KAWAI Opcode
« Reply #4 on: 2006-06-24 21:42:33 »

Kawai (The person) was the character animator.

If that helps...

Synergy Blades

  • Guest
Re: KAWAI Opcode
« Reply #5 on: 2006-06-24 23:39:59 »
Further to the enquiry I made that prompted this I've done a little extra digging and as far as I can tell the maximum it could be is 12 arguments. This is based on dataio_8 where the 'materia' script has a KAWAI followed by 12 bytes, before the next script begins (again, based off the script offsets table). I ruled out a number of possibilities using various other field files and have it narrowed down to: 0, 3, 5, 8 or 11 arguments. Any other number and either the KAWAI is too long such that it overruns into the next script, or the script following the KAWAI (which obviously varies given that the remainder of the script depends on how many arguments this opcode has) causes the script to overrun into the next one, due to the number of arguments the remaining commands have being greater than the script size. I expect it's 8 'cos the resulting script 'looks' right - the others all contain a lot of unnecessary RETs since there's a lot of 00s around the opcode.

'course, it could just be some dodgy coding I've done.  :-D But my logic seems to follow with the table offsets, otherwise there'd be at least a huge 255 jump between some of the offsets where a KAWAI appears, but I haven't seen offset shifts anywhere near this value where they have cropped up.

Quote
The byte after the opcode looks like a size to me.

Interesting... having checked a few I see either 05 or 0A as first argument. Subtract 2 (for whatever reason  :-D) and it'd fit my suggested argument count. Is a variable length argument feasible given what you/people know about the scripting?

Btw as far as purpose goes, so far I have only seen this opcode on the following scripts for item pickups: materia, treasure boxes, potions.
« Last Edit: 2006-06-25 00:07:17 by Synergy Blades »

Synergy Blades

  • Guest
Re: KAWAI Opcode
« Reply #6 on: 2006-06-25 00:09:53 »
Further to the enquiry I made that prompted this I've done a little extra digging and as far as I can tell the maximum it could be is 12 arguments. This is based on dataio_8 where the 'materia' script has a KAWAI followed by 12 bytes, before the next script begins (again, based off the script offsets table). I ruled out a number of possibilities using various other field files and have it narrowed down to: 0, 3, 5, 8 or 11 arguments. Any other number and either the KAWAI is too long such that it overruns into the next script, or the script following the KAWAI (which obviously varies given that the remainder of the script depends on how many arguments this opcode has) causes the script to overrun into the next one, due to the number of arguments the remaining commands have being greater than the script size. I expect it's 8 'cos the resulting script 'looks' right - the others all contain a lot of unnecessary RETs since there's a lot of 00s around the opcode.

'course, it could just be some dodgy coding I've done.  :-D But my logic seems to follow with the table offsets, otherwise there'd be at least a huge 255 jump between some of the offsets where a KAWAI appears, but I haven't seen offset shifts anywhere near this value where they have cropped up.

Quote
The byte after the opcode looks like a size to me.

Interesting... having checked a few I see either 05 or 0A as first argument. Is a variable length argument feasible given what you/people know about the scripting?

Btw as far as purpose goes, so far I have only seen this opcode on the following scripts for item pickups: materia, treasure boxes, potions.

Qhimm

  • Founder
  • *
  • Posts: 1996
    • View Profile
    • Qhimm.com
Re: KAWAI Opcode
« Reply #7 on: 2006-06-25 00:28:16 »
The byte after the opcode looks like a size to me. KAWAI... What is it used for anyway?
Pin-pon! Correct answer, KAWAI is a variable-length command. Can't recall what its function is at the moment though. I'd pass you a copy of my script parser/reader/displayer-thingy (which AFAIK correctly decodes all op-codes and also the arguments a fair amount of them), but unfortunately I have misplaced that entire project on another hard drive. Which I have lying around ...somewhere. =\
« Last Edit: 2006-06-25 00:34:25 by Qhimm »

FF7ExpNeg1

  • *
  • Posts: 16
    • View Profile
Re: KAWAI Opcode
« Reply #8 on: 2006-06-25 06:25:11 »
...

Also, as a side mention.

I can't seem to "unlzs" the SCEAP.LZS without it bombing. Am I using an old version of lzs? Anyone heard of this bug? I'm cerious to see what's in that.

To answer your second question, here is some C code I whipped up when I was investigating what SCEAP.LZS was a month back (this code isn't too good, I have a much better way to unlzs this using a 4k buffer so there isn't any compilcated offset instruction).  It does, however, write the uncompressed data to a 640x480 bitmap named "test.bmp". Pass in SCEAP.LZS as the only argument.

Code: [Select]
#include <stdio.h>

typedef unsigned char byte;

int main(int argc, char *argv[])
{
FILE *f;
int out_len; //compressed length
uint size;
byte control;
byte *data;
byte *out;
byte buf[4];
int buf_size;
int read;
int pos;
int control_pos;
int raw_offset;
int marker;
int len;
int i;
byte *flipped, *src, *dest;
FILE *outf;

if (argc != 2) {
printf("lzsexpand -- Uncompress a LZS file\n");
printf("\n");
printf("USAGE: lzsepand [lzs file]\n");
}

f = fopen(argv[1], "rb");
fread(buf, 4, 1, f);
size = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
printf("Size: %d\n", size);

//read in the data
data = (byte*)calloc(size, 1);
read = fread(data, size, 1, f);
printf("Bytes read: %d\n", read);

pos = 0;
out_len = 0;
buf_size = 4096;
out = (byte*)malloc(buf_size);
while (pos < size) {
if (out_len + 8 * 18 > buf_size) {
buf_size += 4096;
out = (byte*)realloc(out, buf_size);
}
control = data[pos];
pos++;
for (control_pos = 0; control_pos < 8; control_pos++) {
if (control & 1) {
out[out_len] = data[pos];
pos++;
out_len++;
}
else {
raw_offset = data[pos] | ((data[pos + 1] & 0xF0) << 4);
len = (data[pos + 1] & 0xF) + 3;
marker = out_len - ((out_len - 18 - raw_offset) & 0xFFF);
pos += 2;

for (i = 0; i < len; i++) {
if (marker < 0)
out[out_len] = 0x00;
else {
out[out_len] = out[marker];
}
out_len++;
marker++;
}
}
control >>= 1;
if (pos >= size)
break;
}
}

/* the lines in the bitmap are upside, after some research
* this is to be expected. allocate enough memory for one
* vertical line and start reversing
* 640 pixels * 2 bytes per pixel = 1280 bytes
*/
flipped = (byte*)malloc(640 * 480 * 2);
dest = flipped;
src = out + 640 * 479 * 2;
for (i = 0; i < 480; i++) {
memcpy(dest, src, 1280);
dest += 1280;
src -= 1280;
}

free(out);
out = flipped;

free(data);
fclose(f);

outf = fopen("test.bmp", "wb");

{
byte header[] = {
0x42, 0x4d, 0x36, 0xb4, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xe0, 0x01,
0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

//calc size real quick
unsigned int fsize = 640 * 480 * 2 + sizeof(header);
header[2] = fsize & 0xFF;
header[3] = (fsize >> 8) & 0xFF;
header[4] = (fsize >> 16) & 0xFF;
header[5] = (fsize >> 24) & 0xFF;

printf("Size of header %X\n", sizeof(header));
fwrite(header, sizeof(header), 1, outf);
}

fwrite(out,  out_len, 1, outf);
free(out);
fclose(outf);

return 0;
}