Points of Required Attention™
Smaghetti, a new Super Mario Advance 4 editor, is currently in development! Check out the thread HERE!

Please chime in on a proposed restructuring of the ROM hacking sections.
Views: 88,316,071
Main | FAQ | Uploader | IRC chat | Radio | Memberlist | Active users | Latest posts | Calendar | Stats | Online users | Search 03-29-24 07:16 AM
Guest: Register | Login

0 users currently in ROM Hacking | 2 guests | 1 bot

Main - ROM Hacking - B.O.B. Hacking New thread | New reply


GuyPerfect
Posted on 07-02-07 05:10 AM (rev. 5 of 07-02-07 05:15 AM) Link | Quote | ID: 51440


Paratroopa
Level: 30

Posts: 82/155
EXP: 152257
Next: 13612

Since: 03-14-07

Last post: 6017 days
Last view: 5966 days
Someone's hacking B.O.B.? You bet. You've probably never heard of it. Or maybe you just saw its title at the top while looking for other ROMs, but B.O.B. is indeed a game and it is indeed one of my favorites. You'll have to look it up to find out more about it. THIS thread is about hacking that game.

Anyhow, I'm still fighting with pointers, but I have enough to get the first two levels decoded, more or less. I generated some images! They're at the bottom of the post.

Now, before I go and spam the thread with all my hacking notes, I'm gonna ask if anyone cares. Otherwise, I'll do my thing and post progress just in case. But if anyone's interested in this, do tell!

I'll be making a level editor for sure. Items and enemies aren't shown in these maps, but I know how those are stored. I just didn't plot them.
__________

Click the name for a big version.

Stage 1


Stage 2


CKY-9K
Posted on 07-02-07 05:16 AM Link | Quote | ID: 51441


Pokey
Level: 57

Posts: 40/693
EXP: 1427195
Next: 58733

Since: 06-27-07
From: cKy

Last post: 182 days
Last view: 90 days
Nice work!

____________________








Raccoon Sam
Posted on 07-02-07 08:49 AM Link | Quote | ID: 51527


Cobrat
Level: 56

Posts: 254/672
EXP: 1376932
Next: 21244

Since: 02-19-07
From: Hi

Last post: 3439 days
Last view: 2670 days
B.O.B. Isn't he the orange robot... thing?
Nonetheless, any development on a level modification utility is admirable, and so it this. Great work!

____________________


Squash Monster
Posted on 07-02-07 01:49 PM (rev. 2 of 07-02-07 01:50 PM) Link | Quote | ID: 51583


Buster Beetle
Level: 48

Posts: 215/469
EXP: 802644
Next: 20899

Since: 02-22-07
From: New York

Last post: 5668 days
Last view: 5668 days
DUDE! I was talking about how much a hack could help this game just the other day.

This game would be completely awesome if the levels didn't keep getting longer and it wasn't full of gotchas. You totally need to keep this up so somebody can fix it up and turn it into that completely awesome game.


It looks like it's made of large tiles. Amirite?

____________________

Raccoon Sam
Posted on 07-02-07 02:41 PM Link | Quote | ID: 51589


Cobrat
Level: 56

Posts: 259/672
EXP: 1376932
Next: 21244

Since: 02-19-07
From: Hi

Last post: 3439 days
Last view: 2670 days
32 x 32, unless I'm mistaken.

____________________


setz
Posted on 07-02-07 04:06 PM Link | Quote | ID: 51597


Spike
fuck~
Level: 58

Posts: 521/722
EXP: 1533455
Next: 44091

Since: 02-19-07
From: Pittsburgh, PA

Last post: 5262 days
Last view: 2549 days
so which version are you hacking?

____________________

GuyPerfect
Posted on 07-02-07 04:23 PM Link | Quote | ID: 51601


Paratroopa
Level: 30

Posts: 83/155
EXP: 152257
Next: 13612

Since: 03-14-07

