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

Strange behavior in Nestopia

Strange behavior in Nestopia
by on (#152689)
Wasn't Nestopia created to be a cycle-exact emulator? Yet, my game/sample doesn't work with it while it works fine in FCEUX and even the old FCE Ultra 0.98.12.

Now the thing is: My program also works on a real NES with the PowerPak.

The problems is Nestopia: The status bar shows incorrect tiles. And while the controller input is registered (I used a sprite that shows me the controller status and it changes whenever I press a button), my moving sprite doesn't move when I press a button.

Are these well-known problems? Or is it something new and I should upload a sample code and a sample ROM?
Re: Strange behavior in Nestopia
by on (#152700)
Incorrect tiles, with the effect varying between emulators and hardware, may be an artifact of uninitialized nametable memory or uninitialized MMC3 CHR bank registers. The initial state of both is unspecified. For example, on MMC3, you should write to bank registers 0-5 before turning on rendering. A ROM or screenshot might help us narrow down the problem.
Re: Strange behavior in Nestopia
by on (#152702)
Before blaming Nestopia, you should keep in mind that if you're not doing anything out of the ordinary, your program SHOULD be working everywhere. Any decent emulator should run a program that does everything by the book and doesn't exploit hardware quirks. FCEU(X) is notoriously inaccurate, and the PowerPak not only messes up the Power up state of the console, but many of its mappers aren't 100% correct either.

I second tepples' request: a ROM or screenshots should help us diagnose the problem.
Re: Strange behavior in Nestopia
by on (#152757)
Alright, I created a little sample file. (See attachment.)

It's a simple mapper 0 program. And I do initialize the whole background graphics. The incorrect data is only the score anyway. And that one is updated in every frame.

This is what it looks like in fceux:
Image

This is what it looks like in Nestopia:
Image

Note the garbled score in the top.

In fceux, you can control the ball with the d-pad. In Nestopia, it doesn't work.

Besides, if you move the ball out of the screen on the right side, the score is increased.
Re: Strange behavior in Nestopia
by on (#152761)
I'd prefer you post the relevant asm code, or the entire asm code as a file if you're not sure where the problem is. Preferably with appropriate labels and comments. I don't want to have to look line by line in a debugger to try to figure out your code.
Re: Strange behavior in Nestopia
by on (#152769)
Alright, I found the location that produces the error, but not the actual reason:

If I declare a variable in the zeropage, it's fine in both emulators. If I declare it in the regular RAM section, it works only with fceux.

I used CC65 and I didn't use any additional config file. I let the compiler use the built-in one.

My compile command is this:
Code:
cl65 -t nes -LC:\cc65\lib -o Test.nes Test.s


Below, you'll find my code. Search for the word IMPORTANT to find the relevant stuff.
Also, you'll find the config file that CC65 uses.

The "Graphics.chr" is attached. The ROM as well.

In fceux, you'll see a 1 within all the zeroes on the screen as declared in the code. In Nestopia, you'll see a blank space (since all tiles are empty, except for numbers and letters and he took some random tile).

Code:
.segment "HEADER"
   .byte "NES", $1A, $02, $01, $01, $00

.segment "STARTUP"

.segment "ZEROPAGE"
   Pointer: .res 2

; IMPORTANT: With ZEROPAGE, it works.
.segment "BSS"
   Score: .res 1

.segment "CODE"

Reset:
   SEI
   CLD
   LDX #$40
   STX $4017
   LDX #$FF
   TXS
   INX
   STX $2000
   STX $2001
   STX $4010
   BIT $2002
@waitForVBlank1:
   BIT $2002
   BPL @waitForVBlank1
   LDA #$00
   STA Pointer
   STA Pointer + 1
   TAX
   TAY
@outerLoop:
@innerLoop:
   STA (Pointer), Y
   INY
   BNE @innerLoop
   INC Pointer + 1
   INX
   CPX #$08
   BNE @outerLoop
   LDA #$F4
   LDX #$00
@loop:
   STA $0200, X
   INX
   BNE @loop
@waitForVBlank2:
   BIT $2002
   BPL @waitForVBlank2
LoadPalettes:
   LDA $2002
   LDA #$3F
   STA $2006
   LDA #$00
   STA $2006
   LDX #$00
@loop:
   LDA Palettes, X
   STA $2007
   INX
   CPX #$20
   BNE @loop

   ; IMPORTANT: Score is set to 1.
   LDA #$01
   STA Score

   LDA #%10010000
   STA $2000
   LDA #%00011110
   STA $2001
@forever:
   JMP @forever


Nmi:
   LDA #$00
   STA $2003
   LDA #$02
   STA $4014

   ; IMPORTANT: Score (i.e. tile 1) is drawn to the PPU into a specific location.
   LDA $2002
   LDA #$20
   STA $2006
   LDA #$6D
   STA $2006
   LDA Score
   STA $2007

   LDA #$00
   STA $2006
   STA $2006
   STA $2005
   STA $2005

   RTI

.segment "VECTORS"

   .word $00, $00, $00
   .word Nmi
   .word Reset
   .word 0

.segment "RODATA"

Palettes:
   .byte $21, $00, $10, $30, $21, $10, $30, $12, $21, $05, $26, $16, $21, $23, $12, $31
   .byte $21, $18, $16, $36, $21, $16, $24, $36, $21, $07, $F0, $36, $21, $38, $12, $36

.segment "CHARS"

   .incbin "Graphics.chr"


Code:
MEMORY {
ZP:  start = $02, size = $1A, type = rw, define = yes;
HEADER: start = $0, size = $10, file = %O ,fill = yes;
ROM0: start = $8000, size = $7ff4, file = %O ,fill = yes, define = yes;
ROMV: start = $fff6, size = $c, file = %O, fill = yes;
ROM2: start = $0000, size = $2000, file = %O, fill = yes;
SRAM: start = $0500, size = $0300, define = yes;
RAM: start = $6000, size = $2000, define = yes;
}

SEGMENTS {
HEADER:   load = HEADER,          type = ro;
STARTUP:  load = ROM0,            type = ro,  define = yes;
LOWCODE:  load = ROM0,            type = ro,                optional = yes;
INIT:     load = ROM0,            type = ro,  define = yes, optional = yes;
CODE:     load = ROM0,            type = ro,  define = yes;
RODATA:   load = ROM0,            type = ro,  define = yes;
DATA:     load = ROM0, run = RAM, type = rw,  define = yes;
VECTORS:  load = ROMV,            type = rw;
CHARS:    load = ROM2,            type = rw;
BSS:      load = RAM,             type = bss, define = yes;
HEAP:     load = RAM,             type = bss, optional = yes;
ZEROPAGE: load = ZP,              type = zp;
}

FEATURES {
CONDES: segment = INIT,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
CONDES: segment = RODATA,
type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__;
CONDES: type = interruptor,
segment = RODATA,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__;
}

SYMBOLS {
__STACKSIZE__ = $0300;
}
Re: Strange behavior in Nestopia
by on (#152771)
STA (Pointer), Y

'Pointer' must be a location in the zero page, if it it used like this as an indirect address.
Re: Strange behavior in Nestopia
by on (#152775)
There might be a problem with this line too...
Quote:
ROMV: start = $fff6, size = $c

$c seems like too many bytes, you could be writing 2 bytes past the vectors, which would screw up your CHRROM start point.

Fix = change fff6 to fff4 here.
Re: Strange behavior in Nestopia
by on (#152776)
dougeff wrote:
STA (Pointer), Y

'Pointer' must be a location in the zero page, if it it used like this as an indirect address.

As you can see, "Pointer" is in the zero page:
Code:
.segment "ZEROPAGE"
   Pointer: .res 2

; IMPORTANT: With ZEROPAGE, it works.
.segment "BSS"
   Score: .res 1


The question is why "Score" only works inside the zero page.

dougeff wrote:
There might be a problem with this line too...
Quote:
ROMV: start = $fff6, size = $c

If this line was incorrect, wouldn't the program fail completely? I mean, the vectors are clearly in the correct position. Furthermore, such an error would corrupt all graphics data, not just a single tile that is only incorrect when a certain variable is not in the zeropage.

P.S.: Yes, the value in the config file is incorrect. But the code comensates for it until I use a custom file:
Code:
.segment "VECTORS"

   .word $00, $00, $00
Re: Strange behavior in Nestopia
by on (#152778)
I might have to look at it in a debugger, like I was hoping I wouldn't have to. I'll do that when I get home and back to my computer.

Edit: are you sure...fff6 + c = 10002. Two bytes too many.
Re: Strange behavior in Nestopia
by on (#152779)
Without knowing too much about cx65, I would assume it's because in your config BSS = RAM, and RAM is set to start at $6000, but your game is NROM and NROM doesn't typically have RAM there, so you're reading back open bus values.

The reason it works on Powerpak/some emulators is probably because it's better to allow writes to that segment than not, because the header might be wrong about whether or not the game has RAM there. If you were running the game off an actual NROM board without the RAM, the behavior would likely match Nestopia.

Edit: Rainwarrior linked to a good .cfg setup in this post: viewtopic.php?p=152490#p152490

Edit2: Indeed, in your ROM there are a lot of LDA $6XXXs.

Edit3: No idea about the controller. Post your controller read code and things. I could disassemble it, but that's more work when you could just post the code.
Re: Strange behavior in Nestopia
by on (#152781)
No wait, Kasumi is right. And if you specifically want it to be a non-zero page address, it should start at ...not 200, that's where your sprites are...um, 300.
Re: Strange behavior in Nestopia
by on (#152783)
Alright, looks like I really have to do the config file next. I was hoping that I could do this later, but if the default one really isn't made for my type of game, then I'll check it out before I program anything else.
Thanks for finding out the solution.