Code not working, clues?

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
CrowleyBluegrass
Posts: 42
Joined: Sun Jun 30, 2013 7:59 am

Code not working, clues?

Post by CrowleyBluegrass »

Hey guys. After reading around for a while I've decided to start doing some assembling. I'm trying to write a simple program (based on Nerdy Nights) that sets the red emphasis bit when you press the A button. The problem is that, well, nothing happens. I've tried to correct it myself, but I can't seem to find out what is wrong. I'm sure it's something painfully obvious. I have emphasis set as a variable because I eventually want to scroll through the emphasis bits when you press the A button by using ASL. Thanks to tokumaru for his template :)

Code: Select all

;----------------------------------------------------------------
; constants
;----------------------------------------------------------------

PRG_COUNT = 2 ;1 = 16KB, 2 = 32KB
MIRRORING = %0001 ;%0000 = horizontal, %0001 = vertical, %1000 = four-screen
FRAMECOUNTER = 0
EMPHASIS = %00100000

;----------------------------------------------------------------
; variables
;----------------------------------------------------------------

   .enum $0000

   ;NOTE: declare variables using the DSB and DSW directives, like this:

   ;MyVariable .dsb 1
   ;MyVariable1 .dsb 3

   .ende

   ;NOTE: you can also split the variable declarations into individual pages, like this:

   ;.enum $0100
   ;.ende

   ;.enum $0200
   ;.ende

;----------------------------------------------------------------
; iNES header
;----------------------------------------------------------------

   .db "NES", $1a ;identification of the iNES header
   .db PRG_COUNT ;number of 16KB PRG-ROM pages
   .db $01 ;number of 8KB CHR-ROM pages
   .db $00|MIRRORING ;mapper 0 and mirroring
   .dsb 9, $00 ;clear the remaining bytes

;----------------------------------------------------------------
; Init
;----------------------------------------------------------------

    .base $8000

Reset:
  SEI          ; disable IRQs
  CLD          ; disable decimal mode
  LDX #$40
  STX $4017    ; disable APU frame IRQ
  LDX #$FF
  TXS          ; Set up stack
  INX          ; now X = 0
  STX $2000    ; disable NMI
  STX $2001    ; disable rendering
  STX $4010    ; disable DMC IRQs

vblankwait1:       ; First wait for vblank to make sure PPU is ready
  BIT $2002
  BPL vblankwait1

clrmem:
  LDA #$00
  STA $0000, x
  STA $0100, x
  STA $0200, x
  STA $0400, x
  STA $0500, x
  STA $0600, x
  STA $0700, x
  STA $0300, x
  INX
  BNE clrmem

vblankwait2:      ; Second wait for vblank, PPU is ready after this
  BIT $2002
  BPL vblankwait2

;----------------------------------------------------------------
; code
;----------------------------------------------------------------
  LDA #%10000000   ; enable NMI
  STA $2000

Loop:
lda FRAMECOUNTER ;wait for vblank
cmp FRAMECOUNTER
beq Loop

ReadController1:
  lda #$01
  sta $4016
  lda #$00
  sta $4016     ; tell both the controllers to latch buttons

  lda $4016     ; player 1 - A button
  and #%00000001
  beq Loop ;if A is not pressed, wait for vblank

  lda EMPHASIS ;if A is pressed
  sta $2001

  JMP Loop     ;jump back to Loop, infinite loop

  NMI:
  INC FRAMECOUNTER
  RTI

;----------------------------------------------------------------
; interrupt vectors
;----------------------------------------------------------------

  .org $fffa     ;first of the three vectors starts here
  .dw NMI        ;when an NMI happens (once per frame if enabled) the
                 ;processor will jump to the label NMI:
  .dw Reset      ;when the processor first turns on or is reset, it will jump
                 ;to the label RESET:
  .dw 0          ;external interrupt IRQ is not used in this tutorial


;;;;;;;;;;;;;;

  .incbin mario.chr   ;includes 8KB graphics file from SMB1
zzo38
Posts: 1080
Joined: Mon Feb 07, 2011 12:46 pm

