[TI-ASM] Level Data

Got questions? Got answers? Go here for both.

Moderator: MaxCoderz Staff

Post Reply
User avatar
nepmarauder
Regular Member
Posts: 119
Joined: Thu 14 Apr, 2005 7:02 pm
Location: Ann Arbor, MI
Contact:

[TI-ASM] Level Data

Post by nepmarauder »

I'm looking to start on a simple, Mini-Putt clone, and I need a way of storing/retrieving variable data that corresponds to sprites. Here is a short, pseudo code idea:

Code: Select all

LevelList = {1,2,3}

get first value from LevelList
if the first value == 1
display sprite one at (0,0)
if the first value == 2
display sprite two at (0,0)

etc.
The code to store levels in arrays seems pretty tedious and large. I've seen some source code that seems to have level data stored as variable lists in .db or .dw variables:

Code: Select all

LevelData: .db 1,2,3
Assuming I am correct and you can store variable lists this way, how can you specify and retrieve a specific number in the list?
Image
IT'S GREAT TO BE A MICHIGAN WOLVERINE!
User avatar
Halifax
Sir Posts-A-Lot
Posts: 225
Joined: Mon 01 Jan, 2007 10:39 am
Location: Pennsylvania, US

Post by Halifax »

Now to answer your question. I am going to put this in its simplest form, and the way your directly specified you wanted it above. Of course there is a better way, but that is a little bit more complicated, and advanced.

Code: Select all

ld a,(LevelData)
cp 1
jp z,DispSpriteOne
cp 2
jp z,DispSpriteTwo
cp 3
jp z,DispSpriteThree

etc.
User avatar
driesguldolf
Extreme Poster
Posts: 395
Joined: Thu 17 May, 2007 4:49 pm
Location: $4080
Contact:

Post by driesguldolf »

I would like to apply a simple optimization:

Code: Select all

start:
   ld a, (leveldata)
   dec a      ; Sets the zero flag if a was one
   jr z, dispsprite1
   dec a      ; A is already decremented, if we do it again we have subtracted 2 in total, zero is set if A was 2
   jr z, dispsprite2
   dec a      ; Zero set if A was 3
   jr z, dispsprite3
;...
To access an element of your array (which 28days explains perfectly) you take the address where your arrays starts (aka base address) and add an offset:

Code: Select all

   ld a, (leveldata)   ; Gets the first element
   ld a, (leveldata+1) ; Gets the 2nd element
   ld a, (leveldata+2) ; Gets the 3rd element
;...
This will only work if every element of your array is one byte large (-> points again to 28days for more explanation)


Keep in mind that I don't have an accurate idea about how far you are with programming, don't take it personal when I say something you already knew ;)
driesguldolf wrote:Halifax is entirely correct, though I'd like the emphase that you should think the memory as one BIG array.
Now those elements of that array are bytes.
To recall any of it's elements is very simple:

Code: Select all

   ld a, (index)
where index is a number ranging from 0-65535 (aka addresses).
This effectively gets the byte stored at 'address' and copies it's content to the register A

Keep in mind that the only thing you can store there are numbers (or better ones and zeros). That implies that your code are also numbers, in fact each instruction you type will be converted (by the assembler) into a number(s) (aka opcodes)

Now the .db directive simply states that the assembler has to put some numbers on the following locations
Thus:

Code: Select all

.db 13  ; Inserts the number '13' in your program
.db -4  ; I assume you know how the Z80 deals with negative numbers
.db 888 ; ERROR: the value is supposed to fit in a byte (and 888 is outside 8bit (aka byte) range)
.db 67,8,123,0      ; You can have multiple bytes after each other
.db "This is text!" ; (*)
(*) Text is no exception of the fact that you can only store numbers in memory: each character is represented by a number (TASM uses 'ASCII' to find out what character translates to what number)

Code: Select all

.db 84,104,105,115,32,105,115,32,116,101,120,116,33
Would be exaclty the same as typing .db "This is text"

Now you can think "Do I have to remember all the addresses where I store my data out of my head?". Of course you do!... lol just kiddin', in TASM there are 'labels'. If you write something at the start of a line TASM will interpret it as a label and assigns a value to it corresponding to the address the next byte will be stored when you run your program

Too bad you cannot claim all that memory, the first 32Kb is used with the Flash memory and a lot of the other half is claimed by TIOS.
When you run a program it is copied to $9D95 (people commonly use hexadecimal to talk about addresses)
I have no idea why I wrote this, 28days says about the same... lol is something wrong with the font after the first codebox?
User avatar
nepmarauder
Regular Member
Posts: 119
Joined: Thu 14 Apr, 2005 7:02 pm
Location: Ann Arbor, MI
Contact:

