It is currently Sat Nov 18, 2017 8:21 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 12 posts ] 
Author Message
PostPosted: Tue Aug 01, 2017 4:55 pm 
Offline
User avatar

Joined: Thu Aug 13, 2015 4:40 pm
Posts: 113
Location: Rio de Janeiro - Brazil
Sorry for the newbie question, I've been searching for practical examples on this but so far not much luck...

So, when developing a nes game with the cc65 compiler and using Nes Screen Tool, if I include a full screen nametable (the whole screen tiles) binary like so:

Code:
nametable:
.incbin "level_01_bg.nam"


Is it possible to read all of its bytes to send data to the PPU if the included file is longer than $FF bytes? I can only access its first 256 bytes by using "LDA nametable,x", but the rest I have no idea how to access.

I got it to work (the full nametable loaded and displayed) by copy/paste the nametable as asm code from Nes Screen Tool and then setting labels dividing it in 4 areas, but workflow would be streamlined if I could export a file from Nes Screen Tool and compile the game as is, especially because of the nametable splitting and having to rename ".db" to ".byte" (is there a way to make NSS more cc65 compatible?).

minor edit: more descriptive title

_________________
http://nesrocks.com/blog/superpitfall30th/


Last edited by nesrocks on Wed Aug 02, 2017 12:49 pm, edited 4 times in total.

Top
 Profile  
 
PostPosted: Tue Aug 01, 2017 5:09 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19226
Location: NE Indiana, USA (NTSC)
Do you know what a pointer is?

You'll need to make a pointer in two bytes of zero page and use the (dd),Y addressing mode to step through all four 256-byte pages of nametable data.

EDIT: spelling


Top
 Profile  
 
PostPosted: Tue Aug 01, 2017 5:15 pm 
Offline
User avatar

Joined: Sun May 27, 2012 8:43 pm
Posts: 1311
You can use the Indirect Indexed mode, with Y, to load from a large table.
Assuming a ZP two-byte variable "addr_ptr":

Code:

; Put nametable source address in addr_ptr
lda #<nametable
sta addr_ptr
lda #>nametable
sta addr_ptr+1

; Copy one page of data ($100 bytes)
@copypage:
ldy #0
@copyloop:
lda (addr_ptr), y
sta PPUDATA
iny
bne @copyloop

; Move on to the next page, or leave if finished
lda nametable+1
clc
adc #1
sta nametable+1
cmp #(>nametable + 4)
bne @copypage


This code is really rough, so please forgive minor errors. The jist of it is a copy loop using Y from $00-$FF, and then incrementing the high byte of your pointer after that and doing it again until you are done. In this case, it is four iterations to cover a whole nametable.

This code assumes you have already loaded PPUDATA.


Top
 Profile  
 
PostPosted: Tue Aug 01, 2017 5:21 pm 
Offline
User avatar

Joined: Thu Aug 13, 2015 4:40 pm
Posts: 113
Location: Rio de Janeiro - Brazil
tepples wrote:
Do you know what a pointer is?

So you mean I can use that to retrieve the label's address at runtime and find the rest of the data relative to its position? I'll look further into zero page pointers and see if that's the case, thanks.

Pre-posting edit: It seems that's the case (sans my probably imprecise way of describing it), thanks mikejmoffitt!

edit: it works! The only typo in your code is that instead of reading and writing to/from "addr_ptr+1" you wrote "nametable+1" but that was an easy fix. Thanks! I'll study those operators (<, >, +1 etc), I kind of see what they do but I had never seen them.

Updated code for posterity:
Code:
; Put nametable source address in addr_ptr
lda #<nametable
sta addr_ptr
lda #>nametable
sta addr_ptr+1

; Copy one page of data ($100 bytes)
@copypage:
ldy #0
@copyloop:
lda (addr_ptr), y
sta PPUDATA
iny
bne @copyloop

; Move on to the next page, or leave if finished
lda addr_ptr+1
clc
adc #1
sta addr_ptr+1
cmp #(>nametable + 4)
bne @copypage

_________________
http://nesrocks.com/blog/superpitfall30th/


Top
 Profile  
 
PostPosted: Wed Aug 02, 2017 9:17 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
nesrocks wrote:
Code:
nametable:
.incbin "level_01_bg.nam"

