Getting CPU jams all the time.

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Getting CPU jams all the time.
by on (#84887)
I'm learning 6502 asm, and i'm creating a small project called Тетрис (or Tetris if you prefer), and this time i got the code for the title screen showing up, but it only gives me a CPU jam! Upon compiling and running on FCEUX, $0000 is BRK! But how? It happens in any emulator, i'm compiling it with NESASM3. Could anybody tell me a more suitable assembler for this?

The code is long, so i uploaded it to MediaFire: http://www.mediafire.com/?8b4gy1a4rgzbf4f

by on (#84889)
You should probably stick with pastebin (you can create multiple pastes if necessary) or use a good file-hosting service like DropBox.

I haven't looked at the code, but you shouldn't be trying to run code from $0000. Your code should start at $C000 or $8000, depending on the mapper. $0000 is RAM. $8000 to $FFFF is ROM. Your ASM code should .BASE or .ORG accordingly.
Re: Getting CPU jams all the time.
by on (#84891)
IvanDSM wrote:
I'm learning 6502 asm, and i'm creating a small project called Тетрис (or Tetris if you prefer)

I have plenty to say about this, but I'll hold back for now so that I can help you with your code. I just feel like getting one thing off my chest: Do you know what "lock delay" and "hard drop" are?

Quote:
and this time i got the code for the title screen showing up, but it only gives me a CPU jam! Upon compiling and running on FCEUX, $0000 is BRK!

$0000-$07FF is RAM, and it doesn't have a value until you put one there.

Quote:
The code is long, so i uploaded it to MediaFire: http://www.mediafire.com/?8b4gy1a4rgzbf4f

First let's get some power-up state compatibility problems out of the way:
Code:
   lda #%10000000
    sta PPU_CTRL

   jsr waitVBlank

waitVBlank is the "spin on PPU_STATUS" subroutine. Why are you turning on NMIs (the write to PPU_CTRL) before you spin on PPU_STATUS? You really shouldn't be writing anything after you've spun on PPU_STATUS twice. And before clearVRAM, you need one more JSR waitVBlank and then you can turn on NMIs in PPU_CTRL.

Why do you have palette code right in the middle of your code? Either JMP past it or move it out of the way of code.

It's best not to enable the display (write to PPU_MASK) until after the entire nametable has been written to VRAM. If you try to write to VRAM while the PPU is rendering, you'll just cause a load of glitches.

by on (#84893)
Oops, i meant $8000, not $0000!

Hey tepples, i still get CPU jams, what's going wrong? I did the things you said such as waiting for 2 VBlanks before starting the screen.

And thanks snarfblam! I'll use pastebin more often from now on!

http://pastebin.com/787pbWCn

by on (#84894)
IvanDSM wrote:
i still get CPU jams, what's going wrong? I did the things you said such as waiting for 2 VBlanks before starting the screen.

http://pastebin.com/787pbWCn

You're still enabling NMI (line 40) before having called JSR waitVBlank twice. Leave it disabled until after the PPU has fully warmed up. Replace lines 40-41 with
Code:
   stx PPU_CTRL
   jsr waitVBlank

And why do you have a waitVBlank inside the loop at line 55? Move it after bne clearRAM.

The waitVBlank calls at lines 75, 76, and 92 are unnecessary. After the PPU has warmed up, you should use only waitNMI.

At line 94, if the CPU keeps going, it'll fall right into the subroutine LoadBackground, and the RTS will send the program counter off into nowheresville.

by on (#84903)
tepples wrote:
At line 94, if the CPU keeps going, it'll fall right into the subroutine LoadBackground, and the RTS will send the program counter off into nowheresville.

I'm pretty sure this is what crashes the program. Your "mainLoop" is not a loop at all, since there's no "JMP mainLoop" at the end, and because of that, program execution continues right into the LoadBackground subroutine. But since it wasn't called with JSR, there's no address to return to when the RTS at line 107 is reached, so the CPU gets lost and crashes.

Your main loop has a weird structure though... First you pretend that you'll read the controller but you don't read the actual button states, then you do a bunch of PPU operations without having waited for VBlank or NMI first, which means that there are no guarantees that those procedures will take place during VBlank.

by on (#84918)
Been lurking this site for a while finally decided to sign up and post, so I might as well make my first post good.

I've looked over your code, and I found the primary problem. Your project assembled wrong, NESASM does not like to deal with banks larger than 8kb at a time, when you assembled it it the ROM came out to 24kb, it should've been 40kb. To fix that, add the line ".bank 3" right before ".org $fffa" that will put the vectors in the right spot and now it should assemble correctly. This will prevent it from crashing, but the rest of you code needs work too. Here is a good way to structure your code.
Code:
  ;defines here
Reset:
  ;disable nmi, display, and sound
  ;set stack pointer
  ;clear RAM/VRAM
  ;wait two VBlanks
  ;do your background loading here (since display and nmi are disabled)
  ;enable NMI, display (and sound when you have some)
MainLoop:
  ;get controller status
  ;other game code here
  ;loop that waits for NMI (have it check for a flag)
  ;after NMI is done and returned (clear the flag)
  ;jump to the beginning of the main loop
  ;subroutines here
NMI: ;(should set a flag so the loop that waits for nmi will exit)
  ;vectors here
  ;chr memory here
  ;end of code