I've searched everywhere but can't find an answer to this. Do any games execute instructions from outside of 0x8000-0xFFFF? I'm writing my cpu and memory handler now and I need to squeeze all the speed I can out of them. I ran into this problem when running blargg's instr-test-v3 single test roms and executing from cpu ram.
runaway pancake wrote:
I've searched everywhere but can't find an answer to this. Do any games execute instructions from outside of 0x8000-0xFFFF? I'm writing my cpu and memory handler now and I need to squeeze all the speed I can out of them. I ran into this problem when running blargg's instr-test-v3 single test roms and executing from cpu ram.
I know there are probably quite a few that execute out of SRAM. For example:
The red lines in the dark yellow band just above the line directly in the middle are the CPU executing out of SRAM when running Zelda. The image is a 256x256 matrix of the CPU memory space. The bottom half is cartridge memory [$8000-$FFFF]. SRAM is just above that, and takes up the bottom quarter of the top half [$6000-$7FFF].
The yellow dot-dash pattern in the middle of the top half is the APU registers [$4000-$4017]. Above that, the PPU registers [$2000-$2007]. Finally at the very top, CPU RAM [$0000-$0800]. Of course, I'm sure there's games that execute out of RAM, too.
Technically speaking, games could execute out of any portion of memory they want. There is no enforced boundaries on the PC, it operates in the 16-bit range, and all values are valid.
As to how many games ACTUALLY do this, I can only speculate that it's very few.
But for accurate emulation, the PC should be allowed to point to any address in the 16-bit range. And fetch instructions from where it happens to be pointing.
Side note:
@cpow, is that tool color coded by access frequency?
beannaich wrote:
Side note:
@cpow, is that tool color coded by access frequency?
Sort Of^TM.
EDIT: The red/green/yellow/cyan/magenta coloring represent different CPU accesses. Instruction fetching, memory read, memory write, DMA to PPU, DMA for APU.
It has a fade-out so accesses further in the past appear darker than accesses closer to the present. Much like ICU64's display of the same from the C=64 emulator.
It'd be interesting to change it to frequency though...perhaps I'll play with that.
Multicart engines and games with 32 KiB bankswitching are likely to execute code from RAM, as it's the most reliable place to put a trampoline for switching banks. The protection for Earthworm Jim 2 has a really convoluted way of constructing a mapper driver at the end of RAM. And some of the later games point the NMI vector at RAM so that they can change NMI handlers in mid-game.
@cpow:
Thanks for the tip. I checked out Zelda and it starts executing out of SRAM almost immediately
@beannaich:
I know there's no contraints on the PC, but I need to cut as many corners as I can.
@tepples:
Interesting. I figured it would be rare, but that makes sense for the 32KB bank switching.
Thanks everyone.
metroid seems to execute out of SRAM too.
Bart Vs Space Mutants copies and runs code from RAM too. Some emulators don't properly handle MMC5's ExRAM which is mapped at $5C00 to $5FFF, as I discovered while making a hack that wanted to use ExRAM as storage for executable program code. You may be able to gain some performance by being less flexible but you must figure out if that is worth the performance gain. On a typical platform like PC, it is not. But on others like mobile devices or old consoles it may be worth it.
miker00lz wrote:
metroid seems to execute out of SRAM too.
This was one of the first bugs I ran into with my emulator. I wasn't handling $E000.4 properly, and the game is unplayable because the screen is covered in background tiles
EDIT: Just tested this and it turns out that wasn't what was causing it, could have sworn that was the problem. Oh well.
I think executing from RAM or WRAM is quite common.
There is various reasons you could do that, but this allows self-modifying code (which is potentially faster than normal code), it allows you to store code in CHR-RAM and even to compress it.
Personally I used it in my engine for sprite mazing routine, which should be very fast as it has to be called very often so instead of wasting time to check various variable for sprite cycling I just modify the code that write sprites itself directly.
At least Dragon Quest games, Double Dragon games, Rad Racer, Final Fantasy II and III executes code from RAM, but probably a lot of games I haven't checked does this.
Dragon Quest 1 had no WRAM. It's CNROM. Map data was stored in CHR-ROM.
But lots of games which were originally for the FDS used WRAM to store code, probably to simplify porting the game.
And back to the original topic:
There are several "Invalid" places to run code from: The PPU ports area (2000-3FFF), and sound/system ports area (4000-401F). Any jump that goes there is certainly a crash. I don't even attempt to emulate executing code from there.
I meant DQ1 also stores CODE in CHR-ROM, copy it to RAM (not WRAM, just internal RAM at $000-$7ff) and execute it from here.
If you emulate $200x and $400x reads correctly then you can emulate executing code here (even if it's pointless), because executing code is just reading opcodes/arguments to some memory locations.
Bregalad wrote:
If you emulate $200x and $400x reads correctly then you can emulate executing code here (even if it's pointless), because executing code is just reading opcodes/arguments to some memory locations.
Exactly. There is no reason not to emulate this, or atleast provide the CPU something. You don't have to go to the trouble of simulating open bus behavior or anything like that, but it is a fact that the real hardware could execute at those addresses and it is in theory possible to have a program rely on proper behavior from this. Some games do except certain open bus behavior to happen afterall.
MottZilla wrote:
There is no reason not to emulate this
Unless your target platform's CPU is so slow that the only way to make an NES emulator's CPU core run in real time is to deeply special-case the common case of opcode fetches from $0000-$1FFF and $5C00-$FFFF, as opposed to making opcode fetches use the same peekPRG() function that loads and stores use. Nintendo handhelds and old Pocket PC PDAs are probably the only widely used platforms that are this slow. But that's probably why PocketNES doesn't "even attempt to emulate executing code from there." PocketNES even has a problem with crossing the bank boundary from $BFFF to $C000 in some mappers *cough*Magic of Scheherazade*cough*.
tepples wrote:
MottZilla wrote:
There is no reason not to emulate this
Unless your target platform's CPU is so slow that the only way to make an NES emulator's CPU core run in real time is to deeply special-case the common case of opcode fetches from $0000-$1FFF and $5C00-$FFFF, as opposed to making opcode fetches use the same peekPRG() function that loads and stores use. Nintendo handhelds and old Pocket PC PDAs are probably the only widely used platforms that are this slow.
Yeah this is basically my case. My emulator will be running on a PIC or an AVR, but I haven't decided yet. I'm currently debugging on a board with a souped up 8052
beannaich wrote:
miker00lz wrote:
metroid seems to execute out of SRAM too.
This was one of the first bugs I ran into with my emulator. I wasn't handling $E000.4 properly, and the game is unplayable because the screen is covered in background tiles
EDIT: Just tested this and it turns out that wasn't what was causing it, could have sworn that was the problem. Oh well.
yeah, i had the same problem with the background tiles until i emulated the SRAM. i thought it was a CPU bug at first, and that made me a sad panda.
runaway pancake wrote:
tepples wrote:
MottZilla wrote:
There is no reason not to emulate this
Unless your target platform's CPU is so slow that the only way to make an NES emulator's CPU core run in real time is to deeply special-case the common case of opcode fetches from $0000-$1FFF and $5C00-$FFFF, as opposed to making opcode fetches use the same peekPRG() function that loads and stores use. Nintendo handhelds and old Pocket PC PDAs are probably the only widely used platforms that are this slow.
Yeah this is basically my case. My emulator will be running on a PIC or an AVR, but I haven't decided yet. I'm currently debugging on a board with a souped up 8052
heh cool, a friend of mine did a whole PC emulator on a souped up 8052 board! check this out:
http://www.armchairarcade.com/neo/node/3810
i've also done an 80186 PC emulator but i did it on linux/windows PC host so i had a lot more power to work with.
man you've got a serious task ahead of you if you want to emulate a NES at full speed on that CPU, it might be not possible honestly. the guy who did flea86 also wants to do a NES emulator now, you guys should compare notes... he hangs out on my IRC server most nights. the address is irc.rubbermallet.org channel #wtfpwnt
his nick there is usually Flea86 or Valentin.
It's odd. Your emulator should fetch the next opcode from any CPU address. I can tell you that an invalid address range is any greater than $FFFF, or bigger than a WORD (2 bytes).
miker00lz wrote:
beannaich wrote:
miker00lz wrote:
metroid seems to execute out of SRAM too.
This was one of the first bugs I ran into with my emulator. I wasn't handling $E000.4 properly, and the game is unplayable because the screen is covered in background tiles
EDIT: Just tested this and it turns out that wasn't what was causing it, could have sworn that was the problem. Oh well.
yeah, i had the same problem with the background tiles until i emulated the SRAM. i thought it was a CPU bug at first, and that made me a sad panda.
I don't have Metroid running right now, (though it's probably some other problem - fails on undoc opcode). What does the disable prg-ram bit actually do? Right now I always map in 8k of "ram" at $6000. I don't understand what the alternative is.
foobaz wrote:
miker00lz wrote:
beannaich wrote:
miker00lz wrote:
metroid seems to execute out of SRAM too.
This was one of the first bugs I ran into with my emulator. I wasn't handling $E000.4 properly, and the game is unplayable because the screen is covered in background tiles
EDIT: Just tested this and it turns out that wasn't what was causing it, could have sworn that was the problem. Oh well.
yeah, i had the same problem with the background tiles until i emulated the SRAM. i thought it was a CPU bug at first, and that made me a sad panda.
I don't have Metroid running right now, (though it's probably some other problem - fails on undoc opcode). What does the disable prg-ram bit actually do? Right now I always map in 8k of "ram" at $6000. I don't understand what the alternative is.
always mapping it in shouldnt hurt anything afaik, but the disable PRG-RAM does what it sounds like. it makes it so there is no RAM accessable at $6000. it just makes $6000-$7FFF open bus.
just ignore writes to there, and read is undefined. in my emulator it just read zeros from there when it's disabled.
Here's an MMC1 test ROM. It tests to disable of the WRAM I believe as a mechanism to check if there's any extra hardware for external devices like copiers.
http://www.mediafire.com/?549a755cdpr89dt
I'm going to guess that it says "Disabled writes:Accepted" which is what Metroid (I'm guessing) locks up or something on since it should be able to disable it with the MMC1.
Metroid also sometimes refuses to boot if the initial state of CHR-RAM is bad. FCEUX had problems with Metroid for a while, because CHR-RAM was some uninitialized memory from your PC, and not cleared or initialized to anything.
3gengames wrote:
Here's an MMC1 test ROM. It tests to disable of the WRAM I believe as a mechanism to check if there's any extra hardware for external devices like copiers.
http://www.mediafire.com/?549a755cdpr89dtI'm going to guess that it says "Disabled writes:Accepted" which is what Metroid (I'm guessing) locks up or something on since it should be able to disable it with the MMC1.
for a brief period i had the WRAM always accessible even if MMC1 tries to disable it, but metroid still worked just fine.
CHR-RAM actually is uninitialized when you boot a NES game.
And it's common for operating systems to set all variables to zero when the program reserves memory.
So I'd bet it was the opposite : Metroid didn't boot beacuse the CHR-RAM was cleared and it was supposed to be uninitialized.
miker00lz wrote:
man you've got a serious task ahead of you if you want to emulate a NES at full speed on that CPU, it might be not possible honestly. the guy who did flea86 also wants to do a NES emulator now, you guys should compare notes... he hangs out on my IRC server most nights. the address is irc.rubbermallet.org channel #wtfpwnt
his nick there is usually Flea86 or Valentin.
It's definitely possible, although not on an 8-bit micro like the flea86 (very cool btw)
The main constraint is RAM size, so I have two options really. Either add external memory and use an AVR32 (or ARM, but that's sorta been done with pocketnes), or have limited game support (<=96k) and use a PIC32 or dsPIC (mapper 0 only). I'm using the 8052 board for the moment cause I have a video controller on it I can play with that I may end up having to use on the real board.
Here's a prototype of an
ARM+CPLDboard I made like 5 years ago but never wrote the emulator for. Depending on how portable the code turns out I may go back and finish that one too
Zepper wrote:
It's odd. Your emulator should fetch the next opcode from any CPU address. I can tell you that an invalid address range is any greater than $FFFF, or bigger than a WORD (2 bytes).
Yup, that would be ideal!
Bregalad wrote:
CHR-RAM actually is uninitialized when you boot a NES game.
And it's common for operating systems to set all variables to zero when the program reserves memory.
So I'd bet it was the opposite : Metroid didn't boot beacuse the CHR-RAM was cleared and it was supposed to be uninitialized.
You might think the opposite, but Metroid booted successfully with zeroed-out CHR-RAM, and failed to boot with uninitialized RAM.
Could this be a side-effect from it being ported from FDS?
I think (but I'm not sure) the FDS BIOS has already cleared all the memory after booting so memory initialisation is not required for games. In fact, you should not even initialise (all) the memory yourself as you may have wiped clean some of the addresses reserved by the BIOS.
Possibly the porters forgot about this when they adapt the game to cartridge format.
Dwedit wrote:
Bregalad wrote:
CHR-RAM actually is uninitialized when you boot a NES game.
And it's common for operating systems to set all variables to zero when the program reserves memory.
So I'd bet it was the opposite : Metroid didn't boot beacuse the CHR-RAM was cleared and it was supposed to be uninitialized.
You might think the opposite, but Metroid booted successfully with zeroed-out CHR-RAM, and failed to boot with uninitialized RAM.
i was about to say the same time. that happened in my experience too!
So the oversights in Mario Adventure go all the way back to first-party games, I take it.
Zepper wrote:
an invalid address range is any greater than $FFFF, or bigger than a WORD (2 bytes).
In the 6502 that is an impossible scenario.
cpow wrote:
Zepper wrote:
an invalid address range is any greater than $FFFF, or bigger than a WORD (2 bytes).
In the 6502 that is an impossible scenario.
True, since it uses a 16-bit bus. I've read somewhere and in the Nintendulator source about invalid cases for PC address. *One* specific case is about the DMC address increment. Of course, you might say "it's $FFFF and will wrap to zero", but take the emulation case of having PC as unsigned int (4 bytes) instead of short (2 bytes).
In short words, take the emulation side of it.
In my Star Soldier competition hack, I run all of my custom code from WRAM to avoid bankswitching issues (the original game only had 32 KB of PRG ROM). At reset, I swap in the 8 KB bank containing my code, copy the whole thing to $6000-$7FFF, and then swap in the original bank, never touching it again. It feels like cheating, but it works...