Re: Code not working, clues?

Post by zzo38 »

I don't think that is a very good way to wait for vblank, although in what you are doing, I don't think you need to wait for vblank.
[url=gopher://zzo38computer.org/].[/url]
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Re: Code not working, clues?

Post by 3gengames »

zzo38 wrote:I don't think that is a very good way to wait for vblank, although in what you are doing, I don't think you need to wait for vblank.
It's a perfect way to wait for vblank if you know what you're doing with it.

And the code should work because you're missing 10000 other things. You need to set your palette, set up the screen, enable the PPUMask, and tons of other stuff. Always initiating stuff you use if a fairly obvious thing that needs to be done that wasn't done here. Better get used to it, or you won't program much that doesn't have glitches that make program not work on hardware.
CrowleyBluegrass
Posts: 42
Joined: Sun Jun 30, 2013 7:59 am

Re: Code not working, clues?

Post by CrowleyBluegrass »

I'm trying to get used to how programs usually flow/code layout, hence waiting for vblank even though it's not necessary. I assume my lack of knowledge in regards to program flow is the cause of the problem, but I just can't seem to figure it out.

The reason a lot of things aren't set up, is because I'm using the Nerdy Nights tutorials as a base, just slotted into tokumaru's ASM6 template. It worked fine until I added the controller checks. Forgive my blasphemy, but I'm not concerned whether my code works on real hardware at this early stage.

Thank you both :)
Last edited by CrowleyBluegrass on Sat Jul 06, 2013 12:12 pm, edited 1 time in total.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Re: Code not working, clues?

Post by 3gengames »

It's necessary everywhere in there...well, you could technically cut out the first and be okay, but it's not really that bad the first wait. I'd keep it in too.

And it can work, but it shouldn't. You NEED all of those things I mentioned. Key word is NEED. Maybe stop jumping assembler ships and such, and start reading the Wiki so you understand the hardware better, with what you need to and don't need to do. Stick with NESASM3 until you can edit your stuff easier and understand why you need to edit some code/make it. You have a good grasp, just need to refine it so you're more confident about code. Not being sure how to code and use the assembler is a bad combination to have. Still, the things you need to do are:

Upload a palette.

Set up the screen.

