Need next steps for NES emulator

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

codeblox
Posts: 26
Joined: Wed Dec 11, 2013 9:54 pm

Need next steps for NES emulator

Post by codeblox »

Greetings,

I have written a barebones 6502 emulator. The ultimate goal is to write an NES emulator. My 6502 emulator follows the basic fetch execute cycle and all of the opcodes have been implemented. What should my next focus be for working towards creating this emulator?
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Need next steps for NES emulator

Post by tepples »

Does your emulator's CPU match the known-good log of nestest cycle-for-cycle? (See Emulator tests on the wiki.) Make sure each instruction takes the same number of cycles (on NTSC there are three PPU cycles in a CPU cycle, 341 PPU cycles in a scanline, and 262 scanlines in a frame) and produces the same stream of program counter values, and find the first instruction at which they diverge.

Once it does, the next thing to emulate is vertical blank timing. At the start of line 241, bit 7 of $2002 (Vblank flag) becomes 1. It becomes 0 at the start of line 261 or when $2002 is read, whichever comes first. If bit 7 of $2002 rises (goes from 0 to 1) while bit 7 of $2000 (NMI) is turned on, call the NMI handler. Once your CPU is correct, emulating bit 7 of $2000, bit 7 of $2002, and NMI should be enough to get games like Donkey Kong and Mario Bros. to start trying to boot.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: Need next steps for NES emulator

Post by blargg »

Be sure it passes the available CPU tests for official instructions.
Zelex
Posts: 268
Joined: Fri Apr 29, 2011 9:44 pm

Re: Need next steps for NES emulator

Post by Zelex »

Yeah, CPU tests and probably start on a PPU implementation. You don't have to get every detail implemented for many games to start working. Should be fun :) Start with mapper 0 games.
codeblox
Posts: 26
Joined: Wed Dec 11, 2013 9:54 pm

Re: Need next steps for NES emulator

Post by codeblox »

The emulator hasn't been tested against the official instructions so I'll probably start working on that next. I see that the files to test with come in .nes format. I'm assuming I just read this file into my emulators memory at the beginning and let her run, correct?
User avatar
Dwedit
Posts: 4924
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Need next steps for NES emulator

Post by Dwedit »

Throwing the entire contents of a NES file at memory address 0000 will never work.

You need to get the NES memory map correct, and understand the very basics of the iNES file format.
16 byte header, then PRG data, then CHR data.
Throwing the PRG data into address 8000 (for 32K PRG) or C000 (for 16K PRG) might work here.

Also, you do have the reset vector implemented, right?
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
miker00lz
Posts: 235
Joined: Thu Sep 23, 2010 7:28 pm

Re: Need next steps for NES emulator

Post by miker00lz »

Have you tried running any code at all yet in your 6502 emulator?
codeblox
Posts: 26
Joined: Wed Dec 11, 2013 9:54 pm

Re: Need next steps for NES emulator

Post by codeblox »

I have not tested it against any code. It sounds like my next steps are to test this against the suite provided in this thread. Thanks guys, I'll see how that works out and come back with results. What I have done however is create a test function of sorts which validates addressing modes and mnemonic <-> opcode resolution. Basically as a test I fed 0 - 255 as data to the emulator. Could you guys kindly tell me if it looks correct?

Code: Select all


