Points of Required Attention™
Please chime in on a proposed restructuring of the ROM hacking sections.
Views: 88,664,095
Main | FAQ | Uploader | IRC chat | Radio | Memberlist | Active users | Latest posts | Calendar | Stats | Online users | Search 05-25-24 05:51 PM
Guest: Register | Login

Main - Posts by GuyPerfect

Pages: 1 2 3 4 5 6 7 8

GuyPerfect
Posted on 06-30-07 10:54 PM, in Need some ASM hack - SMB3 (with SMB1 Gold Color Animation) Link | Quote | ID: 51072


Paratroopa
Level: 30

Posts: 81/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
Posted by CKY-2K
[...] most likely because they are just opening a program level editor which does all the work for them.

This may be a strange place to mention it, but my favorite hacking pasttime is actually programming the level editor.

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


Paratroopa
Level: 30

Posts: 82/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 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


GuyPerfect
Posted on 07-02-07 04:23 PM, in B.O.B. Hacking Link | Quote | ID: 51601


Paratroopa
Level: 30

Posts: 83/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 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.

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


Paratroopa
Level: 30

Posts: 84/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 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?

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


Paratroopa
Level: 30

Posts: 85/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 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.

GuyPerfect
Posted on 07-03-07 09:57 PM, in Post your tray Link | Quote | ID: 51961


Paratroopa
Level: 30

Posts: 86/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
Being a person with the expertise and desire to keep my computer in good, working condition, I don't clutter it up with a bunch of crap.


GuyPerfect
Posted on 07-03-07 11:20 PM, in Making level editor programs? Link | Quote | ID: 51971


Paratroopa
Level: 30

Posts: 87/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
Basically, editors just do what you would do, except they are capable of performing all of the tasks in one package.

In B.O.B., I had to do a few things to get a graphical representation of the level. 1) I had a list of pointers referencing where in the ROM file I needed to get data from. 2) I had to decompress the level and its panel definitions. 3) I had to decode the tile graphics and palette data. So if I were to edit all of those things, I'd need to re-encode the tile and palette data, re-compress the level and panel data, insert them into the ROM, then change the pointers accordingly.

A level editor for the game would take care of all those things.
__________

So basically, this is what it boils down to:
* You need to know enough about a game's level format that you would be able to change it to make your own levels. Some games will allow you to edit levels in a hex editor; some will require more effort. But if you have the knowledge of what to do, you can start on a level editor.
* You'll need to program routines to take care of any processes that go into extracting data then inserting it into the ROM. Compression codecs, graphics manipulation, and of course level data itself are all common bits of information that level editors use.
* Level editors aren't very useful without some kind of user interface. It's up to you how to best allow the user to manage the level data once your program can take care of it.

GuyPerfect
Posted on 07-04-07 01:49 AM, in Making level editor programs? (rev. 2 of 07-04-07 01:50 AM) Link | Quote | ID: 52000


Paratroopa
Level: 30

Posts: 88/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
What Smallhacker really means is that you'd be better off using a language designed to be able to work with file data to this extent. Game Maker is a very specialized language and it will likely not allow you to do what you need to do if you want to make a level editor.

GuyPerfect
Posted on 07-05-07 07:45 AM, in Making level editor programs? (rev. 2 of 07-05-07 07:47 AM) Link | Quote | ID: 52439


Paratroopa
Level: 30

Posts: 89/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
Reading individual bytes from hard disk is very slow. It'd be better to load the whole ROM into memory and read bytes from there.

...

Dim ROMData() As Byte 'Dynamic array for storing ROM data
Dim ROMSize As Double 'For the file's full size
Dim FileNum As Long 'File number... a BASIC thing.

'Get an unused file number, then open the file
FileNum = FreeFile
Open "ROM.rom" For Binary Access Read As FileNum
ROMSize = LoF(FileNum) 'Get the file's size
ReDim ROMData(0 To ROMSize - 1) As Byte 'Allocate memory
Get FileNum, 1, ROMData 'Load the data from file
Close FileNum
...

Once you do things that way, you can pick out individual bytes from the ROM, even using a base index of 0. ROMData(0) is the first byte of the ROM. You can also use hexadecimal offsets with the &H prefix. For example: ROMData(&HF3B48)

