ASM6 and trouble with nametables...

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

JoeGtake2
Posts: 333
Joined: Tue Jul 01, 2014 4:02 pm

ASM6 and trouble with nametables...

Post by JoeGtake2 »

I'm bashing my head against ASM at the moment, (using ASM6 to assemble) and I'd like to reach out and thank those who have given in depth responses. I'm very competent in high level languages such as javascript and C# for development, and generally get the logic in ASM after a few days of muscling through.

The new monster is nametables. Literally, I can not update my code to show a background. Even doing it the longhand way is giving me some unexpected results. I thought creating a .nam file from a capable program and using a loop to load it would work, but so far...nothing. I'm successfully .incbin-ing .chr files and .pal files, so I'm making the assumption the .nam file is loading just dandy, too...but I'll be damned if I can get anything to draw to the screen no matter what I try.

Sprites are showing. Palettes are correct. Just no background. I'm stumped and I'm going crosseyed playing with it, so hopefully someone can demonstrate my (probably very obvious) mistake(s).

Here's my very general process:

Code: Select all

;;;After header, I declare variables for high and low bytes:
	.enum $0000
	addrLo .dsb 1
	addrHi .dsb 2
	.ende

   ;;I've tried setting up the PPU prior to and after loading background, 
   ;;neither of which had any different affect.
   ;; load the background:


	lda $2002
	lda #$20
	STA $2006
	LDA #$00
	STA $2006
	
	;; load nametable
	LDA #>myNam
	sta addrLo
	lda #<myNam
	sta addrHi
	
	jsr LoadBkg

    ;;I've then tried putting LoadBkg just about everywhere...
    ;;prior to the main game loop (which is where    
    ;;I thought I should put it...like, where I load the palatte data and whatnot), 
    ;;IN the main game loop, in the interupts...just trial and error, really...
    ;; since it was not working.

LoadBkg:
	ldx #4
	ldy #00

loadData:
	lda (addrLo),y
	sta $2007
	iny
	bne loadData
	
	inc addrHi
	dex
	bne loadData
	rts

    ;; and then load the binaries for chr data and nam file...I
    ;; I've tried these both ways in case the order mattered...
    ;; again, trial and error.

	.incbin "main.chr"
myNam:	.incbin "mainBkg.nam"
  

I fully, humbly admit that I may have some dramatic misconceptions about things, but man...I feel like I was really getting it very well and then bam...hit a brick wall, and despite scouring and experimenting with advice from online resources, couldn't make this simple thing work.

If anyone can shed some light on what I am doing wrong and/or glaring misconceptions I may have, please let me know!

BTW - so far this forum has rocked. Thank you so much for the help, to all of you who have helped!
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: ASM6 and trouble with nametables...

Post by rainwarrior »

Some ideas:
  • Is the background not showing, or is the nametable not filled with the expected data? What does the nametable debug view in FCEUX show?
  • When you are writing the nametable through $2007, did you first disable rendering (i.e. write 0 to $2001)?
  • When you resume rendering, did you enable the background (another write to $2001)?
  • Is the correct nametable and tileset selected via $2000?
  • Did you set the scroll after you finished writing the nametables (using $2006/$2007 clobbers the scroll position, you need to write $2005 twice to reset it after writing to the nametable)?
User avatar
Memblers
Site Admin
Posts: 4044
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Re: ASM6 and trouble with nametables...

Post by Memblers »

JoeGtake2 wrote:

Code: Select all

	;; load nametable
	LDA #>myNam
	sta addrLo
	lda #<myNam
	sta addrHi
  
That would be the problem. You've got the > and < switched around, so it's loading the upper byte into addrLo, and vice-versa.