Opcode 00(brk) has address mode Implied
Opcode 01(ora) has address mode Indirect X
Opcode 02(trp) is a trap
Opcode 03(trp) is a trap
Opcode 04(trp) is a trap
Opcode 05(ora) has address mode Zero Page
Opcode 06(asl) has address mode Zero Page
Opcode 07(trp) is a trap
Opcode 08(php) has address mode Implied
Opcode 09(ora) has address mode Immediate
Opcode 0A(asl) has address mode Accumulator
Opcode 0B(trp) is a trap
Opcode 0C(trp) is a trap
Opcode 0D(ora) has address mode Absolute
Opcode 0E(asl) has address mode Absolute
Opcode 0F(trp) is a trap
Opcode 10(bpl) has address mode Relative
Opcode 11(ora) has address mode Indirect Y
Opcode 12(trp) is a trap
Opcode 13(trp) is a trap
Opcode 14(trp) is a trap
Opcode 15(ora) has address mode Zero Page X
Opcode 16(asl) has address mode Zero Page X
Opcode 17(trp) is a trap
Opcode 18(clc) has address mode Implied
Opcode 19(ora) has address mode Absolute Y
Opcode 1A(trp) is a trap
Opcode 1B(trp) is a trap
Opcode 1C(trp) is a trap
Opcode 1D(ora) has address mode Absolute X
Opcode 1E(asl) has address mode Absolute X
Opcode 1F(trp) is a trap
Opcode 20(jsr) has address mode Absolute
Opcode 21(and) has address mode Indirect X
Opcode 22(trp) is a trap
Opcode 23(trp) is a trap
Opcode 24(bit) has address mode Zero Page
Opcode 25(and) has address mode Zero Page
Opcode 26(rol) has address mode Zero Page
Opcode 27(trp) is a trap
Opcode 28(plp) has address mode Implied
Opcode 29(and) has address mode Immediate
Opcode 2A(rol) has address mode Accumulator
Opcode 2B(trp) is a trap
Opcode 2C(bit) has address mode Absolute
Opcode 2D(and) has address mode Absolute
Opcode 2E(rol) has address mode Absolute
Opcode 2F(trp) is a trap
Opcode 30(bmi) has address mode Relative
Opcode 31(and) has address mode Indirect Y
Opcode 32(trp) is a trap
Opcode 33(trp) is a trap
Opcode 34(trp) is a trap
Opcode 35(and) has address mode Zero Page X
Opcode 36(rol) has address mode Zero Page X
Opcode 37(trp) is a trap
Opcode 38(sec) has address mode Implied
Opcode 39(and) has address mode Absolute Y
Opcode 3A(trp) is a trap
Opcode 3B(trp) is a trap
Opcode 3C(trp) is a trap
Opcode 3D(and) has address mode Absolute X
Opcode 3E(rol) has address mode Absolute X
Opcode 3F(trp) is a trap
Opcode 40(rti) has address mode Implied
Opcode 41(eor) has address mode Indirect X
Opcode 42(trp) is a trap
Opcode 43(trp) is a trap
Opcode 44(trp) is a trap
Opcode 45(eor) has address mode Zero Page
Opcode 46(lsr) has address mode Zero Page
Opcode 47(trp) is a trap
Opcode 48(pha) has address mode Implied
Opcode 49(eor) has address mode Immediate
Opcode 4A(lsr) has address mode Accumulator
Opcode 4B(trp) is a trap
Opcode 4C(jmp) has address mode Absolute
Opcode 4D(eor) has address mode Absolute
Opcode 4E(lsr) has address mode Absolute
Opcode 4F(trp) is a trap
Opcode 50(bvc) has address mode Relative
Opcode 51(eor) has address mode Indirect Y
Opcode 52(trp) is a trap
Opcode 53(trp) is a trap
Opcode 54(trp) is a trap
Opcode 55(eor) has address mode Zero Page X
Opcode 56(lsr) has address mode Zero Page X
Opcode 57(trp) is a trap
Opcode 58(cli) has address mode Implied
Opcode 59(eor) has address mode Absolute Y
Opcode 5A(trp) is a trap
Opcode 5B(trp) is a trap
Opcode 5C(trp) is a trap
Opcode 5D(eor) has address mode Absolute X
Opcode 5E(lsr) has address mode Absolute X
Opcode 5F(trp) is a trap
Opcode 60(rts) has address mode Implied
Opcode 61(adc) has address mode Indirect X
Opcode 62(trp) is a trap
Opcode 63(trp) is a trap
Opcode 64(trp) is a trap
Opcode 65(adc) has address mode Zero Page
Opcode 66(ror) has address mode Zero Page
Opcode 67(trp) is a trap
Opcode 68(pla) has address mode Implied
Opcode 69(adc) has address mode Immediate
Opcode 6A(ror) has address mode Accumulator
Opcode 6B(trp) is a trap
Opcode 6C(jmp) has address mode Absolute
Opcode 6D(adc) has address mode Absolute
Opcode 6E(ror) has address mode Absolute
Opcode 6F(trp) is a trap
Opcode 70(bvs) has address mode Relative
Opcode 71(adc) has address mode Indirect Y
Opcode 72(trp) is a trap
Opcode 73(trp) is a trap
Opcode 74(trp) is a trap
Opcode 75(adc) has address mode Zero Page X
Opcode 76(ror) has address mode Zero Page X
Opcode 77(trp) is a trap
Opcode 78(sei) has address mode Implied
Opcode 79(adc) has address mode Absolute Y
Opcode 7A(trp) is a trap
Opcode 7B(trp) is a trap
Opcode 7C(trp) is a trap
Opcode 7D(adc) has address mode Absolute X
Opcode 7E(ror) has address mode Absolute X
Opcode 7F(trp) is a trap
Opcode 80(trp) is a trap
Opcode 81(sta) has address mode Indirect X
Opcode 82(trp) is a trap
Opcode 83(trp) is a trap
Opcode 84(sty) has address mode Zero Page
Opcode 85(sta) has address mode Zero Page
Opcode 86(stx) has address mode Zero Page
Opcode 87(trp) is a trap
Opcode 88(dey) has address mode Implied
Opcode 89(trp) is a trap
Opcode 8A(txa) has address mode Implied
Opcode 8B(trp) is a trap
Opcode 8C(sty) has address mode Absolute
Opcode 8D(sta) has address mode Absolute
Opcode 8E(stx) has address mode Absolute
Opcode 8F(trp) is a trap
Opcode 90(bcc) has address mode Relative
Opcode 91(sta) has address mode Indirect Y
Opcode 92(trp) is a trap
Opcode 93(trp) is a trap
Opcode 94(sty) has address mode Zero Page X
Opcode 95(sta) has address mode Zero Page X
Opcode 96(stx) has address mode Zero Page X
Opcode 97(trp) is a trap
Opcode 98(tya) has address mode Implied
Opcode 99(sta) has address mode Absolute Y
Opcode 9A(txs) has address mode Implied
Opcode 9B(trp) is a trap
Opcode 9C(trp) is a trap
Opcode 9D(sta) has address mode Absolute X
Opcode 9E(trp) is a trap
Opcode 9F(trp) is a trap
Opcode A0(ldy) has address mode Immediate
Opcode A1(lda) has address mode Indirect X
Opcode A2(ldx) has address mode Immediate
Opcode A3(trp) is a trap
Opcode A4(ldy) has address mode Zero Page
Opcode A5(lda) has address mode Zero Page
Opcode A6(ldx) has address mode Zero Page
Opcode A7(trp) is a trap
Opcode A8(tay) has address mode Implied
Opcode A9(lda) has address mode Immediate
Opcode AA(tax) has address mode Implied
Opcode AB(trp) is a trap
Opcode AC(ldy) has address mode Absolute
Opcode AD(lda) has address mode Absolute
Opcode AE(ldx) has address mode Absolute
Opcode AF(trp) is a trap
Opcode B0(bcs) has address mode Relative
Opcode B1(lda) has address mode Indirect Y
Opcode B2(trp) is a trap
Opcode B3(trp) is a trap
Opcode B4(ldy) has address mode Zero Page X
Opcode B5(lda) has address mode Zero Page X
Opcode B6(ldx) has address mode Zero Page X
Opcode B7(trp) is a trap
Opcode B8(clv) has address mode Implied
Opcode B9(lda) has address mode Absolute Y
Opcode BA(tsx) has address mode Implied
Opcode BB(trp) is a trap
Opcode BC(ldy) has address mode Absolute X
Opcode BD(lda) has address mode Absolute X
Opcode BE(ldx) has address mode Absolute X
Opcode BF(trp) is a trap
Opcode C0(cpy) has address mode Immediate
Opcode C1(cmp) has address mode Indirect X
Opcode C2(trp) is a trap
Opcode C3(trp) is a trap
Opcode C4(cpy) has address mode Zero Page
Opcode C5(cmp) has address mode Zero Page
Opcode C6(dec) has address mode Zero Page
Opcode C7(trp) is a trap
Opcode C8(iny) has address mode Implied
Opcode C9(cmp) has address mode Immediate
Opcode CA(dex) has address mode Implied
Opcode CB(trp) is a trap
Opcode CC(cpy) has address mode Absolute
Opcode CD(cmp) has address mode Absolute
Opcode CE(dec) has address mode Absolute
Opcode CF(trp) is a trap
Opcode D0(bne) has address mode Relative
Opcode D1(cmp) has address mode Indirect Y
Opcode D2(trp) is a trap
Opcode D3(trp) is a trap
Opcode D4(trp) is a trap
Opcode D5(cmp) has address mode Zero Page X
Opcode D6(dec) has address mode Zero Page X
Opcode D7(trp) is a trap
Opcode D8(cld) has address mode Zero Page X
Opcode D9(cmp) has address mode Absolute Y
Opcode DA(trp) is a trap
Opcode DB(trp) is a trap
Opcode DC(trp) is a trap
Opcode DD(cmp) has address mode Absolute X
Opcode DE(dec) has address mode Absolute X
Opcode DF(trp) is a trap
Opcode E0(cpx) has address mode Immediate
Opcode E1(sbc) has address mode Indirect X
Opcode E2(trp) is a trap
Opcode E3(trp) is a trap
Opcode E4(cpx) has address mode Zero Page
Opcode E5(sbc) has address mode Zero Page
Opcode E6(inc) has address mode Zero Page
Opcode E7(trp) is a trap
Opcode E8(inx) has address mode Implied
Opcode E9(sbc) has address mode Immediate
Opcode EA(nop) has address mode Implied
Opcode EB(trp) is a trap
Opcode EC(cpx) has address mode Absolute
Opcode ED(sbc) has address mode Absolute
Opcode EE(inc) has address mode Absolute
Opcode EF(trp) is a trap
Opcode F0(beq) has address mode Relative
Opcode F1(sbc) has address mode Indirect Y
Opcode F2(trp) is a trap
Opcode F3(trp) is a trap
Opcode F4(trp) is a trap
Opcode F5(sbc) has address mode Zero Page X
Opcode F6(inc) has address mode Zero Page X
Opcode F7(trp) is a trap
Opcode F8(sed) has address mode Implied
Opcode F9(sbc) has address mode Absolute Y
Opcode FA(trp) is a trap
Opcode FB(trp) is a trap
Opcode FC(trp) is a trap
Opcode FD(sbc) has address mode Absolute X
Opcode FE(inc) has address mode Absolute X
Opcode FF(trp) is a trap

tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Need next steps for NES emulator

Post by tepples »

Image

Why are $80 and $89 traps? They're 2-byte no-ops, and if you don't emulate them as 2-byte no-ops, you'll break Puzznic and Beauty and the Beast. A lot of the instructions you've listed as "traps" are actually rawther useful. So much so that if you fail to emulate other unofficial instructions, you might break STREEMERZ: Super Strength Emergency Squad Zeta and Driar.
WedNESday
Posts: 1284
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Re: Need next steps for NES emulator

Post by WedNESday »

tepples has just made my day. :)

I'm pretty sure tepples that his 6502 emulator at this point is pretty basic and he's not bothering with the illegal ops right now. However, not many of us are prepared to read through 256 lines of that green text to help you out. Hook your CPU up to some basic PPU code and run nestest.nes if you really wanna try it.
codeblox
Posts: 26
Joined: Wed Dec 11, 2013 9:54 pm

Re: Need next steps for NES emulator

Post by codeblox »

I'll go ahead and implement these unofficial opcodes now. They appear to simply be a combination of other opcodes (the items in gray at the link provided by tepples). Is that correct? As for the name "trap"... I just picked something that I thought would describe "illegal opcode" haha. I just pulled it out of the air. What should the proper name be for opcodes that do not exist (Where I have the traps)?
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Need next steps for NES emulator