Last post: 6017 days
Last view: 5966 days
I'll reply to the posts in order, since they're kinda interleaved.

CKY-2K:
Hey, thanks!

Raccoon Sam:
More of a musty yellow, but yeah.

Squash Monster:
Hey, I like the gotchas. Like that 1up in level... one of the plant levels before the first boss. You jump for the 1up and one of those ceiling-latchers chomps down on your face. That one's classic. Or the occasional item hovering over the "too deep to jump out of" danger pits...

But yeah, near the end of the game you get nothing but screens full of enemies. Bouncing dots FTW. One of the things I'd like to do is keep the same levels, but just delete a lot of the enemies.

I also find that the bosses get a bit too extravagant. The final boss flings you against the screen six ways 'til Tuesday and still isn't done. I'm thinking of maybe replacing some of the boss levels with bonus stages or more car levels. That'd be fun.

Raccoon Sam:
Yup. It's comprised of 32x32 "panels" which are themselves built of 4x4 tiles.



Panel number 0xFF doesn't actually exist. In the image, I just filled in that spot with empty pixels. When the game encounters panel 0xFF, it reads the next byte as the real panel, and the byte after THAT as an object existing in the same location, such as a power-up, enemy, moving platform, exit, etc.

setz:
US version of the SNES right now. By the looks of things, the game was designed for this system and was ported to Genesis. I'm considering making the level editor support the Genesis versions as well, but that depends on differences between the game's builds.

Sonicandfails
Posted on 07-02-07 07:08 PM Link | Quote | ID: 51631


Lantern Ghost
Level: 60

Posts: 637/766
EXP: 1675779
Next: 96999

Since: 02-19-07

Last post: 5936 days
Last view: 5742 days
I don't know about you, but I kind of hope the tile picker isn't like that screenshot. It always takes so long to find the correct corresponding tile and I hate editors that use it.

____________________
I miss post headers more.

Raccoon Sam
Posted on 07-02-07 08:34 PM Link | Quote | ID: 51642


Cobrat
Level: 56

Posts: 260/672
EXP: 1376932
Next: 21244

Since: 02-19-07
From: Hi

Last post: 3439 days
Last view: 2670 days
Posted by Sonicandfails
I don't know about you, but I kind of hope the tile picker isn't like that screenshot. It always takes so long to find the correct corresponding tile and I hate editors that use it.


This man speaks the truth. Give him a medal.

Tile picking has always been a problem in just about each level editor I've used. If anything should be done, a separate window where the hacker can organize all of the tiles used, and X-flip and Y-flip them through key combinations of such.

____________________


Sonicandfails
Posted on 07-02-07 09:32 PM Link | Quote | ID: 51647


Lantern Ghost
Level: 60

Posts: 638/766
EXP: 1675779
Next: 96999

Since: 02-19-07

Last post: 5936 days
Last view: 5742 days
I turned on Genesis Plus on my Wii and loaded up B.O.B.

Pretty neat game, but it seems hindered by the Genesis, I'll have to try the SNES version.

____________________
I miss post headers more.

Squash Monster
Posted on 07-02-07 09:44 PM Link | Quote | ID: 51652


Buster Beetle
Level: 48

Posts: 220/469
EXP: 802644
Next: 20899

Since: 02-22-07
From: New York

Last post: 5668 days
Last view: 5668 days
The gotchas where it was just pwning you for going after a powerup were mostly okay. I was thinking more of the times where you're just cruising through a level and then BAM, something takes off half your life without warning.

If you feel like having a good tile picker, try making a tabbed box. One tab has every tile in order. The others are set up to be organized by the hacker as desired. This solves both of the problems with tile pickers: organization to fix how you can never find anything, tabs to fix how you can never get to anything reasonably fast.

____________________

iamstillhiro1112
Posted on 07-02-07 09:53 PM Link | Quote | ID: 51654


Paragoomba
Level: 20

Posts: 59/66
EXP: 42319
Next: 120

