It is currently Wed Sep 19, 2018 4:38 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Tue Sep 04, 2018 8:59 pm 
Offline

Joined: Tue Aug 28, 2018 8:54 am
Posts: 18
Location: Edmonton, Canada
I am sorry, as it is probably going to be duplicate question, but I tried forum and google search on the forum and did not find an answer (possibly by using wrong keywords)

So I have my nametable generated from "nesst".

Code:
TitleScreen:
  .incbin "title.nam"


And I have this following code. Obviously X register will end after the quarter of the nametable.

Code:
    lda PPU_STATUS
    lda #>PPU_ADDR_NAMETABLE1 ;define for $2000
    sta PPU_ADDR
    lda #<PPU_ADDR_NAMETABLE1
    sta PPU_ADDR
    ldx #$00
    :
        lda TitleScreen,x
        sta PPU_DATA
        inx
        ; magic goes here
        cpx $FF ; end of my X register
        bne :-


I can solve it by splitting my "nam" file into 4 chunks and loading them separately. Can it be done any other way?

My thought process:
Absolute addressing - limits to 255.
Indirect addressing only manipulates zero page.
There is no LDA X,Y addressing like AVR microcontroller has

Code:
ldi ZH, high(Table_1) ; Initialize Z pointer
ldi ZL, low(Table_1)
lpm r16, Z ; Load constant from program


Top
 Profile  
 
PostPosted: Tue Sep 04, 2018 9:16 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6801
Location: Canada
You can use a two byte address on the zeropage ($00-$FF) to access memory by that address.

The indirect indexed addressing mode works for LDA and STA.

LDA ($00), Y < This instruction loads a byte from the address stored at: ($01 << 8) + $00 + Y

Code:
ptr = $00 ; zero page pointer at $00, $01

lda #<nametable_data
sta ptr+0
lda #>nametable_data
sta ptr+1
ldx #4 ; do this loop 4 times
ldy #0
:
   lda (ptr), Y
   sta $2007
   iny
   bne :-
   dex
   beq :+ ; finished if X = 0
   inc ptr+1 ; ptr = ptr + 256
   jmp :- ; loop again: Y = 0, X -= 1, ptr += 256
:


Top
 Profile  
 
PostPosted: Tue Sep 04, 2018 9:19 pm 
Offline

Joined: Tue Aug 28, 2018 8:54 am
Posts: 18
Location: Edmonton, Canada
rainwarrior wrote:
You can use a two byte address on the zeropage ($00-$FF) to access memory by that address.

The indirect indexed addressing mode works for LDA and STA.

LDA ($00), Y < This instruction loads a byte from the address stored at: ($01 << 8) + $00 + Y


Oh damn, that was stupid of me. Thank you very much.


Top
 Profile  
 
PostPosted: Wed Sep 05, 2018 1:43 am 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1243
It's definitely good to know how to do this on one's own with indirect indexed (as described by rainwarrior), but I figure I should add NES Screen Tool actually just includes code to load a full (compressed) nametable.

In NES Screen Tool: Nametable, Save Nametable and Attributes, select RLE packed binary from the dropdown menu.
Include "rle.asm" in your project, write the address of where the data should start in the PPU to $2006 then jsr to unrle with the address of the data itself in X and Y.

Be aware that the file is in NESASM syntax. To change this, change lda [RLE_LOW],y to lda (RLE_LOW),y. You may also need to update the labels for your assembler, and you may also want to relocate which RAM it uses at the top. You may also need to change references to PPU_DATA to $2007 if you are not using that standard.
I'm told this only works if you are using < 256 unique tiles in the nametable, but haven't verified this.

_________________
https://kasumi.itch.io/indivisible


Top
 Profile  
 
PostPosted: Wed Sep 05, 2018 7:54 am 
Offline

Joined: Tue Aug 28, 2018 8:54 am
Posts: 18
Location: Edmonton, Canada
Kasumi wrote:
It's definitely good to know how to do this on one's own with indirect indexed (as described by rainwarrior), but I figure I should add NES Screen Tool actually just includes code to load a full (compressed) nametable.

In NES Screen Tool: Nametable, Save Nametable and Attributes, select RLE packed binary from the dropdown menu.
Include "rle.asm" in your project, write the address of where the data should start in the PPU to $2006 then jsr to unrle with the address of the data itself in X and Y.


I've seen that, what I'm doing right now is just hello world screen.

I glanced at the unpacker code, but my brain did not switch to assembler yet. I understand how individual instructions work (except my fail with indirect indexed addressing), and can port it, but can not grasp it. I though I might as well take a look at the source of compressor, and write decompressor myself, as a practice.

Kasumi wrote:
You may also need to change references to PPU_DATA to $2007 if you are not using that standard.