Indirect addressing with (dd),y is the way to go (smaller code size, not that much slower), but I'll just note that you could've also done this to avoid splitting the data manually to 4 parts:
Code:
nametable_part0:
nametable_part1 := nametable_part0+$100
nametable_part2 := nametable_part1+$100
nametable_part3 := nametable_part2+$100
.incbin "level_01_bg.nam"

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Wed Aug 02, 2017 10:03 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10112
Location: Rio de Janeiro - Brazil
thefox wrote:
Code:
nametable_part0:
nametable_part1 := nametable_part0+$100
nametable_part2 := nametable_part1+$100
nametable_part3 := nametable_part2+$100
.incbin "level_01_bg.nam"

I sometimes need to do this (usually to label the individual arrays/fields of structures of arrays), so I created a ca65 macro for this (IIRC, you need to supply the names of all the labels and the macro calculates how far apart they are based on the length of the data and the number of labels - so it won't work if the arrays aren't all the same length). I can post it if anyone is interested, I just don't have it with me right now.

For something constant-sized like a name table I probably wouldn't bother creating separate labels though, I'd just adjust the base address directly in the 4 loops that copy the data:

Code:
lda nametable+$000, x
;(...)
lda nametable+$100, x
;(...)
lda nametable+$200, x
;(...)
lda nametable+$300, x


Top
 Profile  
 
PostPosted: Wed Aug 02, 2017 11:57 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
For completeness, here's one more option (ca65 syntax):
Code:
nametable_part0:
.incbin "level_01_bg.nam", 0*256, 256
nametable_part1:
.incbin "level_01_bg.nam", 1*256, 256
nametable_part2:
.incbin "level_01_bg.nam", 2*256, 256
nametable_part3:
.incbin "level_01_bg.nam", 3*256, 256

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Wed Aug 02, 2017 12:00 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5822
Location: Canada
!!! How did I not know that ca65 has way to trim an .incbin like that???
Thanks for making me aware of this.


Top
 Profile  
 
PostPosted: Wed Aug 02, 2017 12:09 pm 
Offline
User avatar

Joined: Sun May 27, 2012 8:43 pm
Posts: 1311
nesrocks wrote:
tepples wrote:
Do you know what a pointer is?

So you mean I can use that to retrieve the label's address at runtime and find the rest of the data relative to its position? I'll look further into zero page pointers and see if that's the case, thanks.

Pre-posting edit: It seems that's the case (sans my probably imprecise way of describing it), thanks mikejmoffitt!

edit: it works! The only typo in your code is that instead of reading and writing to/from "addr_ptr+1" you wrote "nametable+1" but that was an easy fix. Thanks! I'll study those operators (<, >, +1 etc), I kind of see what they do but I had never seen them.


Glad it mostly worked! The < and > operators retrieve the low and high addresses of the provided symbol, respectively. <nametable gets the lower byte, and >nametable gets the higher byte of nametable. Putting those into a pointer in order gets you a pointer to the nametable.

addr_ptr+1 simply means "the high byte of addr_ptr", which is one byte after the symbol. That's because addr_ptr uses two bytes to represent a memory address. We're checking the high byte (in this little-endian system) because it effectively indexes the page, which we've already iterated through.

rainwarrior wrote:
!!! How did I not know that ca65 has way to trim an .incbin like that???
Thanks for making me aware of this.

Agreed, that's fantastic. This makes a yy-chr palette file directly usable as well.


Top
 Profile  
 
PostPosted: Wed Aug 02, 2017 12:12 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10112
Location: Rio de Janeiro - Brazil
rainwarrior wrote:
!!! How did I not know that ca65 has way to trim an .incbin like that???

I didn't know either! That may come in handy sometime!


Top
 Profile  
 
PostPosted: Wed Aug 02, 2017 12:38 pm 
Offline
Formerly WheelInventor

Joined: Thu Apr 14, 2016 2:55 am
Posts: 1012
Location: Gothenburg, Sweden
Incbin management like this is super useful for a beginner like me, too. Tip of the month at the very least!

_________________
http://www.frankengraphics.com - personal NES blog


Top
 Profile  
 
PostPosted: Wed Aug 02, 2017 3:19 pm 
Offline
User avatar

Joined: Thu Aug 13, 2015 4:40 pm
Posts: 113
Location: Rio de Janeiro - Brazil
Amazing stuff that this information could be spread! And here I was wondering if writing "+1" was correct... :lol: Now I know a decimal number doesn't need a preceding character. Coming from a hacking background where I mostly worked with hex numbers typing byte code directly into the hex it looked weird to see in asm code.

And yeah, being able to .incbin only a section of a file seems very powerful for the workflow, one could include parts of other ROMs without splitting it into different files or clogging your own ROM with useless bytes. The uses are endless.

_________________
http://nesrocks.com/blog/superpitfall30th/


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group