Enable rendering. (Disabled on start up on NES, so how would it ever work if you don't turn it on?) You touch it with the emphesis bit, but rendering then is disabled. You may technically change the output, but it's not reliable in any way because you have 0 clue on the state of the palette pointer, palette, screen tiles, anything.

Then do your code stuffs.

http://wiki.nesdev.com/w/index.php/PPU
CrowleyBluegrass
Posts: 42
Joined: Sun Jun 30, 2013 7:59 am

Re: Code not working, clues?

Post by CrowleyBluegrass »

Thanks for the advice.

As I said, everything was working fine (despite not uploading a palette etc.) until I added the input check. I wasn't aware the things you mentioned were necessary because they weren't in the NN code, which I'm merely adding controller input to as a way of getting my feet wet (without drowning) :oops:

I'll go back to lurking the wiki for a while.

Thanks again.
User avatar
Movax12
Posts: 529
Joined: Sun Jan 02, 2011 11:50 am

Re: Code not working, clues?

Post by Movax12 »

if your code isn't working you should try to remember to always check if you forgot a # first. If you don't use it where you should, odd things tend to happen, and you have made that error here.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Re: Code not working, clues?

Post by 3gengames »

Yep, basically if you want you can set $2007 to $3F00, and upload all 20's to make the screen white. Then the background *could* be left uninitiated. Just enable rendering, and then write it to the screen. Try to make it determine if A is pressed like:

Code: Select all

  LDA $4016 ;Load A button status.
  LSR A ;Put A on to carry.
  LDA #%00011110 ;Enable rendering.
  BCC .NoEmphesis
  ORA #%00100000 ;Turn on what we need to if it's changed.
.NoEmphesis:
  STA PPUMask ;Replace with right location, I don't remember the exact location, I call them by names.
;Done.
Basically load the common value, and change it based on the carry/another flag used elsewhere to minimize size of code and keep flow working as linearly as possible.
User avatar
qbradq
Posts: 952
Joined: Wed Oct 15, 2008 11:50 am

Re: Code not working, clues?

Post by qbradq »

Movax12 found the bug. Your LDA EMPHASIS line is loading the RAM value at $20, not the literal value. Change it to LDA #EMPHASIS and it might start working again.

I agree that proper initialization is important. Even the most basic of experiment programs needs to have complete initialization or you'll start to have strange errors, especially if you test on the more accurate emulators.
unregistered
Posts: 1193
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Code not working, clues?

Post by unregistered »

qbradq wrote:Movax12 found the bug. Your LDA EMPHASIS line is loading the RAM value at $20, not the literal value. Change it to LDA #EMPHASIS and it might start working again.
In 6502 assembly a "#" is used for literal values.

Code: Select all

lda #20
that code will set the accumulator up with #$14.

Code: Select all

lda $20
and that will load the accumulator with the value at memory location $0020.

Code: Select all

lda #$20
and that will load the accumulator with #$20. That's a literal(#) hexadecimal($) 20... Looks like 00100000b in binary asm6.
CrowleyBluegrass
Posts: 42
Joined: Sun Jun 30, 2013 7:59 am

Re: Code not working, clues?

Post by CrowleyBluegrass »

I've tried sorting it out a little bit, but still having some graphical problems.

Code: Select all

; iNES header

; iNES identifier
.byte "NES",$1a 

; Number of PRG-ROM blocks
.byte $01

; Number of CHR-ROM blocks
.byte $01

; ROM control bytes: Horizontal mirroring, no SRAM
; or trainer, Mapper #0
.byte $00, $00

; Filler
.byte $00,$00,$00,$00,$00,$00,$00,$00

;;;;;;;;;;;;;;;
;Variables

enum $0000

FRAMECOUNTER .byte 0

ende

;;;;;;;;;;;;;;;;
;Init

.org $C000
RESET:
  SEI          ; disable IRQs
  CLD          ; disable decimal mode
  LDX #$40
  STX $4017    ; disable APU frame IRQ
  LDX #$FF
  TXS          ; Set up stack
  INX          ; now X = 0
  STX $2000    ; disable NMI
  STX $2001    ; disable rendering
  STX $4010    ; disable DMC IRQs

vblankwait1:       ; First wait for vblank to make sure PPU is ready
  BIT $2002
  BPL vblankwait1

clrmem:
  LDA #$00
  STA $0000, x
  STA $0100, x
  STA $0200, x
  STA $0400, x
  STA $0500, x
  STA $0600, x
  STA $0700, x
  LDA #$FE
  STA $0300, x
  INX
  BNE clrmem

vblankwait2:      ; Second wait for vblank, PPU is ready after this
  BIT $2002
  BPL vblankwait2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Main code setup

LoadPalettes:
  LDA $2002    ; read PPU status to reset the high/low latch
  LDA #$3F
  STA $2006    ; write the high byte of $3F00 address
  LDA #$00
  STA $2006    ; write the low byte of $3F00 address
  LDX #$00
LoadPalettesLoop:
  LDA palette, x        ;load palette byte
  STA $2007             ;write to PPU
  INX                   ;set index to next byte
  CPX #$20
  BNE LoadPalettesLoop  ;if x = $20, 32 bytes copied, all done

SetupScreen:
  LDA #%00001000   ; enable rendering
  STA $2001

  LDA #%10000000   ; enable NMI, sprites from Pattern Table 0
  STA $2000
  
  LDA #$00
  LDY #$00

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Main code
Loop:
  CPY FRAMECOUNTER
  BEQ Loop

Main:
  LDA #$01            ;tell both the controllers to latch buttons
  STA $4016
  LDA #$00
  STA $4016
  LDA $4016           ;get A button status
  LSR                     ;shift A button status onto carry
  LDA #%00001000 ;set A to default no emphasis
  BCC Loop             ;if A is not pressed wait for vblank
  LDA #%00101000 ;if A is pressed, set emphasis to red

NMI:
  INC FRAMECOUNTER
  STA $2001     ;update emphasis on screen
  RTI

;;;;;;;;;;;;;;

  .org $E000
palette:
  .db $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
  .db $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20


  .org $FFFA     ;first of the three vectors starts here
  .dw NMI        ;when an NMI happens (once per frame if enabled) the
                   ;processor will jump to the label NMI:
  .dw RESET      ;when the processor first turns on or is reset, it will jump
                   ;to the label RESET:
  .dw 0          ;external interrupt IRQ is not used in this tutorial

;;;;;;;;;;;;;;


  .incbin "mario.chr"   ;includes 8KB graphics file from SMB1
Produces unwanted (albeit mildly enjoyable) flashy effects, which I'm pretty sure is due to the layout of my code as everything seemed to work fine when it was all handled by the NMI. I'm trying to "prepare" the emphasis update in the main code, and use the NMI routine solely for updating the screen (storing A into PPUMASK). Clearly, I have no idea how to do this correctly and your help would be much appreciated. If you'd like to point out any problems in my init code too, that'd be fab.

Thank you :)