This always bothered me reading code on the forum and other nes homebrews. There should be a reason which I don't know, and I am coming from being developer for work, and notion that your code should be readable. Why would you ever do

Code:
    lda #$80
    sta $2000


Instead of

Code:
    lda #(PPU_CTRL_NMI_ON | PPU_CTRL_BG_ADDR_0 | PPU_CTRL_SPR_ADDR_1)
    sta PPU_CTRL


Top
 Profile  
 
PostPosted: Wed Sep 05, 2018 8:44 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20556
Location: NE Indiana, USA (NTSC)
Probably because not everyone uses exactly the same names for things, particularly for the bit constants that get stored in the register. It's not like Game Boy where the official register names leaked fairly early on and essentially the entire homebrew community started using the same header file.


Top
 Profile  
 
PostPosted: Wed Sep 05, 2018 8:48 am 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1243
Ah, but the wiki calls it PPUCTRL without the underscore! There's not really a standard. I've always wondered about the source of the names, myself. Early homebrew developer decided to name them, or do they come from official Nintendo stuff? Either way, if I give you sta $2007 instead of those names, it will assemble in anything regardless of how the assembler deals with defines/equs/.dsbs.

I know I can branch on minus after this:
Code:
    lda #$80
    sta $2000

and I don't after this:
Code:
    lda #(PPU_CTRL_NMI_ON | PPU_CTRL_BG_ADDR_0 | PPU_CTRL_SPR_ADDR_1)
    sta PPU_CTRL

Not to say that you shouldn't use PPUDATA/PPU_DATA if you're comfortable with them, but those are some reasons why people don't. Yes, I realize in the above you could comment either with the info the other doesn't have.

I don't use them because not using them is what I'm used to. The two that I have to look up ($2000/$2001), I'd have to look up if they were named too.

