Accessing data or "strings" in data segment

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

User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Accessing data or "strings" in data segment

Post by Dafydd »

I want to make a routine that reads data from a "string" or "array" in the data segment and prints text on the screen (very advanced stuff, I know).

I think I can do

.segment "DATA"
.word $11, $0E, $15, $15, $18

where the numbers are the tile indexes for "hello", set $2006 to $21CD or something and then load these values into a register and store them in $2007 one after the other. But

1. How do I access the string? I don't know the address. Do I just put a label up like @hellostring: .word $11, $0E etc, or what?
2. Is there an elegant way of making the routine return after it has printed the string without knowing its length beforehand? I was thinking of ending the string with a zero or $FF or something (kind of like in C) and then return upon detecting 0 (or whichever value represents the end of a string). Is there a better way?
3. I've seen code examples where people write .word "Hello", but no explanation as to how these letters are translated into tile indexes. The compiler doesn't know where in my tileset my characters are located by itself. Is there a way I could tell it? Or do people use their own scripts to replace strings with sequences of hex numbers before compiling?
User avatar
thefox
Posts: 3139
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: Accessing data or "strings" in data segment

Post by thefox »

Dafydd wrote:1. How do I access the string? I don't know the address. Do I just put a label up like @hellostring: .word $11, $0E etc, or what?
Yes, use a label.
2. Is there an elegant way of making the routine return after it has printed the string without knowing its length beforehand? I was thinking of ending the string with a zero or $FF or something (kind of like in C) and then return upon detecting 0 (or whichever value represents the end of a string). Is there a better way?
You have to store the length one way or another. You can use a terminator character like you said, or store the string length in the beginning of the string, or some other method.
3. I've seen code examples where people write .word "Hello", but no explanation as to how these letters are translated into tile indexes. The compiler doesn't know where in my tileset my characters are located by itself. Is there a way I could tell it? Or do people use their own scripts to replace strings with sequences of hex numbers before compiling?
It depends on the assembler. If you use ca65, you can use .charmap to define how characters should be translated.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Accessing data or "strings" in data segment

Post by tokumaru »

In ASM6 you can "shift" the character codes from their normal ASCII codes like this:

Code: Select all

.db "ABCDEF"-65
This string will appear in the ROM as $00, $01, $02, $03, $04, $05.
User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Re: Accessing data or "strings" in data segment

Post by Dafydd »

Alright. Thanks!

One more question - is there a convention for label names, like, which labels should begin with @ and so on?
User avatar
thefox
Posts: 3139
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: Accessing data or "strings" in data segment

Post by thefox »

Dafydd wrote:One more question - is there a convention for label names, like, which labels should begin with @ and so on?
It's not just a convention, in ca65 (and many other assemblers) labels beginning with @ are treated differently from other labels. Google "cheap local labels ca65" for an explanation.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Re: Accessing data or "strings" in data segment

Post by Dafydd »

Good thing I asked, then, hehe. Thanks for the pointer.
User avatar
Movax12
Posts: 529
Joined: Sun Jan 02, 2011 11:50 am

Re: Accessing data or "strings" in data segment

Post by Movax12 »

Super Mario Bros. sets up string data as such:

Code: Select all

TopStatusBarLine: .byte $20, $43, $05, $16, $0a, $1b, $12, $18 ; "MARIO"
This includes the high and low nametable address, followed by the string length and then the string itself (tile numbers).

If you adjust the character mapping it becomes:

Code: Select all

TopStatusBarLine: .byte $20, $43, $05, "MARIO"
And you could add a macro to encode it for you with x, y coords of the string's destination.

Code: Select all

vram_string 3, 2, "MARIO"
Macro:

Code: Select all

.macro vram_string xpos, ypos, str
    .byte >($2000 + (ypos * $20 + xpos)), <($2000 + (ypos * $20 + xpos)), .strlen(str), str
.endmacro
Last edited by Movax12 on Sun Feb 24, 2013 8:52 pm, edited 1 time in total.
User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Re: Accessing data or "strings" in data segment

Post by Dafydd »