GuyPerfect
Posted on 07-05-07 10:27 PM, in Making level editor programs? Link | Quote | ID: 52565


Paratroopa
Level: 30

Posts: 90/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
That won't work for instances where data is stored big-endian. It's always better to manipulate data manually when it comes to ROM hacking, and having all data in memory is the fastest way to get things done.

GuyPerfect
Posted on 07-05-07 11:34 PM, in I am a moron who doesn't know how to fill in the thread title Link | Quote | ID: 52586


Paratroopa
Level: 30

Posts: 91/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
But the bike's okay, right?

GuyPerfect
Posted on 07-08-07 11:34 PM, in Request Thread Link | Quote | ID: 53292


Paratroopa
Level: 30

Posts: 92/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
*Charges up a shot DBZ-style or summat*

Hey! Who got me to do that?!??!?

GuyPerfect
Posted on 07-10-07 03:47 AM, in Can you hear ultrasonic ringtones on your phone? Link | Quote | ID: 53576


Paratroopa
Level: 30

Posts: 93/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
It's related to age, but indirectly. Namely, there's the fact that the human genome allows for only so much variability (such as height, skin color, etc.) and the exact shape and functions of certain organs won't change from person to person.

In this case, there's the structure of the inner ear. The inner ear of a big person will be just about the same shape of the inner ear of a small person; just bigger. So, uh... which ear do you think will have a better frequency response for higher pitches? Yeah. The smaller ear.

Thing is, when you get older, you tend to grow as well. Grow until, oh... early 20's? The simple fact that your inner ear grows larger results in higher pitches being more difficult to hear.
__________

Personally, I lost perception of sounds above around 18khz when I was 15. I'm a big person (6'5"), and I grew faster than normal. Wisdom teeth are usually the last change to take place in the body before adulthood, and those came in at 17. Most people get them in the 21~24 area.

I can hear when a TV's on, yeah. But I can't much hear that 18.8khz sample.

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


Paratroopa
Level: 30

Posts: 94/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 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;
}
...

GuyPerfect
Posted on 07-12-07 04:41 AM, in Zero Fission/Metroid Zero Mission and Fusion Hacking Link | Quote | ID: 54046


Paratroopa
Level: 30

Posts: 95/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
Technically, the HTTP request can't have a non-angelfire referrer.

GuyPerfect
Posted on 07-12-07 06:16 AM, in Warm Welcome? Link | Quote | ID: 54070


Paratroopa
Level: 30

Posts: 96/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
Posted by Hiryuu
Also had annoying large signatures like he does.

Now, now. No need to talk in past-tense. (-:

GuyPerfect
Posted on 07-15-07 07:06 PM, in LZSS/LZ77 decompressor? Link | Quote | ID: 55194


Paratroopa
Level: 30

Posts: 97/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
I actually posted some self-made LZ77 codec routines in the B.O.B. thread earlier this week. You may have to modify it a bit to suit your needs, but it works and I'm pretty sure it's reasonably optimized.

Link to post

GuyPerfect
Posted on 07-17-07 08:29 PM, in Let's hack NSMB! (To be exact, a level viewer.) Link | Quote | ID: 55721


Paratroopa
Level: 30

Posts: 98/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
Somewhere buried deep in the confines of my endless data archives, I have the information on the NDS ROM file format, complete with checksum algorithm and FAT specification.

What would be neat is if you would implement a file reader in order to view files directly given the ROM. I'd be willing to help out with that.

GuyPerfect
Posted on 07-21-07 03:38 AM, in 24 Hour Reversion Link | Quote | ID: 56331


Paratroopa
Level: 30

Posts: 99/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
DOOOOOOOOM!

/coh humor

GuyPerfect
Posted on 07-21-07 03:41 AM, in 24 Hour Reversion Link | Quote | ID: 56333


Paratroopa
Level: 30

Posts: 100/155
EXP: 152957
Next: 12912

Since: 03-14-07

Last post: 6074 days
Last view: 6023 days
That's just a fancy way of saying the same thing.

Incidentaly, what happened?
Pages: 1 2 3 4 5 6 7 8


Main - Posts by GuyPerfect

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

Page rendered in 0.259 seconds. (338KB of memory used)
MySQL - queries: 137, rows: 169/169, time: 0.249 seconds.