I normally use a macro for this (it's for ca65, but I guess should convert to ASM6 easily enough), makes the source easier to read IMHO, and less typing hopefully means less typos. :)

Code: Select all

;---------------------------------------------------------
;---------------------------------------------------------
;       Load 16-bit pointer (for indirect addressing)
;       (macro: pointer target,zeropage)
;---------------------------------------------------------
.macro  pointer   addr,addr2
                lda #<addr
                sta addr2
                lda #>addr
                sta addr2+1
.endmacro
edit: Also don't forget to set $2006 to $0000 when you're done.
JoeGtake2
Posts: 333
Joined: Tue Jul 01, 2014 4:02 pm

Re: ASM6 and trouble with nametables...

Post by JoeGtake2 »

Thanks so much, both of you guys.

Rainwarrior - debugging shows that the nametable is not filled with the right data (all with tile 0 instead). Also, I noticed that my palette file only seemed to load sprite palette and not bkg palette, so I just threw up the longhand way for now...I think that was my fault.

As for points 2 and 3, I think I've done that correctly, I'll post the code below to where I disabled and re-enabled rendering (at $2001)...could absolutely be incorrect placement on my part.

I believe that the correct nametable and tileset are selected via $2000...if they are not, I'm not certain how to do it. I'm only playing with a single nametable right now.

There is no scrolling in this yet. I'm not sure if I still have to write to $2005 for a static screen...if so, I haven't seen that on any resources I've looked at yet.


Memblers - I made that correction...I think that was just sloppiness on my part. Unfortunately, fixing this did not fix the problem.

I'm going to post the code in its entirety (with comments for the amendments you suggested that were either there or that I've updated). Please feel free to eviscerate it if it's messy and let me know what it is I'm doing wrong! I have no pride here, I'm just learning, but I feel like I get the code, it's just not doing what it's supposed to be doing. I assume it is a case of mistaken placement of something or otherwise some little tidbit I haven't learned yet. Does anything jump out at you?

Code: Select all

	
	.enum $0000
	addrLo .dsb 1
	addrHi .dsb 2
	.ende
	
	.org $c000

RESET:
	SEI
	CLD
	LDX #$40
	STX $4017
	LDX #$FF
	TXS
	INX
	STX $2000 
	STX $2001
	STX $4010
	
	BIT $2002
Vwait1:
	BIT $2002
clrmem:
	STA $000,x
	STA $100,x
	STA $300,x
	STA $400,x
	STA $500,x
	STA $600,x
	STA $700,x
	INX
	BNE clrmem
	
Vwait2:
	bit $2002
	BPL Vwait2
	
;;---Load Palettes
	LDA $2002
	LDA #$3F
	STA $2006
	LDA #$10
	STA $2006

	LDX #$00
LoadPaletteLoop:
	LDA PaletteData,x
	STA $2007
	INX
	CPX #$20
	BNE LoadPaletteLoop
	
	
;;---Set up PPU	
  LDA #%10000000 
  STA $2000

  LDA #%00011110   
  STA $2001	
		

;;--load a background--;

	lda #$00	;load 0
	STA $2001	;write it to $2001 to disable rendering
	lda $2002
	lda #$20
	STA $2006
	LDA #$00
	STA $2006

;; load nametable
	LDA #<myNam   ; fixed symbol
	sta addrLo
	lda #>myNam    ; fixed symbol
	sta addrHi
	
	jsr LoadBkg
	LDA $0000  ; update 
	STA $2006  ; update 
;; Load a sprite to center of screen
	LDA #$80
	STA $0200
	STA $0203
	LDA #$00
	STA $0201
	LDA #$01
	STA $0202
	

NMI:
	LDA #$00
	STA $2003
	LDA #$02
	STA $4014
	RTI


mainLoop:	

LoadBkg:
	ldx #4
	ldy #00

loadData:
	LDA #$00   ; update - writing 0 
	STA $2001  ; to $2001 
	lda (addrLo),y
	sta $2007
	iny
	bne loadData
	
	inc addrHi
	dex
	bne loadData
	
	LDA #%00011110   ; enabling rendering / background--
	STA $2001	     ; again.
	rts

  JMP mainLoop
  

