|And a read function which reads from a 16-bit address and returns a 16-bit value!|
fucking little endian
Yup that's definitely an approach. ;)
Also little endian is superior. In the case of the 6502 it literally speeds up the CPU.
|Also, I notice that several memory regions in the 6502 are mirrored and such, and program data starts from 0x8000 onwards. Is it important to mirror everything to specification? Or will it end up not mattering?|
For most games it won't matter... but every once in a while you'll run into a weird one.
Mirroring isn't difficult to do, though. What I typically do is have reads/writes to each of the $X000 pages go to a different function. For example... $0000 and $1000 pages would read system RAM... but since there is only 2K system ram and not 8K.. you just mask out the low bits to mirror it:
u8 read(u16 a)
return ram[a & 0x07FF]; // <- handles all your mirroring
Likewise, the 8 ppu regs that are mirrored across $2xxx and $3xxx pages:
u8 read(u16 a)
switch(a & 7)
case 0: // $2000
case 1: // $2001
|And implementing a memory mapper (for roms with more than 32kb of data and can't fit all at once in the 6502's memory) is still confusing to me. How would the mapper know when to switch out memory regions? |
bankswitching is usually (99% of the time) triggered by a register write. Most mappers put their registers in ROM space (between $8000-FFFF) since ROM can't be written to anyway.
Mapper 2 is probably the easiest.
$8000-BFFF is the swappable bank
$C000-FFFF is fixed at the last bank
The game swaps out the $8000 page by writing anywhere in $8000-FFFF. The value written determines the 16K page number to swap in.
I wrote a ton of mapper docs a long while back which outlined the details. The wiki has more up-to-date and accurate info on many of them.... but personally I find the format of my docs easier to understand.
But all of that said... I wouldn't worry about mappers until you get basic "mapper 0" games running.