Since: 03-09-07

Last post: 6091 days
Last view: 6082 days
Good to see another classic game getting attention.

GuyPerfect
Posted on 07-02-07 11:43 PM (rev. 2 of 07-02-07 11:44 PM) Link | Quote | ID: 51688


Paratroopa
Level: 30

Posts: 84/155
EXP: 152257
Next: 13612

Since: 03-14-07

Last post: 6017 days
Last view: 5966 days
First off, "tile" is a technical term for the system and it is inappropriate to use it to describe the blocks that the levels are made up of. Yes, the levels are technically made of tiles if you go down far enough, but that's all the way to the little 8x8-pixel squares. The main unit for the levels is a 4x4-tile square, which itself cannot be called a tile. I'm using the word "panel," but if there's some better word for it, let me know.
__________

As far as how to pick and choose from these pieces of map, my hands are tied. The 16x16 image I put in my last post is the "underground complex" set and is shared between all levels that use the same tiles for graphics. If you move or edit any of them, you'll be affecting several levels in the game.

As was suggested, there should be a sort of user-defined setup to make things easier to work with. What you see in that image is the programmer's convenience; you can tell the level designer actually picked from that list since parts of it are laid out so neatly.

Ideally, hacking will uncover the method used to determine which graphics are spliced together where to make which courses, allowing for all courses to have their own individual set, but I don't yet know enough about the game's inner workings for that to be possible.

Also, the game reads level chunks out of RAM as they appear in the image; esentially blitting them into VRAM. All you can do is tell it which one to do. You can't flip them without redefining them.
__________

Oh, and I can't help but wonder... Had there not been any images shown, who would have still posted anyway?

Sonicandfails
Posted on 07-03-07 12:16 AM Link | Quote | ID: 51692


Lantern Ghost
Level: 60

Posts: 642/766
EXP: 1675779
Next: 96999

Since: 02-19-07

Last post: 5936 days
Last view: 5742 days
Posted by GuyPerfect
First off, "tile" is a technical term for the system and it is inappropriate to use it to describe the blocks that the levels are made up of. Yes, the levels are technically made of tiles if you go down far enough, but that's all the way to the little 8x8-pixel squares. The main unit for the levels is a 4x4-tile square, which itself cannot be called a tile. I'm using the word "panel," but if there's some better word for it, let me know.



You need to seriously consider getting over yourself.

And I would have still posted after I tried out B.O.B. on my Wii.

____________________
I miss post headers more.

Squash Monster
Posted on 07-03-07 01:16 AM Link | Quote | ID: 51702


Buster Beetle
Level: 48

Posts: 221/469
EXP: 802644
Next: 20899

Since: 02-22-07
From: New York

Last post: 5668 days
Last view: 5668 days
I would've still posted. Does it really matter though?


And your hands aren't tied on how to choose the pieces of map. Just because you can re-arrange their order in a tile editor doesn't mean you have to re-arrange their order in the actual game. Just keep an array that says what each position in your tile picker refers to in real tiles.

____________________

GuyPerfect
Posted on 07-03-07 01:43 AM (rev. 2 of 07-03-07 01:48 AM) Link | Quote | ID: 51713


Paratroopa
Level: 30

Posts: 85/155
EXP: 152257
Next: 13612

Since: 03-14-07

Last post: 6017 days
Last view: 5966 days
Posted by GuyPerfect
As was suggested, there should be a sort of user-defined setup to make things easier to work with.

What I really meant with that was a blanket concept for "anything to make life easier" such as what you mentioned.

smkdan
Posted on 07-03-07 04:49 AM Link | Quote | ID: 51759


Ninji
Level: 36

Posts: 44/238
EXP: 287992
Next: 20118

Since: 05-26-07

Last post: 4034 days
Last view: 3983 days
Looks like you have it sorted out pretty well.

