I have decided to use a pointer to the ROM to make my emulator faster. I have everything setup, apart from the value of the PC itself.
Code:
*CPU.PC = 0x69 // ADC Immediate
&CPU.PC = Address
How do I calculate the value of the PC ($0000-FFFF)? I need it for pushing and popping the PC for JSR/RTS and for the function that handles memory mapping. I have managed to do some kind of 'Current Address - Start Address' kind of thing but have only come up with 0x2C, which seems odd.
That method will not work if you divide your NES memory into banks via pointers (the only efficient way of doing it).
Really, doing it that way won't gain any significant speed over doing Memory[CPU.PC].
Quietust wrote:
That method will not work if you divide your NES memory into banks via pointers (the only efficient way of doing it).
Really, doing it that way won't gain any significant speed over doing Memory[CPU.PC].
Could someone please provide an example of this?
My way:
decode addr into 8 w/ addr & 0xE000
0000 Y0 = wram[addr & 0x7FF]
2000 Y1 = ppu regs (furthur decode)
4000 Y2 = decode <4018 to apu regs, >= 4018 to mapper handler
6000 Y3 = decode to mapper handler or SRAM
else = decode to mapper handler
.....
----handler for 8k bankswitching----
if(addr & 0xC000 == 0x8000)
return *PRG_8_ptr + (addr & 0x1FFF);
.......ptrs for 8k bankswitching....
PRG_8_ptr = &PRGmem + bank*0x2000
..
..
PRG_E_ptr = &PRGmem + ((((sizeof(PRGmem))/8)-1)*0x2000) or whatever
Thanks, but that still doesn't tell me the value of PC when I need it.
Encapsulate what I said into global_read(addr) then do cpu_instruction(global_read(cpu.pc)).
It sounds like you want to store pc itself as a pointer, but I couldn't understand your question very well. Good luck:
Code:
byte* pc_ptr = rom; // pc = 0x8000
int pc = pc_ptr - rom + 0x8000; // recover 16-bit program counter from pointer
The problem with this is that you can't easily handle bank changes. This is how most people handle banks:
Code:
int pc; // 16-bit value of emulated program counter
// no banks
byte* rom = malloc( 0x8000 );
int data = rom [pc & 0x7FFF];
// 8 banks
byte* banks [8];
int data = banks [pc >> 12 & 7] [pc & 0x0FFF];
Finally! Now I understand thanks to blargg's explanation. Here is what I do:
Code:
ROM_Pointer = Cartridge.ROM[Bank];
opcode = ROM_Pointer[PC & 0x7FFF];
Is that acceptable? Or is there a faster method?
Is ROM[bank] an array of pointers each pointing to a bank in the flat ROM image memory?
I'm having difficulty understanding what we're talking about, your idea seems very convoluted. Why not keep only one pointer to the ROM?
byte *ROM_pointer = malloc(sizeof(game));
opcode = *ROM_pointer[banknumber*sizeof(bank) | (PC & (sizeof(bank)-1))]
Code:
$8000-BFFF
ROMBank1 = &Cartridge.ROM[Bank] // Bank = $8000 for the 3rd Bank
$C000-FFFF
ROMBank2 = &Cartridge.ROM[Bank] // Bank = $4000 for the 2rd Bank
opcode = ROMBankx[PC & $7FFF]
Read trapping designates which ROMBank to use.
kyuusaku wrote:
opcode = *ROM_pointer[banknumber*sizeof(bank) | (PC & (sizeof(bank)-1))]
Is a lot of code for fetching an opcode.
(bank*0x2000|pc&0x1FFF) doesn't seem so bad. It's your choice whether to modify pointers or variables. Generally it would be best to use more than less pointers since they needn't be modified as often as my example would need to be evaluated. From the description of the problem though, I couldn't tell if you had pointers to banks.