Very nice.

For now, I tried this:

Code: Select all

.segment "DATA"
mystring: .byte $11, $0E, $15, $15, $18, 0

.segment "CODE"

...

	lda $2002
	lda #$21
	sta $2006
	lda #$AC
	sta $2006
	ldx #$00
	
@printstring:
	lda mystring,x
	sta $2007
	inx
	bne @printstring
But instead of getting the tiles listed in mystring I get other tiles (not sure which one, my tileset is mostly blank, but 256 in a row before the loop quits). What am I doing wrong? How do I properly load stuff from mystring into the accumulator?
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Accessing data or "strings" in data segment

Post by tepples »

"inx bne" will increase X until it hits 256 and wraps to 0. You need to compare the byte to the terminator after the LDA. And if you're using digits 0-9 in tiles $00-$09, using 0 as your terminator means you can't have a 0 in your text:

Code: Select all

WHAT DOES THE SCOUTER SAY
ABOUT HIS POWER LEVEL?

IT'S OVER 9
That's why I usually put the font at tiles $20-$5F.
User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Re: Accessing data or "strings" in data segment

Post by Dafydd »

tepples wrote:"inx bne" will increase X until it hits 256 and wraps to 0. You need to compare the byte to the terminator after the LDA.
I thought bne compared A to 0, not whichever register you last modified. Which is it?
EDIT: I just read up on the Z flag. Didn't know that thing even existed. This will certainly make things easier...

I don't intend to keep using 0 as my terminator, btw, but it was easier to test this way.
Last edited by Dafydd on Sat Feb 23, 2013 7:29 pm, edited 1 time in total.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Accessing data or "strings" in data segment

Post by tepples »

Dafydd wrote:I thought bne compared A to 0, not whichever register you last modified. Which is it?
BNE branches if the Z flag is off. Pretty much any instruction that calculates a value (almost anything other than a store or jump) will update the N and Z flags. Bit 7 goes into N (the minus flag) and the NOR of all bits goes into Z (the equal flag). This means if the calculated value is 0, the Z flag turns on; otherwise, it turns off. The INX instruction calculates X := X + 1 and updates N/Z based on the result.

Try this, which will use any value with bit 7 turned on (that is, $80-$FF) as your terminator:

Code: Select all

@printstring:
   lda mystring,x
   bmi @printdone
   sta $2007
   inx
   bne @printstring
@printdone:
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Accessing data or "strings" in data segment

Post by tokumaru »

Dafydd wrote:I thought bne compared A to 0
BNE doesn't compare anything, it just branches (or doesn't) based on the status of the Z flag. CMP is one of the instructions that affects the Z flag, but many, many other instructions do too.
not whichever register you last modified. Which is it?
CMP changes the Z flag. So does CPX, CPY, LDA, LDX, LDY, ADC, SBC... the list goes on.
User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Re: Accessing data or "strings" in data segment

Post by Dafydd »

Haha, you beat me to it. As edited above, I just found out about the Z flag - I'll read up on it and the other flags as well (the opcode ref chart I was using wasn't as informative as it should have been). Thanks for the help.

It'd be pretty cool to have an editor where you have a status window or something that briefs you on the opcode your cursor is currently at. Maybe one already exists?
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: Accessing data or "strings" in data segment

Post by Kasumi »

Here is a guide that lets you click an opcode to get quick info on it.

The 6502 Macroassembler is a tool that will give you information about an opcode as you type it. It will also let you write and run programs step by step and let you see how the flags are affects.
User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Re: Accessing data or "strings" in data segment

Post by Dafydd »

Cool! The simulator does exactly what I was asking for.

I tried tepples' code, changing the terminator in my string to $FF, but I would keep getting 256 of that wrong tile. I then changed the routine into

Code: Select all

@printstring:
   lda mystring,x
   bmi @printdone
   lda #$0E
   sta $2007
   inx
   bne @printstring
which would print 256 of the tile $0E as expected. It seems I'm still not reading values from mystring into A properly, or I would only have printed out 5 of $0E before branching into @printdone.
Post Reply