Dwedit / PocketNES

NES emulator for GBA
49 stars 10 forks source link

flags and sprite/mem follow ROM header data is ignored in a single game compilation #5

Open patters-match opened 2 years ago

patters-match commented 2 years ago

With an EZ-Flash IV flashcart, it's a common scenario to build an emulator+rom compilation for each individual ROM since the emulator can exit back to the flashcart menu and then the game load is nearly instant, rather than copying megabytes of data to PSRAM before execution. Also there will be plenty of room for save states in the SRAM without contention from other games, and the additional storage space isn't an issue with an SD card.

When a single rom is added to PocketNES like this, the emulator ignores the ROM flags and sprite/mem follow values from the ROM header. If you add more than one ROM it's fine. I discovered this while writing my own PocketNES builder script here: https://github.com/patters-syno/gba-emu-compilation-builders

This behaviour can also be observed using PocketNES Menu Maker to build a single ROM compilation, so it's not caused by my own code. I have verified that the ROM header data in the compilation is consistent with the expected values, so it seems that the emulator isn't acting on this information for some reason. Perhaps it's dependent on the game list selection code, but it probably shouldn't be.

Dwedit commented 2 years ago

That bug was probably introduced when I rewrote the ROM menu to run in the background.

Anyway, if you're creating a PocketNES builder, try to have the ROM data bytes (after the header) be aligned to a 256 byte boundary.

The branch instructions are using the physical address of the code to detect if a branch instruction crosses a page (256 byte boundary), and thus have it consume one more CPU cycle.

For games 256K and under, this doesn't matter as the entire ROM gets copied into RAM at an aligned address. But big games are executed in place, and need the 256 byte alignment for accuracy. The Fixed Bank of a ROM is still copied into VRAM to make the game run faster, so it's always aligned.

patters-match commented 2 years ago

Thanks, I hadn't really considered byte alignment. I had left some code in there from much more simple old Python 2 builder scripts Kuwanger had written which I think had aimed for 4 byte alignment. However it looks wrong. He wrote: rom = rom + b"\0" * (len(rom)%4)

However, by my own reckoning that ought to be: rom = rom + b"\0" * ((4 - (len(rom)%4))%4)

For 256 byte alignment of rom data (after PocketNES rom header and .nes header) that would become the following: rom = rom + b"\0" * ((256 - ((len(rom) + EMU_HEADER)%256))%256) ...provided that the very first ROM's data was also aligned (which needs pocketnes.gba to be slightly padded such that pocketnes.gba + EMU_HEADER + NES_HEADER is 256 byte aligned)

I don't seem to be able to pad the emulator binary for the other emulators though, which implies that the first ROM in the compilation will be suboptimal, which is bad for the EZ-Flash IV since a new compilation is made for each game. Any obvious solution? Is this same byte alignment desirable for the other emulators, or is it specific to PocketNES?

Dwedit commented 2 years ago

It's just PocketNES (6502). The other emulators don't have a branch instruction that checks for crossed pages.