What's new

Nes

hap

New member
With an array of 4 pointers that hold the current nametablebank, respectively for ppu memmap locations 0x2000, 0x2400, 0x2800 and 0x2c00.

eg. vertical mirroring: pointers 0x2000 and 0x2800 point to nametable 1, and pointers 0x2400 and 0x2c00 point to nametable 2.
 

hap

New member
Fixed mmc1, and mmc2 too (punch out), fixed sprites, added mmc3 without irq. I'm bound to meet 'Error' still many times during progress.

*edit* someone said no NES rom uses the BRK opcode. Well, Dragon Warrior 1 uses it. And it might also be worth noting that the game 'Super Cars' depends on undocumented opcodes.
 
Last edited:

hap

New member
I've slightly modified my rom loader to make it throw up a list of mappers of the GoodNES roms. See the attachment for the result, handy when testing.

*edit* hmm, I've found out why games like Megaman, Rushn Attack, Jackal, and probably others, wouldn't boot: the iNES header was messed up with a string 'DiskDude!' at the end.

Just to let be known that this mapperlist contains errors due to broken headers.
 
Last edited:

hap

New member
Hmm, I think I've gotten somewhat bored with NES, I've hardly worked on it for nearly a month. I'm done with most of the fun stuff, and sound emulation scares me. I'll get back to it later probably, but in the meantime it's time for something new, like perhaps joining the Gameboy emulation programming bandwagon :p

*edit* or maybe the MSX... well, at least something with a Z80 in it as the main CPU.
 
Last edited:

aprentice

Moderator
hap said:
Hmm, I think I've gotten somewhat bored with NES, I've hardly worked on it for nearly a month. I'm done with most of the fun stuff, and sound emulation scares me. I'll get back to it later probably, but in the meantime it's time for something new, like perhaps joining the Gameboy emulation programming bandwagon :p

*edit* or maybe the MSX... well, at least something with a Z80 in it as the main CPU.

if you choose gameboy, welcome to our club, we have lots of people with working gameboy emus, if you do msx, create a thread for it so we could follow your progress maybe even join your bandwagon :p

I havent touched my nes emu in more than a month but its not too far from running commercial, it just has some bugs in it keeping gfx from showing, might be resuming work on it sooner or later..

good luck with whatever path you choose!
 

_pm_

Pathetic Member
hap said:
Fixed mmc1, and mmc2 too (punch out), fixed sprites, added mmc3 without irq. I'm bound to meet 'Error' still many times during progress.

*edit* someone said no NES rom uses the BRK opcode. Well, Dragon Warrior 1 uses it. And it might also be worth noting that the game 'Super Cars' depends on undocumented opcodes.
Yes, "Super Cars" is such an annoying game to emulate properly.
 

|\/|-a-\/

Uli Hecht
i'm ready with the instructions. but what the hell ... mappers, mirroring ?! non ne capisco niente...
i think i understood the function of mappers, i don't like them ;)
but mirroring... why are some pages mirrored twice, i don't understood the sense... and where is that VRAM, in the cart or in nes or both? if i got right, the mappers controll the addressing...
ah, i'm a bit confused 'bout that stuff, hope ya can help me.
no google was no help
yes, i already wrote a chip8 emulator
 
OP
BGNG

BGNG

New member
The NES was designed to be reprogrammable on a hardware level in order to introduce expansions. Mirrored memory can typically be used as non-mirrored memory by providing in-cart RAM and rerouting the addresses. In this same manner, video memory can be provided by the cartridge. This is how the four-way split screen function works.
 

|\/|-a-\/

Uli Hecht
hm... i managed the other things too, so i don't know, why i've that problems now.
i give an example: i write to an address in a nes-memory page. this page is mirrored four times, like explaind in the docs. what do i have to do in my MemWrite() procedure now?

if i got right things work like this: the game gives an address higher than 0x10000, the mapper controls that and operates on the respective address in extra cart memory ?!?!? :alien2:

what are those registers used in emulators like reg8. the cpu regs and the ppu have other names as far i know. :plain:
 
Last edited:

|\/|-a-\/

Uli Hecht
hm, they are called reg8,regA,regC and regE (i'm not 100% sure about this), i think i got the answer: i read something about "page boundary addresses" in a memory mappers documentation.
 

hap

New member
i give an example: i write to an address in a nes-memory page. this page is mirrored four times, like explaind in the docs. what do i have to do in my MemWrite() procedure now?

For RAM mirroring, check whether the address is in the RAM region, and then mask it (use AND).

if i got right things work like this: the game gives an address higher than 0x10000, the mapper controls that and operates on the respective address in extra cart memory ?!?!?

It can't give an address higher than 0xffff. Extra cart memory (if the cart has it) is usually bankswitched to 0x6000.

what are those registers used in emulators like reg8. the cpu regs and the ppu have other names as far i know.

Proof that looking at other emulator's sources will confuse you instead of enlighten you. In this case (looking at your reply of today), it's probably a shortcut to mapper IO from 0x8000: reg8=0x8000-0x9fff, regA=0xa000-0xbfff, etc. This is handy, since many mappers use IO registers at the start of those regions.
 

smcd

Active member
@hap:

In your sources you have "binary.h" - 2.31MB or so! I dug around and found a macro someone I chat with made, and it might reduce your compile time and source size without sacrificing readability or speed

Original:
Code:
#define bo(x) ((x&1) | \
              (x>>3&1)<<1 |\
              (x>>6&1)<<2 |\
              (x>>9&1)<<3 |\
              (x>>12&1)<<4|\
              (x>>15&1)<<5|\
              (x>>18&1)<<6|\
              (x>>21&1)<<7)