As mentioned before, advanced tile arrangement utilities would be great. Like arranging these 4x4 tile panels and constructing larger objects which could be copied in chunks to the main map and be saved or later use. Trackdes suffers so much from having a simple 8x8 tile picker since you have to do an awful lot of messing around to see what tiles fit with the others. Making a smooth curve complete with rumble strip is a real chore.



GuyPerfect
Posted on 07-11-07 02:44 AM (rev. 6 of 07-11-07 03:15 AM) Link | Quote | ID: 53762


Paratroopa
Level: 30

Posts: 94/155
EXP: 152257
Next: 13612

Since: 03-14-07

Last post: 6017 days
Last view: 5966 days
Woo hoo! An update!

B.O.B. stores many of its files in a simple LZ77 format. The first byte is a chunk header; 8 bits describing how to process the next 8 pieces of information. If the bit is a 0, the next piece is a literal byte and is copied from the input buffer to the output buffer. If the bit is a 1, the next two bytes are read as a distance/length pair.

The format of the distance/length pair is a 16-bit, unsigned, little-endian number. The first 5 bits of which are the length-3, the remaining 11 bits of which are the distance. Take note that the distance can potentially hold a value of 0. This is an error on the programmer's part, as distance in an LZ77 stream should NEVER be zero, else an error is thrown.

Once all 8 pieces are read, the next byte will be another chunk header and the whole process starts over again.
__________

Turns out B.O.B.'s programmer made a mistake when he was programming his LZ77 compressor. It's a common mistake, but makes a difference. He failed to compensate for the fact that Length can be greater than Distance in a distance/length pair. Since every byte copied increases the size of the output buffer, Length can be an arbitrarily long value regardless of Distance, since it will never run out of bytes to copy. Doing things this way will result in a sequence of bytes repeated a number of times; much like an RLE compression.

When data is compressed using the above more-optimal technique, the B.O.B. programming is still able to decode the data, so it is in fact something the programmer overlooked.
__________

A few things can happen while decompressing data in B.O.B.:
* Distance could be 0, which will render decompression impossible.
* Distance could be greater than the number of bytes in the output buffer, which also renders decompression impossible.
* Length could instruct data to be decompressed past the target file length, which will not cause an error, but might signify corrupted data.
__________

Anyhow, I wrote some code and verified all of this today. Here are two functions, lzDec and lzEnc, which process data streams according to the B.O.B. variant of LZ77. DecLen is the length of the decompressed data (final file size for decompression and original file size for compression), Src is a pointer to the first byte of the input buffer and Dst is a pointer to the first byte in the output buffer.

* lzDec will return 0 if an error occurs, or the size of the compressed file if successful.
* lzEnc will return the number of bytes in the compressed file once it's completed.

Let's say you have the ROM loaded, and have a 0x822 byte file at offset 0x1AD34... You'd use this syntax:
lzDec(0x822, &(ROMData[0x1AD34]), DecompressedData);

So without further ado:

...

// Decodes a data stream to B.O.B.'s specifications
unsigned int lzDec(unsigned int DecLen,
unsigned char *Src, unsigned char *Dst) {
unsigned int sOff = 0, dOff = 0, Temp, Dist;
unsigned char cHdr, Bit, BitVal, Leng;

// Keep going 'til it's all decoded
while (dOff < DecLen) {
// Chunk header
cHdr = Src[sOff]; sOff++;

// Cycle through bits
for (Bit = 0; Bit < 8; Bit++) {
BitVal = (cHdr >> (7 - Bit)) & 1;

// Literal
if (BitVal == 0) {
Dst[dOff] = Src[sOff];
sOff++; dOff++;

// Distance/length pair
} else {
Temp = Src[sOff] | (Src[sOff + 1] << 8);
Dist = Temp & 0x7FF;
Leng = (Temp >> 11) + 3;
sOff += 2;

// Prevent out of bounds for bad data
if (Dist > dOff || Dist == 0) return 0;

// Copy Length bytes from output buffer
for (Temp = 0; Temp < Leng; Temp++) {
Dst[dOff] = Dst[dOff - Dist];
dOff++; if (dOff == DecLen) break;
} // for
} // if
if (dOff == DecLen) break;
} // for
} // while

// Return size of packed data
return sOff;
}