P.S here's my yet untested (for very obvious reasons!) code for switching between the emphasis bits if you're particularly unoccupied. Parentheses indicate clock cycles for each line.

Code: Select all

           LDA #%00100000
           STA EMPHASIS
           MAIN:   
           LDA $4016     ;get A button status (4)
           BEQ LOOP      ;if A is not pressed wait for vblank (2)or(3)
           LDA #%00001000;set rendering bit in A (2)
           ORA #EMPHASIS ;set emphasis bit in A (4)
           BPL-          ;if emphasis is not set to blue, skip to shift left (2)or(3)
           LDY #%00010000;otherwise, set EMPHASIS to the bit right of red (2)
           STY EMPHASIS ;(3)
-          ASL #EMPHASIS ;shift emphasis bit left for next run (6)
           LDY FRAMECOUNTER;set up check for loop (4)
[/size]
User avatar
qbradq
Posts: 952
Joined: Wed Oct 15, 2008 11:50 am

Re: Code not working, clues?

Post by qbradq »

You're still not clearing sprite memory. Also, this code is WAY more complex than it needs to be with the register sharing.

To answer your question, your code is failing because you need to have a "JMP Loop" instruction at the end of your main block there.

The way your code is now when you hold down the A button, you skip the branch, load the A register with the emphasis bits you want, then start executing the NMI routine, then RTI with no return address on the stack. That'll probably start executing whatever's in RAM at $0000, which appears to be all zero's thanks to your initialization, which forces a break instruction, which executes your IRQ vector, which is again set to $0000. So then you enter an infinite loop of IRQ's.

Brain 'splosion!

Don't give up! You're doing great! Assembly is freaking hard stuff. All of us here have went through something like this at one point or another. Just keep at it and you'll get better.
CrowleyBluegrass
Posts: 42
Joined: Sun Jun 30, 2013 7:59 am

Re: Code not working, clues?

Post by CrowleyBluegrass »

I done fixed it :)
It appears that in the future, I must bear one important detail in mind. The 6502 can not read my mind to figure out where to go next! I added the JMP Loop you suggested but of course, it was still flashing incessantly. Mostly due to the fact that I was re-setting the emphasis every time the main code was executed without the A button pressed!

I never though it could be so fulfilling to have a orangey screen pop up when you press a button, haha. Slowly but surely.

Thank you my friend.

Lest this topic become redundant (god forbid!) would anyone like to suggest a less convoluted method for switching through the emphasis bits?
Last edited by CrowleyBluegrass on Wed Jul 10, 2013 4:57 pm, edited 1 time in total.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Re: Code not working, clues?

Post by 3gengames »

Yeah, just keep working to understand 6502 more and eventually you'll get a good NMI routine and keep a RAM emphasis that has the current emphesis settings, and just write it every frame. And also, make sure in the future you put controller buttons to RAM. Reading them straight from $4016 is piss poor for any real game, this it can be done with "just to easily get one button" but in the future, not so much.
Post Reply