#define b(x) bo(0##x)

#include <stdio.h>

int main(void) {
   int c=b(11111111);
   printf("%d\n", c);
   return 0;
}

My version to allow 16bits:
Code:
#include <stdio.h>

#define bo(x) ((x&1) | \
              (x>>3&1)<<1 |\
              (x>>6&1)<<2 |\
              (x>>9&1)<<3 |\
              (x>>12&1)<<4|\
              (x>>15&1)<<5|\
              (x>>18&1)<<6|\
              (x>>21&1)<<7)

#define	binary8(x)	bo(0##x)
#define binary16(x,y)	((bo(0##x)<<8)|(bo(0##y)))

int main(void)
{
	printf("binary8(10101010) = %d\r\nbinary16(11001100,11001100) = %d\r\n",
			binary8(10101010),
			binary16(11110000,11110000));
	return 0;
}
 
Last edited:

hap

New member
hmm, does it compile as int c=255 or int c=[lots of arithmetics] ?
I'm not familiar with "0##", what does it mean ?
 

smcd

Active member
It's a macro, so it'll expand into "lots of arithmetics" ##x puts the literal contents of "x" so it'll be 0< contents of x >. You can run gcc or g++ and tell it "preprocess only" to see the magic behind macros, it can be quite handy :) Also, just because you see all those shifts and ORs in the code doesn't mean the compiler can't "see" it ends up being a constant and optimizing it as such.

gcc -E makebin.c:
Code:
# 1 "makebin.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "makebin.c"
# 14 "makebin.c"
int main(void) {
   int c=((011111111&1) | (011111111>>3&1)<<1 | (011111111>>6&1)<<2 | (011111111>>9&1)<<3 | (011111111>>12&1)<<4| (011111111>>15&1)<<5| (011111111>>18&1)<<6| (011111111>>21&1)<<7);
   printf("%d\n", c);
   return 0;
}

Running it through gcc -S makebin.c:
Code:
	.file	"makebin.c"
	.def	___main;	.scl	2;	.type	32;	.endef
	.section .rdata,"dr"
LC0:
	.ascii "%d\12\0"
	.text
.globl _main
	.def	_main;	.scl	2;	.type	32;	.endef
_main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	andl	$-16, %esp
	movl	$0, %eax
	addl	$15, %eax
	addl	$15, %eax
	shrl	$4, %eax
	sall	$4, %eax
	movl	%eax, -8(%ebp)
	movl	-8(%ebp), %eax
	call	__alloca
	call	___main
	;
	;
	; it optimizes it quite well even with no -O switch, as we can see
	;
	;
	movl	$255, -4(%ebp)
	movl	-4(%ebp), %eax
	movl	%eax, 4(%esp)
	movl	$LC0, (%esp)
	call	_printf
	movl	$0, %eax
	leave
	ret
	.def	_printf;	.scl	3;	.type	32;	.endef

Running it through gcc -O3 -S makebin.c:
Code:
	.file	"makebin.c"
	.def	___main;	.scl	2;	.type	32;	.endef
	.section .rdata,"dr"
LC0:
	.ascii "%d\12\0"
	.text
	.p2align 4,,15
.globl _main
	.def	_main;	.scl	2;	.type	32;	.endef
_main:
	pushl	%ebp
	movl	$16, %eax
	movl	%esp, %ebp
	subl	$8, %esp
	andl	$-16, %esp
	call	__alloca
	call	___main
	movl	$LC0, (%esp)
	;
	;
	; looky, it optimized it into a single MOV of a constant!
	;
	;
	movl	$255, %eax
	movl	%eax, 4(%esp)
	call	_printf
	leave
	xorl	%eax, %eax
	ret
	.def	_printf;	.scl	3;	.type	32;	.endef
 
Last edited:

hap

New member
hap said:
Hmm, I think I've gotten somewhat bored with NES, I've hardly worked on it for nearly a month. I'm done with most of the fun stuff, and sound emulation scares me. I'll get back to it later probably, but in the meantime it's time for something new, like perhaps joining the Gameboy emulation programming bandwagon :p

*edit* or maybe the MSX... well, at least something with a Z80 in it as the main CPU.

The choice was MSX, but without progress that is worth mentioning, since I've gotten a bit interested again in the NES. Current additions (among other small things) are 2 player support, sram (the standard .sav files), and a couple of mappers. I'll mention the release of v1.1 here when it's ready, which should not be an alpha version anymore.

sethmcdoogle: your macro is working nicely in sega li.
 

aprentice

Moderator
hap said:
The choice was MSX, but without progress that is worth mentioning, since I've gotten a bit interested again in the NES. Current additions (among other small things) are 2 player support, sram (the standard .sav files), and a couple of mappers. I'll mention the release of v1.1 here when it's ready, which should not be an alpha version anymore.

sethmcdoogle: your macro is working nicely in sega li.

msx is a good choice. btw, did you get sound in your nes emu yet?
I'm thinking of resuming work on my nes emu as well, keep us up on your changes..
 

Top