Post by nepmarauder »

Thanks once again guys. Ya, I'm more of a C and C++ programmer, and I haven't touched assembly in about two years... so I don't take the newbie instructions personal. Too bad I didn't see that source in 28Days... :x... rookie mistake.
Image
IT'S GREAT TO BE A MICHIGAN WOLVERINE!
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

Re: [TI-ASM] Level Data

Post by King Harold »

nepmarauder wrote:

Code: Select all

LevelData: .db 1,2,3
Assuming I am correct and you can store variable lists this way, how can you specify and retrieve a specific number in the list?
Do you mean you just want to index the list?
If so, it is really easy. You probably know that LevelData[index] translates to &LevelData + sizeof(byte)*index, in z80 assembly you cannot do this in 1 instruction with a variable index. However, nothing keeps us from splitting the math into several instructions so:

Code: Select all

ld de,LevelData  ;base address (  &LevelData  ) use BC if DE is in use
ld hl,(index)  ;if index is a variable, if you computer it just leave this line out
add hl,de  ;forget about multiplication: this is a byte array anyway
;(hl) now refers to the number LevelData[index]
If you have DW's

Code: Select all

ld de,LevelData  ;base address (  &LevelData  ) use BC if DE is in use
ld hl,(index)  ;if index is a variable, if you computer it just leave this line out
add hl,hl  ;it might be a good idea to pre-multiply the index..
add hl,de
;slightly more complicated: (hl) refers to the LSB of LevelData[index], don't forget to 'inc hl' and read the MSB as well!

On Halifaxes code:
Nothing really wrong with, but seeing as these values are a continuous range..

Code: Select all

ld a,(LevelData)
dec a  ;if it started with zero, use OR A (..or AND A..) first
jp z,DispSpriteOne
dec a
jp z,DispSpriteTwo
dec a
jp z etc etc..
save one byte on each branch thingy (and 3 t-states)
Or even crazier: a jumptable! (you shouldn't need this..)
Only good when you want speed and you have lots of compares otherwise, hard to use HL to pass a parameter to functions this way

Code: Select all

ld a,(LevelData)
dec a ;only needed because you start at 1
ld l,a
ld h,0
ld d,h
ld e,a
add hl,hl ;x2
add hl,de ;x3
ld de,jumpTable
add hl,de
jp (hl)
jumpTable:
jp SpriteOne
jp SpriteTwo
jp SpriteThree
etc..
alternatively you could use a vector table: (I think it could be faster.. and the table takes less space)

Code: Select all

ld a,(leveldata)
dec a
ld h,0
ld l,a
add hl,hl ;only x2 this time
ld de,vectortable
add hl,de
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
jp (hl)
vectortable:
.dw SpriteOne
.dw SpriteTwo
.dw SpriteThree
etc
but thinking about those sprites, if you store them the right way you could make a subroutine that draws the sprite at HL, making the problem far simpler:
(for sprites that are 8pix high)

Code: Select all

ld a,(LevelData)
ld h,0
ld l,a
add hl,hl ;x2
add hl,hl ;x4
add hl,hl ;x8
ld de,Sprites
add hl,de
call DrawSpriteHL
BC (or DE if you replace DE by BC) is the only normal register that is free, I don't know how your code works but you may want to pass an X and an Y coordinate in it..

Edit: alright, dries beat me to it while I was still writing this huge post, lol
User avatar
Halifax
Sir Posts-A-Lot
Posts: 225
Joined: Mon 01 Jan, 2007 10:39 am
Location: Pennsylvania, US

Post by Halifax »

King_Harold: Yes I could have done that, but as I said I was translating his code directly. As driesguldolf said "we don't exactly know your skills" so I just gave the easiest method possible that was a direct translation.

mepmarauder: Yeah, haha it is much better to switch to C when you come from an assembly background, then vice versa. Especially when dealing with the z80.
User avatar
nepmarauder
Regular Member
Posts: 119
Joined: Thu 14 Apr, 2005 7:02 pm
Location: Ann Arbor, MI
Contact:

Post by nepmarauder »

Simple ASM knowledge made C++ so much easier to learn. Unfortunately it doesn't work both ways. :roll:
Image
IT'S GREAT TO BE A MICHIGAN WOLVERINE!
Liazon
Calc Guru
Posts: 962
Joined: Thu 27 Oct, 2005 8:28 pm

Post by Liazon »

that's for sure ^^
Image Image Image
Post Reply