// Encodes a data stream to B.O.B.'s specifications
unsigned int lzEnc(unsigned int DecLen,
unsigned char *Src, unsigned char *Dst) {
unsigned int sOff = 1, dOff = 2, HdrOff = 0, Temp;
unsigned char cHdr = 0, Bit = 1, tLen;
unsigned int mDist, MaxLeng, mOff, LongLeng, LongDist;

// Write the first byte as literal
Dst[1] = Src[0];

// Encode until done
while (sOff < DecLen) {
// Calculate starting distance
if (sOff < 0x7FF) mDist = sOff;
else mDist = 0x7FF;

// Find the longest match
LongLeng = 0;
for (mOff = sOff - mDist; mOff < sOff; mOff++) {
// Match was found; find its length
if (Src[mOff] == Src[sOff]) {
// Calculate maximum possible length
MaxLeng = DecLen - mOff;
if (MaxLeng > 0x22) MaxLeng = 0x22;

// Scan bytes and check reported length
for (tLen = 1; tLen <= MaxLeng; tLen++)
if (Src[mOff + tLen] != Src[sOff + tLen]) break;
if (tLen > MaxLeng) tLen = MaxLeng; // For loop quirk

// If this is the longest match so-far, record it
if (tLen >= LongLeng) {
LongLeng = tLen;
LongDist = sOff - mOff;
} // if
} // if
} // for

// Literal byte
if (LongLeng < 3) {
Dst[dOff] = Src[sOff];
dOff++; sOff++;

// Distance/length pair
} else {
Temp = LongDist | ((LongLeng - 3) << 11);
Dst[dOff] = Temp & 0xFF;
Dst[dOff + 1] = (Temp >> 8);
cHdr |= (0x80 >> Bit);
dOff += 2; sOff += LongLeng;
}

// Write out a chunk header if needed
Bit++;
if (Bit == 8) {
Dst[HdrOff] = cHdr;
cHdr = 0; Bit = 0;
HdrOff = dOff; dOff++;
}

} // while

// Write the last chunk header if needed and return output size
if (Bit > 0) Dst[HdrOff] = cHdr;
return dOff;
}
...

Squash Monster
Posted on 07-11-07 05:07 AM Link | Quote | ID: 53803


Buster Beetle
Level: 48

Posts: 241/469
EXP: 802644
Next: 20899

Since: 02-22-07
From: New York

Last post: 5668 days
Last view: 5668 days
Posted by GuyPerfect
Turns out B.O.B.'s programmer made a mistake when he was programming his LZ77 compressor. It's a common mistake, but makes a difference. He failed to compensate for the fact that Length can be greater than Distance in a distance/length pair. Since every byte copied increases the size of the output buffer, Length can be an arbitrarily long value regardless of Distance, since it will never run out of bytes to copy. Doing things this way will result in a sequence of bytes repeated a number of times; much like an RLE compression.

When data is compressed using the above more-optimal technique, the B.O.B. programming is still able to decode the data, so it is in fact something the programmer overlooked.
Hahaha. I remember this mistake. The GBA Fire Emblems do exactly the same thing. And I remember it being easier to compress them taking advantage of this than it was to compress them not. I have no idea why it'd be a common mistake.

They didn't have the distance can be 0 problem though: their distances were actually 1+(whatever was stored), which also makes the compression a non-noticeable amount better.

____________________

Main - ROM Hacking - B.O.B. Hacking New thread | New reply

Acmlmboard 2.1+4δ (2023-01-15)
© 2005-2023 Acmlm, blackhole89, Xkeeper et al.

Page rendered in 0.029 seconds. (348KB of memory used)
MySQL - queries: 127, rows: 166/166, time: 0.018 seconds.