(Another case of ninja'd but posting anyway.)

_________________
https://kasumi.itch.io/indivisible


Top
 Profile  
 
PostPosted: Wed Sep 05, 2018 8:53 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20556
Location: NE Indiana, USA (NTSC)
I have a confession to make: I think I was the one who came up with the "PPUCTRL" set of names for PPU registers $2000-$2007 that the community has since more-or-less adopted. But that was back in the 2000s decade. Because I didn't put serious work into an audio driver until 2009, I didn't get a chance to make analogous names for the audio regs that caught on.


Top
 Profile  
 
PostPosted: Wed Sep 05, 2018 10:12 am 
Offline

Joined: Tue Aug 28, 2018 8:54 am
Posts: 18
Location: Edmonton, Canada
tepples wrote:
Probably because not everyone uses exactly the same names for things, particularly for the bit constants that get stored in the register. It's not like Game Boy where the official register names leaked fairly early on and essentially the entire homebrew community started using the same header file.


It is true, and I understand the lack of official naming cases issues. My concern is more about using magic numbers in general.

Kasumi wrote:
Ah, but the wiki calls it PPUCTRL without the underscore! There's not really a standard. I've always wondered about the source of the names, myself. Early homebrew developer decided to name them, or do they come from official Nintendo stuff? Either way, if I give you sta $2007 instead of those names, it will assemble in anything regardless of how the assembler deals with defines/equs/.dsbs.


Yes (PPU_CTRL is from nes.inc from cc65, PPU_CTRL bit names are mine. I tried to name them to be more or less understandable). But as I said above, I'm talking more about magic numbers than actual names.

Kasumi wrote:
(Another case of ninja'd but posting anyway.)


Not sure I'm following =)


Top
 Profile  
 
PostPosted: Wed Sep 05, 2018 10:48 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20556
Location: NE Indiana, USA (NTSC)
If you got "ninja'd", that means someone else submitted a reply to a topic while you were composing your reply.


Top
 Profile  
 
PostPosted: Wed Sep 05, 2018 11:28 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6801
Location: Canada
I've always preferred "$2007" to "PPU_DATA", and I find the latter to be obfuscating rather than the former, but opinions differ. I would say that the NES only has 8 PPU registers. So relative to other systems, the numbers are less difficult to keep in memory.

tepples wrote:
I didn't get a chance to make analogous names for the audio regs that caught on.
The PPU registers at least mostly have a single function per register. This is not really true for half the audio registers. Naming them effectively is not so easy a problem.

I think it was feos_tas that added these names to FCEUX. I disabled them immediately.

The other thing about the audio registers is most programs hardly ever write an audio register in more than one place in the code. There's a lot less need to have a name for a thing that appears exactly once.

Code:
(PPU_CTRL_NMI_ON | PPU_CTRL_BG_ADDR_0 | PPU_CTRL_SPR_ADDR_1)

vs.

$80
TBH, I find the former obfuscating in its verbosity. $80 as a hex number is very easily remembered as a byte with only the high bit set, and I do easily remember that the high bit of $2000 controls the NMI, as from using that register I find it's the most important bit.

The rest of the bits of $2000 I don't remember. I look them up when I need to use them, and it's really not any kind of problem to do so. I have to interact with them so few times in the code that I see no reason to build verbose constants to help me construct these bitfields. BTW, I very often like to use binary notation like %10000000 instead of $80 for things that are bitfields, but depends on the situation.

Actually, the most likely thing I'd do would probably be to annotate it with a comment, rather than creating bitfield constants:
Code:
%10001010 ; NMI on, nametable $2800
I do, on the other hand have bitfield construction constants for controller reading stuff. PAD_L, PAD_A, PAD_SELECT. Those I find quite useful, as controller bitfield parsing tends to have many cases in a typical program, each with very specialized needs. Very different situation than with $2000 which gets used maybe 3 places in the code. Also, the order of controller bits as left to right or right to left is arbitrary, depending on how you stored the bits as they were read; there's much more need to use defined constants when something is arbitrary or could change. $2000 on the other hand is always $2000.

$2006 and $2007 get used in a lot of places in the code, but for the same reason they're very memorable. Both of them also have very simple function, no bit packing, just a whole byte with one purpose.

$2004 doesn't need a name because you're not going to use it anyway. ;P

Et cetera.


Anyhow, you should use the style that feels effective to you. Lots of people like the defined names for these registers, and they seem to be included by default by Mesen and FCEUX at this point. Some people, like me, feel the opposite. I don't think it's a no brainer that this is the better way to go.


Top
 Profile  
 
PostPosted: Wed Sep 05, 2018 11:35 am 
Offline

Joined: Tue Aug 28, 2018 8:54 am
Posts: 18
Location: Edmonton, Canada
rainwarrior wrote:
Anyhow, you should use the style that feels effective to you. Lots of people like the defined names for these registers, and they seem to be included by default by Mesen and FCEUX at this point. Some people, like me, feel the opposite. I don't think it's a no brainer that this is the better way to go.


Thank you for the explaining the reasoning. Anyhow I was just wondering, not implying that everyone should redefine registers :)

As of me, I just feel safer to type PPU_ADDR instead of $2006, as it is much easier to mistype to $2005 or $2007, but I understand that after working a lot on the code, you will probably immediately notice that.


Top
 Profile  
 
PostPosted: Tue Sep 11, 2018 1:23 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 28
Location: Colorado
Kasumi wrote:
In NES Screen Tool: Nametable, Save Nametable and Attributes, select RLE packed binary from the dropdown menu.
Include "rle.asm" in your project, write the address of where the data should start in the PPU to $2006 then jsr to unrle with the address of the data itself in X and Y.



I just tried this and it doesn't seem to work for me. It doesn't actually create the file I choose. I added an empty dummy file to see if it's content changed and for some reason it just doesn't seem to save.

Any idea what I'm doing wrong?

Thanks

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
PostPosted: Tue Sep 11, 2018 1:28 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3589
Location: Mountain View, CA
Also, for NES Screen Tool / nesst.zip:

The rle.asm file in the .zip may need to be adjusted for whatever assembler you're using. It appears to have been written for NESASM 2.x or 3.x (it often matters, and the source doesn't specify which version). But the code is very short and fairly easy to understand. If/when converting it to the assembler you use, be aware that NESASM uses brackets to specify indirect addressing (ex. lda [RLE_LOW],y), rather than the more common parenthesis (ex. lda (RLE_LOW),y). This has caused many problems for people in the past.

If the export-to-file feature doesn't work, you can alternately try using "Put to the clipboard -> ASM data" to put a ton of .db statements into the clipboard, which you can paste directly into your source code (if you wish to do it that way). There is no point in discussing which method is better or worse; use whatever you prefer, or whatever works. I'll note that I've never used this tool before, I'm going completely off of the readme.


Top
 Profile  
 
PostPosted: Tue Sep 11, 2018 1:31 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 28
Location: Colorado
koitsu wrote:
If the export-to-file feature doesn't work, you can alternately try using "Put to the clipboard -> ASM data" to put a ton of .db statements into the clipboard, which you can paste directly into your source code (if you wish to do it that way). There is no point in discussing which method is better or worse; use whatever you prefer, or whatever works. I'll note that I've never used this tool before, I'm going completely off of the readme.


The only issue I have with that is it doesn't seem to do the RLE thing. It looks like all the data is uncompressed.


Another related question. What segment should I drop the nametable into?

Thanks for your help

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 1 guest


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