PaletteData:
	;.incbin "mainPal.pal"

	.db $0F,$3C,$38,$35,  $0F,$2A,$26,$24, $0F,$1C,$18,$12, $0F,$0C,$08,$03
	.db $0F,$36,$39,$3C,  $21,$24,$29,$2C, $11,$14,$17,$1A, $02,$05,$08,$0C
	

  .org $fffa
  .dw NMI
  .dw RESET
  .dw 0

	.incbin "main.chr"
myNam:	.incbin "mainBkg.nam"



User avatar
Memblers
Site Admin
Posts: 4044
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Re: ASM6 and trouble with nametables...

Post by Memblers »

Stuff I noticed:

Palette is writing 32 bytes starting at $3F10, should write 32 bytes starting at $3F00 to set both BG and sprites.

NMI is turned on too early. With something like this I usually wait until just before turning the screen on (actually I tend to only turn the screen on inside the NMI, otherwise you might see the screen jump). Since the NMI isn't saving the register state, in this case the accumulator is getting corrupted whenever it interrupts. Also, the program flow is running right into the NMI routine instead of mainLoop. Though I can see your mainLoop is sorta mixed up with a subroutine, you'll want some kind of main loop, even if it's just an infinite JMP loop. Seems like it would crash or do something weird when it hits that RTI.

And yeah, even without scrolling you'll want to set $2005 to zero, or some known value.
User avatar
Movax12
Posts: 541
Joined: Sun Jan 02, 2011 11:50 am

Re: ASM6 and trouble with nametables...

Post by Movax12 »

If you want to have a separate NMI thread (which I like best) you need a flag to check if the other thread is is ready for the NMI logic to run. If it's not, generally the NMI thread needs to exit with all the CPU registers intact. http://wiki.nesdev.com/w/index.php/NMI_thread

Also, related to what Memblers was saying, I have a shadow variable for PPU registers, and once I turn on NMI, I normally only actually write to the PPU registers inside NMI from the shadow registers. So if the main thread wants to turn rendering on or whatever, write the new register value to the shadow location and update it in NMI and there will be no weird screen tearing.
JoeGtake2
Posts: 333
Joined: Tue Jul 01, 2014 4:02 pm

Re: ASM6 and trouble with nametables...

Post by JoeGtake2 »

Alright, the plot thickens...

I did a few more things based on your suggestions.

1. I handled the accumulator to push the values to the stack and then restore them at the end of the NMI (is this what you meant?). I think I did that right.

2. Palette issue is fixed. That's just me being an idiot...plain and simple.

3. I pushed the NMI down and made it so PPU setup is here (is this what you meant?)

4. I added a 0 write to $2005 just before re-enabling the rendering (is this the correct place?)

5. Please define shadow variable in context - I looked at the NMI thread that you posted, but am not sure how to implement it here. I'm still a little fuzzy on it, truthfully.


Now, this did not fix the problem (other than palettes...doh!), however, I found something funky. Just for kicks, I loaded the ROM file into yy-chr. The chr data started at $4000 rather than at $0000. When I load the .chr file directly, it is at $0000. My powers of deduction tell me this may be related to my problem, however I'm not sure how.

Here's an update to the entire code...

Thanks so much for your patience. I really don't think this should be this difficult, and it's probably something minor! But every piece of advice you guys give me helps tremendously.

Here's updated, still broken, code:

Code: Select all

	
	.enum $0000
	addrLo .dsb 1
	addrHi .dsb 2
	.ende
	
	.org $c000

RESET:
	SEI
	CLD
	LDX #$40
	STX $4017
	LDX #$FF
	TXS
	INX
	STX $2000 
	STX $2001
	STX $4010
	
	BIT $2002
Vwait1:
	BIT $2002
clrmem:
	STA $000,x
	STA $100,x
	STA $300,x
	STA $400,x
	STA $500,x
	STA $600,x
	STA $700,x
	INX
	BNE clrmem
	
Vwait2:
	bit $2002
	BPL Vwait2
	
;;---Load Palettes
	LDA $2002
	LDA #$3F
	STA $2006
	LDA #$00 		;;****YES, I believe this fixed the palette issue.
	STA $2006

	LDX #$00
