Accessing data or "strings" in data segment
Moderator: Moderators
Accessing data or "strings" in data segment
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?
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?
Re: Accessing data or "strings" in data segment
Yes, use a label.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?
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.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?
It depends on the assembler. If you use ca65, you can use .charmap to define how characters should be translated.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?
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
Re: Accessing data or "strings" in data segment
In ASM6 you can "shift" the character codes from their normal ASCII codes like this:
This string will appear in the ROM as $00, $01, $02, $03, $04, $05.
Code: Select all
.db "ABCDEF"-65Re: Accessing data or "strings" in data segment
Alright. Thanks!
One more question - is there a convention for label names, like, which labels should begin with @ and so on?
One more question - is there a convention for label names, like, which labels should begin with @ and so on?
Re: Accessing data or "strings" in data segment
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.Dafydd wrote:One more question - is there a convention for label names, like, which labels should begin with @ and so on?
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
Re: Accessing data or "strings" in data segment
Good thing I asked, then, hehe. Thanks for the pointer.
Re: Accessing data or "strings" in data segment
Super Mario Bros. sets up string data as such:
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:
And you could add a macro to encode it for you with x, y coords of the string's destination.
Macro:
Code: Select all
TopStatusBarLine: .byte $20, $43, $05, $16, $0a, $1b, $12, $18 ; "MARIO"
If you adjust the character mapping it becomes:
Code: Select all
TopStatusBarLine: .byte $20, $43, $05, "MARIO"
Code: Select all
vram_string 3, 2, "MARIO"
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.
Re: Accessing data or "strings" in data segment
Very nice.
For now, I tried this:
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?
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 @printstringRe: Accessing data or "strings" in data segment
"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:
That's why I usually put the font at tiles $20-$5F.
Code: Select all
WHAT DOES THE SCOUTER SAY
ABOUT HIS POWER LEVEL?
IT'S OVER 9
Re: Accessing data or "strings" in data segment
I thought bne compared A to 0, not whichever register you last modified. Which is it?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.
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.
Re: Accessing data or "strings" in data segment
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.Dafydd wrote:I thought bne compared A to 0, not whichever register you last modified. Which is it?
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:
Re: Accessing data or "strings" in data segment
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.Dafydd wrote:I thought bne compared A to 0
CMP changes the Z flag. So does CPX, CPY, LDA, LDX, LDY, ADC, SBC... the list goes on.not whichever register you last modified. Which is it?
Re: Accessing data or "strings" in data segment
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?
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?
Re: Accessing data or "strings" in data segment
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.
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.
Re: Accessing data or "strings" in data segment
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
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.
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