ZN-flag tricks? Does that mean that what I thought was an original idea, to store the ZN value and only test it at a branch or push status op has already been thought of?
Yeah. Store the value result, calculate the flags only when another opcode uses it.
e.g., each Bank_Mode21_C0_FF object knows that it just needs to read from ROM
Mine holds class pointers for every page (every 256 bytes), you need that granularity to map the SuperFX GSU region.
Whenever memory is read, I call:
return memory_table[addr >> 8](addr);
The table holds base classes with virtual functions, and I store derived classes that do things like read from ROM with an offset against the address, or call MMIO register functions, etc.
I figured a single memory function that did your typical if(addr & 0x800000) { ... } etc would be faster, but a lot less flexible. I use my memory mapper to dynamically rewrite the map while the game runs for bank-swapping games like Star Ocean and Far East of Eden Zero, or for the BS-X.
But I don't want to use C/++ for this, as it's already been done so well in other emulators there seems to be little left to achieve in that area.
It's up to you, but I'd rather see another C++ one than a Java one :/
Then again I'm not a fan of Java at all, so I won't share my grievances as they'd just be biased to no end ...
To entice you, I wrote two classes that let me make signed or unsigned integers of any bit-length, and all overflow+masking is transparent. They only take a ~10% speed hit over native math, due to masking overhead.
typedef int_t<24> int24_t;
typedef uint_t<48> uint48_t;
uint48_t foo = 0xffffffffffff;
foo++;
foo == 0;
If I didn't care about speed, I'd use them for the 24-bit address bus stuff. Be very nice to avoid all the masking and ambiguity regarding "do I have to ignore the top 8-bits or are they already clear?" in the code.
I hoped there was no SNES hardware that required that.
ABORTB was for operating system control. Eg for the Apple II GS.
I know of no SNES hardware that can utilize it. Not even sure if the CPU pin is connected to anything. At any rate, you don't have to worry about it.
If I don't use cothreading, do I have to implement separate code blocks for each cycle of each opcode? That sounds a veritable nightmare.
Well, it's Java so you can't use cothreading even if you want to.
But you shouldn't need this for your CPU. As long as the SMP is enslaved to the CPU, you only need to make a cycle-based state machine out of the much-simpler SMP, and have your clock / memory read-write functions run the SMP when needed (eg when the CPU accesses $2140-217f.)
It'll get trickier with the SuperFX / SA-1. The latter is another 65816 (and then some), so you'll have to cycle step one or the other, or share the fun problems other emulators do in Super Mario RPG and such.
I guess what I'm asking is, what's the finest granularity that the CPU must be able to handle?
It depends on what compatibility you want. Is 95% okay? Just opcode-based is fine. Want 99%? Going to need cycle based. Want 100%? Don't we all :P You'll need to handle things like bus-hold delays and such (a memory read doesn't happen immediately at the start of a cycle, but ~33% of the way through it.)
Opcode-based, you'll not (easily) be able to emulate some games that do really wild stuff to affect IRQ/NMI/DMA states in the middle of opcodes. Eg what happens if DMA triggers in the middle of your opcode, and that DMA transfers 10 full emulated seconds worth of data?
If your opcode is its own function, and it calls the DMA function right in the middle, you can't return from your CPU to service the SMP / DSP / user-interface for ten full seconds, unless your DMA is considered the master of your entire program and calls a function to update all that stuff. Which is ... a nasty design, to say the least. Even if you hide it well.
And then trying to emulate the DMASYNC + CPUSYNC states of DMA / HDMA with an opcode-based core ... good luck :/
But you don't need any of that stuff to get almost all games working, if that's what you're going for.
Wow! I never imagined IRQs were going to be such a pain.
Oh ... there are so many unbelievable edge cases ... you have no idea :(