LoadPaletteLoop:
	LDA PaletteData,x
	STA $2007
	INX
	CPX #$20
	BNE LoadPaletteLoop
	
;; Load a sprite to center of screen
	LDA #$80
	STA $0200
	STA $0203
	LDA #$04
	STA $0201
	LDA #$01
	STA $0202
;;--load a background--;

	lda #$00	;load 0
	STA $2001	;write it to $2001 to disable rendering
	lda $2002
	lda #$20
	STA $2006
	LDA #$00
	STA $2006


 ;; load nametable
	LDA #<myNam   ; fixed symbol
	sta addrLo
	lda #>myNam    ; fixed symbol
	sta addrHi
	
	jsr LoadBkg
	LDA $0000  ; update 
	STA $2006  ; update 



mainLoop:	

  JMP mainLoop

LoadBkg:
	ldx #4
	ldy #00

loadData:
	LDA #$00   ; update - writing 0 
	STA $2001  ; to $2001 
	lda (addrLo),y
	sta $2007
	iny
	bne loadData
	
	inc addrHi
	dex
	bne loadData
	LDA #$00		;**** load zero
	STA $2005       ;****write to $2005
	LDA #%00011110   ; enabling rendering / background--
	STA $2001	     ; again.

	
	rts
NMI:		;****** updated NMI to write to stack and
			;****** restore accumulators when finished
	PHA
	TXA
	PHA
	TYA
	PHA
;;---Set up PPU	
			;***** Now only being called in the NMI
	LDA #%10000000 
	STA $2000

	LDA #%00011110   
	STA $2001		

	LDA #$00
	STA $2003
	LDA #$02
	STA $4014
	
	PLA
	TAY
	PLA
	TAX
	PLA

	RTI
	
PaletteData:			;***** YES, this fixed the dumb palette
						;**** issue.  Just me being dumb.
	.incbin "charPal.pal"
	.incbin "bkgPal.pal"

  .org $fffa
  .dw NMI
  .dw RESET
  .dw 0

	.incbin "main.chr"
myNam:	.incbin "mainBkg.nam"



JRoatch
Formerly 43110
Posts: 422
Joined: Wed Feb 05, 2014 7:01 am
Contact:

Re: ASM6 and trouble with nametables...

Post by JRoatch »

I'm confused about one thing. Where/what is the iNES header? because I can't tell if it's CHR ROM or RAM. I'm guessing it's supposed to be CHR ROM because you include main.chr after the vectors, but yet you also include binary data (myNam) to be read by the cpu after that.

tokumaru's ASM6 templates shows an example of an iNES header.
JoeGtake2
Posts: 333
Joined: Tue Jul 01, 2014 4:02 pm

Re: ASM6 and trouble with nametables...

Post by JoeGtake2 »

My mistake for not including that. Yes, from Tokumaru's template, I actually have a 'header.asm' file which has this header, and then its body includes this file. This has been working for the other things I've been messing around with fine (setting up a meta-sprite character, making character move, keeping him within the boundaries of the screen). But this is stumping me.

