What's new

Nes

djudz

New member
i think i understand how video memory works now, but i have trouble understanding where in the games code, the maps and attributes are created. i was looking at the wall.nes dissasembly for any vram write at $2000 (name table 0) trough $2006 but i find some loops that don´t make sense (at least for me) an example is attached

maybe i´m missing something, i don´t know.
thanks for helping

View attachment 33430
 
Last edited:

GbaGuy

New member
That code loads a map from $c190 to the first nametable. Basically it's using:
Y as a counter for how many groups of 256 bytes to write.
X as a counter for how many bytes have been written (upto 256, then it wraps and decrements Y).
Memory location 0 and 1 for a pointer to the map itself.

Perhaps you could be more specific with your question? I'm not sure I understand what you would like explained :) .
 

djudz

New member
i was confused with that loop, but your answer make it a lot clear. i was reading $90c1 and not $c190 :blink:

thanks for helping :)
 

pegasus001

Normal User
I tried at first nes emulation but it was a bit difficult to understand. I can program quite well but i don`t have much knowledge about how the cpu works, the timers and stuff like this, so my 6502 is not finished yet. Can anyone explain this to me.
 

SG57

New member
Hmmm... I started with porting Chip 8 emulators to a very limited SDK (2.8 for PSP tobe exact) and have done about 3 of them so far. Ive basically memorized the interpretation of ROMs down pretty much, Im hoping to start NES, but I want to do it under those limits, once again. Im restricted to know external image loading (besides manual loading of ROMs). So unless there is a way to extract all sprites from a game, store them in a multidementional array for later rendering, Im gonna have to find some other system that either supports it, or uses Chip 8 type graphics (shapes).

Oh and think this is a good step up from Chip 8? Or should I first try something else to test what i know... Im probably just gonna writemy very own Chip 8 emulation from scratch and then move up the ladder, porting many chip 8 emulators gave me a good sense of op codes, but not a first hand expereince ;)

Any advice is well appreciated :)
 

yosh64

New member
hey

I recently started on a NES emu, after previously doing Chip8 and Gameboy emulators (still have to fix what I think is a slight vblank timing bug in my gbemu, that affects just a few games).

Anyhows I thought I would share some docs I found useful :), besides the NES Stuff package.

6502 Instruction Set
Everynes - Nocash NES Specs
Nintendo Entertainment System Architecture

I have basically done the CPU, and are now stuck on the gfx. I think I need to sit down and come to grips with the Name Table + Pattern Table + Attribute Table, well I think the Attribute Table is what really throws me off.

cyas
 
Last edited:

ZeroFusion

New member
Hi,

I'm working on my NES emulator (in fact, it's my bachelor work). Everything went just fine (after the 3-month pause I even discovered a lot of errors in my code that preserved even mapper 0 ROMs from working). As of now, I (imho) implemented everything needed to run mapper 0 ROMs except for scrolling.

I encountered strange problem: various sources contradict on background color mirroring that occurs on palettes:
1) Yoshi's Nestech states that any write to $3F00 is mirrored to $3F04, $3F08 and $3F0C. I think that it should work retroactively, ie. for example any write to $3F04 should be mirrored to $3F00, $3F08 and $3F0C too. The same goes for writes to $3F10, $3F14, $3F18 and $3F1C.

2) Everynes (Nocash NES Specs) stands literally that "$3F10, $3F14, $3F18, $3F1C are mirrors of $3F00, $3F04, $3F08, $3F0C." This corresponds to what was said in this thread before - mirroring occurs like this: $3F00<=>$3F10, $3F04<=>$3F14, $3F08<=>$3F18, $3F0C<=>$3F1C.

The first case gives me the "DPjr" in nestress.nes PPU test, however the sky in SMB1 stays stubbornly black. The second case makes SMB1's sky blue, but nestress.nes PPU test on read pallete test.

Can anyone explain to me what is right?
I also can't figure out what does the "Use $2002/5 to write addr" test means, for it's not covered in nestress' TXT description file nor in the nestress ASM source....
Thanks for any replies.
 

ZeroFusion

New member
Thanks, it wasn't necessary to post it there, because I found solutions in one of the threads there: the 2nd statement is true. I just have to find out why I get Error on appropriate test in Nestress, while FceUXD passes it (DPjr) and has blue sky in SMB1.
 

yosh64

New member
hey

Well I recently started on my nes emu again... haven't got that far again, and kinda stumbling again.

Anyhows I'm onto the PPU now, but I'm confused about things or something... so I thought I'd make a post, although I have nothing specific to ask for atm, so I dunno.

cyas
 

yosh64

New member
hey

Well I've now got the CPU going quite well and such, and got some roms going with video :), but the problem now is to get the PPU timing and such up to scratch.

ATM, when it comes to rendering a scanline I don't handle the tile scroll, and fine scroll offsets :\, as I'm not exactly sure how to when it comes to actually rendering a scanline. I do know, and already handle reads/write from $2005, $2006 and $2007 PPU registers from the CPU, but not from the PPU.

From quickly looking over the nesdev forums I think some folks even suggest rendering a pixel at a time, rather than at each scanline, which I think would lead to a bit to much overhead for my liking.

Anyhows soon I will make note of all the resources I have used and such, and what docs aren't up to scratch or whatever. Hmm, so far I have found THIS doc to be most accurate and helpful in regards to the CPU.

I've been debugging besides the Nintendulator, and found the "nestest.nes" rom by "Kevin Horton" for testing the cpu great ^_^. Anyhows after googling for this rom it lead me back to an earlier post in this thread, thanks hap.

Anyhows any info in regards to what occurs when it comes to actually drawing a scanline would be great :).

edit
BTW, so far I've just tried adding to the name table address based on the tile offset, but I think there is more to it? and haven't even bothered with the fine scroll yet.

another edit
Anyhows, I thought I'd write a little more on the resources I used...

On the CPU side of things, I think the best and most accurate doc I've found is this 6502 doc.

Another is this 6502 Opcodes doc, and also hosted here is a nice detailed explaination of the V (overflow) flag.

Finally there is this 6502 Instruction Set doc, but be careful with this one, as I think there are some incorrect flag settings and such, but mostly it's fine (just compare to other docs).

Onto the actual NES specifications, I found Yoshi's doc to be amoungst the best, and most complete. There is also the Nocash Everynes doc, and Marat Fayzullin's doc.

Another doc really worth mentioning is Loopy's PPU doc, which explains the $2005, $2006, and $2007 registers on the CPU side.

Also, if you are looking for various docs and such then checkout those at nesdev, and zopher's domain.

Anyhows I also used a bunch of test roms (I think the nestest.nes rom is essential!), which I mostly debugged besides Nintendulator, and at times I used NESten and FCE Ultra. BTW, I got most of these test roms from the later mentioned websites, and the nestest.nes from an earlier post in this thread by hap.

cyas
 
Last edited:

aprentice

Moderator
ive scrapped my source and recoding from scratch as of yesterday, so far have every opcode implemented except all the jmp ones :p
 

aprentice

Moderator
have all the ops done and some timing done, just a little confused on what page boundary crossing is and how its detected, want to make sure my timing is decent :p
 

Exophase

Emulator Developer
have all the ops done and some timing done, just a little confused on what page boundary crossing is and how its detected, want to make sure my timing is decent :p

In NES a "page" from the CPU's point of view is a 256 byte region. The address space is split into 256 pages, you could number them from 0-255 (hence why the first one is called "zero page").

This penalty applies to calculated 16bit addresses that are of the type base16 + offset, where the final memory location (base16 + offset) is in a different page than base. base16 can either be the direct or indirect version, but it'll be 16bits either way (and offset will be the contents of either x or y)

You can check this by:

((base + offset) & 0xFF00) != (base & 0xFF00)

That's five operations.

Or you can do this:

((base & 0xFF) + offset) > 0xFF

That's three operations, but both of these involve conditional evaluation which might cost you. If you're doing it in x86 ASM you can do some tricks with 8bit registers/operations so that it's pretty efficient, something like:

mov ebx, eax ; eax has base
add bl, cl ; cl has offset
sbb edx, 0 ; edx is the cycle counter
add eax, ecx ; actually increment the base

(yeah, I know, optimizing NES interpreters to run on multi-GHz PCs is full of lolz)
 

yosh64

New member
hey

Well here is my code for handling zero page writes, and the zero page bug or whatever, this function is only used/needed for IND, IND_X, and IND_Y addressing modes.

Code:
unsigned short mem_read_zp(unsigned short addr)
{

	// check lower byte...
	// note, for when address is 0xFF (for indirect x and y address modes)...
	// note, high byte not increased on page wrap (for indirect address modes)...
	if((addr & 0xFF) == 0xFF) return (g_memBuf[addr] + (g_memBuf[addr-0xFF]<<8));
	else return MAKE_USHORT g_memBuf[addr];
}

Well here are my address mode defines that use the above function...
Code:
#define IND_addr	mem_read_zp(MAKE_USHORT g_memBuf[g_cpu.pc+1])
#define IND_X_addr	mem_read_zp((unsigned char)(g_memBuf[g_cpu.pc+1]+g_cpu.x))
#define IND_Y_addr	mem_read_zp(g_memBuf[g_cpu.pc+1])+g_cpu.y

Anyhows just debug with the nestest.nes rom and ya should eventually figure it out, hehe. Well read about the address modes in the 6502 doc I mentioned, and you can read about that bug in Yoshi's doc.

Also, I'm yet to handle adding the extra instruction cycles for when a page is crossed, but should be strait forward. Just check if the lower byte of the program counter will cross $FF, so I thinks anyhows.

edit
BTW, I haven't worked on my nes emu for a lil while now, but was still wondering about things with the PPU timing and such.

another edit
I was just looking back over the docs, and I think it refers to memory reads crossing pages, not the program counter. Anyhows I'll have to look further into things.

another...
Well just looked into things a little, and I'm not exactly sure on things myself :\. But I'm thinking if the address is greater than $FF when reading from memory, then you must cross a page? but I dunno. I think I'll have to debug something with the nintendulator and see how it handles things :).

Anyhows I think the branch instructions refer to the program counter when checking if a page is crossed. But that 6502 doc that I talk of doesn't even mention such things for jmp/branch instructions, so I dunno.

cyas
 
Last edited:

aprentice

Moderator
i wasnt having a problem with memory addressing, just detecting page crossing so i could have correct timing :p So far my cpu is done, including interrupts and almost done with timing, just need to properly factor page crossing cycles. Haven't had time to code much the last 2 days. Working on memory, right now its a basic skeleton. I'll keep everyone up to date on my progress since this place been pretty dead lately, is anyone still working on their emu? :p
 

Top