Romhacking => Programming => Topic started by: nilsontc on June 05, 2020, 06:00:05 pm

Title: Glitching SNES RAM with LUA - how to avoid disabling sound
Post by: nilsontc on June 05, 2020, 06:00:05 pm
Hi all - possibly a difficult (or impossible) question to answer, but I've been using lua scripts with NES games for awhile now to randomly corrupt bits of data in the RAM to create glitchy visuals and also audio. I started using the script with SNES games, but the SNES memory map feels pretty complicated to me. While I can get some pretty good visuals after awhile, I notice that one of the first things that happens is that the game's audio gets disabled pretty early on in the glitch. I've looked at the differences between Lo and HiROMs, but what addresses do you think I should avoid to not disable the audio? I've been working with 0x2000 - 0x7FFF. I usually go through hundreds - thousands of corrupted addresses, so it's hard to pinpoint exactly what's going on. For instance, Super Mario World pretty consistently gets its audio turned off long before any graphic glitches occur. Should I just bump up or down my target? Does it depend on the game?

Obviously there are several thousand factors, but any insight into a pattern/standard would be appreciated!
Title: Re: Glitching SNES RAM with LUA - how to avoid disabling sound
Post by: Raeven0 on June 05, 2020, 08:24:53 pm
Useful technical context: The SNES CPU has to feed a complete audio program to the sound sub-system through a bizarrely complex handshake protocol. After it does so, the sound sub-system runs independently. This means that corruption of audio data is dangerous -- it's easy to break the handshake and/or the program logic, and once you do so, the audio sub-system cannot recover.

There is no way to predict where audio data is stored in either RAM or ROM. I, personally, would not put them in RAM $7e0000 - $1fff or in ROM above $8000 in any bank, but most programmers are not me.

However, are you sure that your script is writing RAM/ROM, not writing to the literal address you specify? Addresses $2000 - $7fff in banks $00-$3f and $80-$bf map to various hardware element controllers, not to console RAM or cartridge ROM. In particular, $2140 - $217f in those banks map to audio processor I/O ports. A write to e.g. $012144 will go to the sound sub-system, and depending on the audio program may do nothing at all or may irreparably corrupt the program.
Title: Re: Glitching SNES RAM with LUA - how to avoid disabling sound
Post by: nilsontc on June 08, 2020, 11:55:11 am
Thank you for the reply! I'll have to try some more experiments with the targets.

I'm looking at this right now:

and looking at the different banks (which is part of my confusion). This is a dumb question but how do you point to the specific banks? For instance, bank $00–$3F $8000-$FFFF, written out? Is that a thing? Coming from NES, I didn't even realize there were multiple $7FFFs.
Title: Re: Glitching SNES RAM with LUA - how to avoid disabling sound
Post by: Raeven0 on June 09, 2020, 11:02:00 pm
The SNES has a 24-bit address bus, supporting addresses $000000 to $ffffff. In a debugger or RAM editor etc. you should be able to specify the full 6-character address, so e.g. you can point a good memory viewer at $7fff = $007fff and at $137fff and see that they have the same value, being (as they are) two different addresses for the same physical location. The processor handles the top 8 bits separately from the bottom 16, making the address space more like 256 banks of non-contiguous 16-bit regions. I don't know a convenient way to indicate 16-bit ranges in multiple banks other than explicitly "addresses above $8000 in banks $00-$3f" or similar.

Memory map tables like your link, I think, are working from the wrong direction. What's important is that some combinations of address bits are endowed with special meaning, and different areas of the memory map are address ranges that do or do not have special bits set. If the top 7 bits are %0111111, the address points to RAM, so the RAM range is $7e0000 - $7fffff. Otherwise, if bit-15 or bit-22 is 1, the address goes to the cart; so addresses above $8000 in any bank, as well as all of banks $40-$7d and $c0-$ff, are ROM or cart SRAM. Addresses that aren't RAM and with bit-15 and bit-22 = 0 go to console hardware controllers.

I don't know what kind of script etc. you're using, so I can't really guess how it works. If it hooks the SNES address bus, things work the way I've described, and a write to say $002144 goes to SNES hardware, specifically the audio system. If you're injecting instructions into the code, things will work as I describe if you use 24-bit addressing like sta $002144, but not necessarily so with 16- or 8-bit addressing (sta $2144 writes to $2144 in the bank stored in the Data Bank Register, sta $44 writes in bank $00 to $44 + the address stored in the Direct Page register).