Post by koitsu »

There is no "proper" (official) naming convention for them, and don't let anyone here tell you or make you think otherwise. :-)

I strongly suggest you avoid implementing unofficial opcodes at this time. They should be one of the last things you implement, since your goal as admitted in your first post is to make a NES emulator. You have a lot bigger fish to worry about in the future, trust me -- illegal opcodes are the least of your worries, since only 1 game is known at this time to use them. They should act as "traps" or "suspend emulation" situations, since they indicate broken emulation on your part. Handling them now will do nothing but cause massive confusion when trying to troubleshoot your emulator.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Need next steps for NES emulator

Post by tepples »

Actually there are about half a dozen games that use unofficial opcodes, listed at the bottom of this page. But otherwise, koitsu is right that unless you're running a test ROM or one of these games, hitting an unofficial opcode means your CPU or mapper emulation is misbehaving.

But there does exist a compromise that does what the user expects. I'd recommend making a switch for pausing on unofficial opcode with these positions:
  • Always
  • Once after power cycle
  • Only on new mappers
  • Only HLT
For "Only on new mappers", you'd keep track of how stable you think your implementation of each mapper is. It'd act like "Once after each power cycle" until you're certain that a mapper is working correctly. For example, once you think you have most CNROM (#3) games working, you could switch CNROM to "Only HLT" and Puzznic would stop bugging the user.
codeblox
Posts: 26
Joined: Wed Dec 11, 2013 9:54 pm

Re: Need next steps for NES emulator

Post by codeblox »

So aside from working on unofficial opcodees, would you guys say the next step is to run my emu against the nestest suite or begin work on the PPU? I'm not sure if the nestest suite depends on the PPU.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Need next steps for NES emulator

Post by tepples »

There's part of nestest that requires only a working CPU that can JSR $C000, and part of nestest that also requires a working PPU and controller. The emulator tests page links to a log of the first part running in Nintendulator; if you log A, X, Y, P, S, PC, and elapsed cycles after each instruction, you can compare the value at each instruction to Nintendulator's value and make sure they match. (Hint: 3 CYC units = 1 CPU cycle because CYC counts PPU dots, and CYC is measured mod 341 because that's how long a scanline is.)
Post Reply