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

Coding my game Cross Chase also for the NES in C (CC65)

Coding my game Cross Chase also for the NES in C (CC65)
by on (#224143)
I am trying to make a decent NES version of my "universal" 8-bit game Cross Chase (for all 8-bit systems).
Project page: https://github.com/Fabrizio-Caruso/CROSS-CHASE
Video of the current ugly NES version: https://www.youtube.com/watch?v=HK54rtE ... e=youtu.be

The current version is just using tiles and I am getting weird results if I don't disable the screen before modifing some color attributes. This is expected but I am not able to disable and re-enable the screen without losing the tile definitions.

I am using the current default nes.cfg linker file but I am linking my own file with the .byte defitions for the CHARS segment. If I disable and then enable the screen.
How come when I disable the screen, set some attributes and then enable it, all the tile data is lost?
"
PPU.control = 0;
PPU.mask = 0;
(set some color attributes here)
PPU.vram.address = 0;
PPU.vram.address = 0;
PPU.scroll = 0;
PPU.scroll = 0;
PPU.control = 0x90;
PPU.mask = 0x1e;
"

What am I doing wrong?

Fabrizio
Re: Coding my game Cross Chase also for the NES in C (CC65)
by on (#224147)
Might have to do with what has been discussed a few times in recent days:

viewtopic.php?p=223803#p223803 (but see thread entirely)

Use of C makes this more difficult to debug. You'll need to actually look at the assembly to see what's going on. The instructions and their order matter greatly.

You may need to set the scroll ($2005) to zero twice as the **last** piece of code. Try that first.

However, because you're playing with $2000 (PPU.control), you may need to read from $2002 (PPU.status) to get things to work. See https://wiki.nesdev.com/w/index.php/PPU_scrolling -- warning: VERY COMPLICATED TOPIC/WIKI PAGE. You've been warned.

Basically, whenever tinkering with $2000 (PPU.control), $2005 (PPU.scroll), or $2006 (PPU.vram_address), you may need to "reset" some values of those registers before the end of NMI for things to draw correctly. Sometimes reading $2002 (not sure what this is called in the struct; PPU.status maybe?) is required as well. Experts here can probably explain it to you better.

Use of C makes this more difficult to debug. You'll need to actually look at the assembly to see what's going on.
Re: Coding my game Cross Chase also for the NES in C (CC65)
by on (#224148)
"Losing the tile definitions" doesn't describe a familiar problem. Could you share a ROM exhibitng the problem? That would be a lot easier to diagnose.
Re: Coding my game Cross Chase also for the NES in C (CC65)
by on (#224149)
I took the interpretation, given the code provided, to indicate that visually things on-screen get munged. There may be a slightly language barrier.
Re: Coding my game Cross Chase also for the NES in C (CC65)
by on (#224222)
Thanks for your support!
Sorry, I am a NES noob...
I am coding my game als for the NES but I am distracted by the other systems.
My game is insanely cross-platform...

In the end, Shiru found my issue: I was switching to the wrong page:
PPU.control = 0x80;
PPU.mask = 0x1e;
fixes the issue (0x90 was wrong in my case).

The problem was with PPU.control = 0x90, all the tile data appeared as restored to their default (CC65 default) values.

My next step is to use sprites instead of tiles for animation.
I need to understand how to do this through OAM DMA or by direct writes into PPU memory (is it safe?).
I also need to wait for a vertical blank.
How do I wait for a vblank in C?

The current (ugly) NES version is available at:
https://github.com/Fabrizio-Caruso/CROS ... nes_fx.nes

The source code of the NES screen initialization is at:
https://github.com/Fabrizio-Caruso/CROS ... graphics.c
Re: Coding my game Cross Chase also for the NES in C (CC65)
by on (#224229)
Fabrizio Caruso wrote:
I need to understand how to do this through OAM DMA or by direct writes into PPU memory (is it safe?).
I also need to wait for a vertical blank.
How do I wait for a vblank in C?


I seem to remember reading on the wiki that it's possible to write directly to OAM memory on the PPU, but not recommended since it turns of DRAM refreshing or something. The warning was that if leave rendering turned off for too long your OAM values will decay and become corrupted.

CC65 provides a waitvsync() function, but it's not recommended to use it for fine timing. The NES has a hardware bug where the vblank flag will fail to read if written on the same cycle (or something like that). I used it initially in my first project, and the framerate stuttered until I moved to a "proper" NMI. It looks like you've used cc65 enough to know that writing an interrupt handler in C is not very practical. Just too much C state to save and restore.
Re: Coding my game Cross Chase also for the NES in C (CC65)
by on (#224247)
Yes. The OAM is extremely volatile, and needs to be written to every frame, and should be done with OAM DMA, during v-blank. (set up a 256 byte buffer that is aligned to a xx00 address)

And v-blank should be set up with the NMI system that is generated at the start of v-blank (if the NMI bit is turned on with PPU control register 2000)

You could either write an automatic OAM DMA transfer to occur within the NMI code, or you could have a counter which the NMI increments, and have your main code wait for the counter to change, then do the OAM DMA manually.

Have you read Shiru's neslib code? That might be helpful.