Basic NES Emulation theory - I'm stuck
Asked Answered
P

1

6

In advance, I apologize for the open endedness, and general wishy-washiness of this question, because to be honest my knowledge of the topic is very patchy and I'm finding it hard to even describe my problem. I really didn't want to post, but I'm completely and utterly stuck.

I have started a NES emulator. It's interpreted (so no dynamic recomp).

Atm it can load and map roms (mapper 0 roms) and execute the init code right up to where I have to deal with interrupts and the PPU. That's where I'm stuck.

Here is an example output from my emu atm. Execution begins at 8000, and I hit an infinite loop at 800a where I have no idea how to progress from there.

8002: LDA #$10    ; read immediate value to set PPU control registers 
8004: STA $2000   ; store value 
8007: LDX #$FF    ; load immediate value into X register 
8009: TXS         ; store X register into stack 
800a: LDA $2002   ; read PPU flags into accumulator (set N flag based on bit 7) 
800d: BPL         ; test N flag, branch to 800a if not positive, (N is set) 
800a: LDA $2002
800d: BPL
800a: LDA $2002
800d: BPL
800a: LDA $2002
800d: BPL
etc, etc etc (inf loop)

So my question is, can someone please explain the basics of 1 iteration through a PPU render for me, including things like cycle count, interrupts etc (i.e. draw one whole 240 scanline screen and move onto the next).

Prosser answered 8/7, 2010 at 9:28 Comment(5)
Ta for adding a 6502 tagProsser
posting at nesdev.parodius.com will get you results far, far faster and better than SO will. That's just how it is for niche topics.Waugh
I have already posted there, but 5 days later I have 1 reply, and it was essentially read the docs (which I have 100 times, but I'm still a little confused).Prosser
How do you context switch between your CPU core and your PPU emulation?Urana
@DominicBou-Samra: Minor point - your comment on the TXS instruction implies that the contents of .X are placed on the stack. You probably know this, but in case anyone else reads this and misinterprets it, TXS actually transfers .X to the Stack Pointer (.SP), thereby adjusting the current depth of the Stack rather than placing the contents of .X onto it. In this case, setting .SP to #$FF 'resets' the Stack (the Stack Pointer now points to the top, first, entry of the Stack).Byronbyrum
S
1

There are emulators out there, have you looked at their sources for the answer? usually those are written for performance and not very readable but you might find a tidbit to get you going. is the code waiting for an interrupt to be executed and have you executed that interrupt? It may be that the interrupt modifies the return address and allows the program to continue? is the infinite loop polling a bit in a register? or is it an unconditional branch to self?

Scarabaeus answered 8/7, 2010 at 19:11 Comment(3)
The issue is I have no interrupt handling. I literally grab the opcodes from the memory map, execute them, and increment the counter. That's all working well. I'm stuck when it comes to understanding the CPU cycles and it's relation to the main loop. I'm just looking for some basic pseudo code relating to how the emulator should process.Prosser
Are you sure it is not an interrupt? Certainly with video rendering and for other reasons there will be a hardware interrupt that forground task is waiting for, the interrupt routine sets a memory location or in this case waits for a flag? I struggled with a similar infinite loop for Asteroids until I understood how that all worked. Otherwise I need more info on the problem in order to help.Scarabaeus
Thanks mate. I've sorted it out. LOL @ this question - was so confused when I wrote it.Prosser

© 2022 - 2024 — McMap. All rights reserved.