This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

$8000 and $C000

$8000 and $C000
by on (#49815)
I read that in the structure of NES bus Program Code begin from $8000.
But I saw lots of code write :

.bank 0
.org $C000

Why do this ?

And when I use ".org $8000", however, using Debugger find in position $C000 my codes appear again. How can it be done?

My knowledge about NES Asm is all from the nesasm_Tutorial.pdf document.

Thanks a lot.

by on (#49817)
If you have mapper 0, 16 KiB of PRG (one iNES bank or two NESASM banks), and 8 KiB of CHR, you have the NROM-128 board. This board mirrors the same 16 KiB of code in $C000-$FFFF and $8000-$BFFF.

by on (#49818)
This stuff all depends on the memory map.

If you have a 16K PRG game, it will be mirrored across the full 32K ROM address space.
If you have a 32K PRG game, it will fill the entire 32K ROM address space.
If you have a bigger ROM which requires bankswitching, it depends on the mapper. Most mappers which use 16K sized banks make the C000 bank fixed, and the 8000 bank is switchable. Some mappers switch the entire 32K bank. Other mappers can use different banking methods, see documentation on each individual mapper.

Also remember that the address of the first executed instruction is determined by the Reset Vector at address $FFFC, it won't automatically jump to $8000 or $C000 on bootup unless that happens to be the address the Reset Vector is pointing to.

by on (#49823)
tepples wrote:
one iNES bank or two NESASM banks


Oh, this can explain why in NESASM codes' head there always be a declaration:
Code:
.inesprg 1
Is it mean that "I am declaring a iNES file format" so even NESASM need two banks, the coder should write like that( .inesprg 1)?

But the next line
Code:
.ineschr 1
show 1 bank, this mean both in iNES and NESASM need only one bank for CHR?

And...(forgive me) iNES is a file format, NESASM is a kind of asm language for nes. why they are not same at those places?

Thanks for your patient. :wink:

by on (#49824)
Dwedit wrote:
This stuff all depends on the memory map.

If you have a 16K PRG game, it will be mirrored across the full 32K ROM address space.
If you have a 32K PRG game, it will fill the entire 32K ROM address space.
If you have a bigger ROM which requires bankswitching, it depends on the mapper. Most mappers which use 16K sized banks make the C000 bank fixed, and the 8000 bank is switchable. Some mappers switch the entire 32K bank. Other mappers can use different banking methods, see documentation on each individual mapper.

Also remember that the address of the first executed instruction is determined by the Reset Vector at address $FFFC, it won't automatically jump to $8000 or $C000 on bootup unless that happens to be the address the Reset Vector is pointing to.


Thank you.
I notice $C000-$8000 = 16K is half of 32K(the PRG size)
so I understand the mapper function.
Through Debugger I saw code run start from $C000, is this depends on different mappers? I mean where to start. In Reset Vector the first code is start from $8000.

by on (#49826)
The first instruction that the CPU executes is always JMP ($FFFC). That would go to $8000 if the bytes at $FFFC are $00 $80.

Some mappers allow switching $FFFC. In this case, the reset vector would depend on what bank number was floating in the latch at power-on. Games using these mappers have to put the reset vector and about a dozen bytes of reset code into all banks, switch, and then jump to the rest of the reset code.

Despite the name, NESASM was originally designed to target the TurboGrafx-16 system, whose built-in mapper uses 8 KiB banks. NES support was an afterthought, and the bank numbers were a happy coincidence for NES mappers that use 8 KiB banks such as MMC3 and FME-7. But most simpler mappers use 16 KiB or 32 KiB banks.

by on (#49847)
Thank you. May I ask things about cc65?

by on (#49850)
Go ahead and ask us.

by on (#49886)
Ah...Say I use most simple code here:
Code:
#include <conio.h>
void main()
{
   clrscr();
   gotoxy(10,10);
   cprintf("Hello, world");
   while(1);
}


When it was compiled, I dragged the nes file to FCEUX, but nothing happen.
However, when I use fceu dsp , "Hello, world" came out.

That mean different emu. has different running environment? How to write an universe program by cc65? Or only nesasm could do that work?

Thank you.

by on (#49887)
What happens in Nintendulator and Nestopia?

by on (#49888)
Nestopia is OK.
nesasm is the only universe way?

by on (#49889)
0x7c00 wrote:
nesasm is the only universe way?

No, any assembler will be fine, as long as your code does not contain errors. The C compiler you are using most likely failed because the person who made it made mistakes with the generated assembly code.

by on (#49892)
But I don't think it's ca65's mistake. I mean the problem showed up in different emulator environment. The emulator provides a virtual environment to run nes, as far I know, there is not a standard for all developers who work on emulator. So I think the different may be a common question.

by on (#49893)
When a program works differently on different emulators, it's hard to tell where the problem is. Not necessarily the emulator that runs the program well is the correct one, it might very well be forgiving something that the program is doing wrong, while other emulators and real consoles are more strict.

But the truth is that a well coded program should run mostly the same across different emulators, unless it uses all sorts of complex tricks. Hello World is as simple as it gets, and if it doesn't work the same in all emulators, something went really wrong during the creation of the program.

by on (#49894)
In that case, there is a defect either in the startup code (which runs before main()) or in one or more emulators. The defect could in fact be in both the startup code and the emulator, if the startup code does something no game from the NES's commercial era ever did (possibly because the game would fail lot check if it did) and emulators aren't prepared to handle it.

by on (#49895)
Here is my nesasm code:
Code:
   .inesprg 1
   .ineschr 0
   .inesmap 0
   .inesmir 0
   
   .bank 0
   .org $8000
RESET:
   lda #%10000000
   sta $2001
   
FOREVER:
   jmp FOREVER
   
   .bank 1
   .org $FFFA
   .dw 0
   .dw RESET
   .dw 0


In Nestopia there is nothing, however in fceux, it gets its function(display blue)...Nowadays I'm confusing about the different between emulators :?

by on (#49896)
Your palette isn't initialized so it will display the defaut BG color of your NES (the one that show up when a cart isn't functionning) with a slight blue tend.

by on (#49897)
0x7c00 wrote:
Nowadays I'm confusing about the different between emulators :?

I told you, if a program is well coded and doesn't use crazy tricks, it should work the same on all emulators.

There are several things wrong with your code: You don't do any initialization whatsoever, you don't wait for the PPU to warm up (2 frames), your IRQ and NMI vectors point to something that is not code...

There are many things you have to fix before you can claim the emulators behave differently, because it's very likely they will if the program itself is completely broken.