**EDIT** On that note, placing the .incbin for the nametable just after the .incbin for palette data (rather than at the end with the chr data) helped marginally - now I DO have a background drawn, however there are two things wrong - it is certainly showing the wrong tiles (though they are in the right arrangement), and also the whole nametable is offset by a noticeable amount of pixels (I didn't count...maybe -64 both vertically and horizontally). So that's progress at least!

Any thoughts?
User avatar
Movax12
Posts: 541
Joined: Sun Jan 02, 2011 11:50 am

Re: ASM6 and trouble with nametables...

Post by Movax12 »

Step through your code with a debugging emulator and breakpoints, etc. That is often the best way to see where things are going wrong. A "shadow register" is just a memory location/variable to hold what you want to write at a later time .. like in NMI.
JRoatch
Formerly 43110
Posts: 422
Joined: Wed Feb 05, 2014 7:01 am
Contact:

Re: ASM6 and trouble with nametables...

Post by JRoatch »

You missed a BPL for Vwait1, and Keep in mind that $2005 and $2006 are double write registers. In LoadBkg you write to $2005 only once, and after the jsr LoadBkg, that might have interfered with the single write to $2006 with the contents of addrLo.

Also writing 0 to PPU_MASK every byte sent to PPU_DATA?
Last edited by JRoatch on Mon Jul 07, 2014 7:52 pm, edited 1 time in total.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: ASM6 and trouble with nametables...

Post by tokumaru »

JoeGtake2 wrote:it is certainly showing the wrong tiles (though they are in the right arrangement)
When you set $2000 you're telling the PPU to fetch tiles from $0000 (i.e.) the first pattern table, for both sprite and background. Could the background tiles be at $1000 instead?
and also the whole nametable is offset by a noticeable amount of pixels (I didn't count...maybe -64 both vertically and horizontally).
A common cause for this is not resetting the scroll after using $2006/$2007 to write to the PPU. I'm not seeing you reset the scroll anywhere... You do have this weird piece of code, which is probably not doing what you expect it to:

Code: Select all

   LDA $0000  ; update 
   STA $2006  ; update
This will load a byte from $0000 (i.e. the first byte of RAM) and write it to $2006. A single write doesn't set the PPU address, and I doubt that's the value you wanted to write. You probably meant to do this:

Code: Select all

lda #$00
sta $2006
sta $2006
Which is one way to reset the scroll (the wrong way, because it doesn't fully reset the scroll). the correct way is to select the name table through $2000 and then writing #$00 to $2005 twice, to clear both horizontal and vertical scroll.
User avatar
Memblers
Site Admin
Posts: 4044
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Re: ASM6 and trouble with nametables...

Post by Memblers »

I think the screen offset is caused by the LDA $0000 / STA $2006, that's actually reading from RAM, your addrLo variable, in fact. So you'll want to do LDA #0 / STA $2006 / STA $2006, and the same for $2005.

By the "shadow registers", we mean making a variable (I call them v2000 and v2001), so in your NMI routine you would do LDA v2001 / STA $2001, and would only write to v2001 in the main thread of the program. The exception of course is when enabling NMI from the main thread, for that I do one of these (in case v2000 already has some other settings): LDA v2000 / ORA #%10000000 / STA v2000 / STA $2000. In your current program, I think the NMI will never happen because it's only getting enabled from within the NMI.
JoeGtake2
Posts: 333
Joined: Tue Jul 01, 2014 4:02 pm

Re: ASM6 and trouble with nametables...

Post by JoeGtake2 »

You guys are awesome. Seriously. I fully realize I'm asking some newbish questions, and not a single troll or impatient response yet. What a wonderful part of the interwebs this is!

Tokumaru - you nailed it on the clearing the scrolling. That fixed the issue 100% as far as that weird offset I was getting. Now everything is lined up, but is still showing the same issue with the tiles. I believe that you are absolutely right - I'm looking for background sprites at $1000 and it is pulling from $0000. Wouldn't the method to do this be in the PPU - in the load to $2000?

Code: Select all

LDA #%00010000
STA $2000
I've tried this...also tried reversing this. Both seemed to do nothing.

I've even tried moving the PPU setup around in case the NMI was never being accessed (Memblers, I was a step ahead of you on that thought), but that didn't seem to do anything either.

Is there a concept I'm missing to access from $1000 rather than $0000, or am I right in the concept and something else is getting in the way negating that?



Memblers - I think I get what you are saying. I'm going to try it out and hopefully you won't mind checking my work haha.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: ASM6 and trouble with nametables...

Post by thefox »

43110 wrote:I'm guessing it's supposed to be CHR ROM because you include main.chr after the vectors, but yet you also include binary data (myNam) to be read by the cpu after that.
^ THAT is your problem (one of them). You need to put the nametable in the PRG-ROM part of the ROM (before the vectors), not in CHR-ROM.

EDIT: Oops, I missed the fact that you already mentioned fixing this this in an earlier post.
Last edited by thefox on Mon Jul 07, 2014 8:51 pm, edited 1 time in total.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
Post Reply