Author Topic: My first 68k asm program: a small sprite routine  (Read 6848 times)

0 Members and 1 Guest are viewing this topic.

Offline chickendude

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 817
  • Rating: +90/-1
  • Pro-Riot Squad
    • View Profile
My first 68k asm program: a small sprite routine
« on: June 13, 2012, 02:41:03 am »
Last night i spent several hours writing a really simple sprite drawing routine. I'm curious if anyone could give me any comments or suggestions on the code. For some reason, i had a lot of trouble trying to rotate the pixels from one register into another so i just doubled the size of the sprite  :-[ (initially i was using all bytes)
Code: [Select]
move.b #0,d0 | X
move.b #20,d1 | Y
lea spriteBox,a1
jsr drawSprite

movea.l AMS_jumptable,%a5 | load the AMS jumptable to a5
movea.l 4*ngetchx(%a5),%a5 | ngetchx()
jsr (%a5)
bra exit


|----------------------------
| drawSprite: draw a sprite to LCD
| d0 = X position
| d1 = Y position
| a1 = sprite location
drawSprite:
move.b d0,d2 | save X coord
and.b #0x07,d0 | how much we need to rotate the sprite
mulu #30,d1 | i think the screen is 30 bytes wide?
lea LCD_MEM,a0 | start of LCD_MEM
add d1,a0 | add the Y offset to a0
lsr #3,d2 | shift d2 (xCoord) right 3 bits
add d2,a0 | add X offset to a0
move.b #7,d2 | display 8 rows
screenLoop:
move.w (a1)+,d1 | put the byte of data into d1
lsr.w d0,d1 | rotate byte of data 'd0' bits to the right
eor.w d1,(a0) | xor (ExclusiveOR) the byte (well, word) into a0 (the LCD)
lea 30(a0),a0 | shift down a row
dbra d2,screenLoop | it's beyond me why d2=7 will draw 8 rows... it must break on -1?
rts

spriteBox:
.byte 0b11111111,0
.byte 0b11111111,0
.byte 0b11100111,0
.byte 0b11000011,0
.byte 0b11000011,0
.byte 0b11100111,0
.byte 0b11111111,0
.byte 0b11111111,0
It's also kinda weird that the dbra/deq both break on -1 and not 0. Being able to rotate a byte by X/register number of bytes is pretty cool, though :D How exactly does that work? Will rotating a byte 5 times take longer than rotating it 3 times? I assume so, but i don't know anything about the size/speed of 68k instructions... I also don't know if "lea 30(a0),a0" is faster than "adda #30,a0", but i like being able to use all the address registers sort of like the z80's index registers (ix/iy).

And, the LCD: it took me a long time to get the sprite drawn right, the screen is 160 pixels wide, or 20 bytes, why does it seem like it's 30 bytes wide? How many bytes tall is LCD_MEM? Could you use the bytes to the right of the screen for smoothscrolling in a tilemapper, for example? Next up, a simple tilemapper :D

I may have asked this before, too, but why do numbers (except addresses?) need to be prefixed by a pound (#) sign? At first i thought it was to signal a decimal value, but later i realized you need to put it before all numbers.

And does anyone have a list of saferam areas for the 89? Is there a graph buffer somewhere?

Offline chickendude

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 817
  • Rating: +90/-1
  • Pro-Riot Squad
    • View Profile
Re: My first 68k asm program: a small sprite routine
« Reply #1 on: June 18, 2012, 09:37:39 am »
...so i tried displaying another sprite afterwards and it gives me an address error (i've come to dread those words, i see them all the time). I'm not sure why, is it maybe because i'm using byte-sized commands and maybe i fill one of the registers with a word or long that doesn't get cleared? I can't see where the problem might be...

EDIT: Ah.. it's the parameters i'm passing to the routine, there must be a mistake in there somewhere. I'll look through the code again...
EDIT2: So i don't get it. The first time through i XOR a byte to $4E58 (well within LCD_MEM) without a problem, the second time through it bugs out on $4E58. Does it have to be word-aligned or something?
« Last Edit: June 18, 2012, 09:58:52 am by chickendude »

Offline chickendude

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 817
  • Rating: +90/-1
  • Pro-Riot Squad
    • View Profile
Re: My first 68k asm program: a small sprite routine
« Reply #2 on: June 19, 2012, 12:32:47 am »
Now that i know you've got to stay word-aligned things have started to go a little more smoothly, though i still make lots of mistakes especially when the upper bytes of a register corrupt the results of a calculation, but last night i finally got a little tilemap routine up and running:
Code: [Select]
;a2=pointer to map data
drawTileMap:
move.b (a2)+,mapWidth+3 ; the first byte contains the width of the map
clr.l d1 ; d1 = y position on screen of current tile, set to 0 and clear out upper bytes
move.l #6,d3 ; number of rows to draw
;d0=x
;d1=y
;d2=col counter
;d3=row counter
;a2=mappointer
dTM_vert
clr.l d0
move.w #9,d2
dTM_horiz:
movem.w d0-d3,-(sp) ; push x/y and the counters onto the stack
move.b (a2)+,d2
mulu.b #32,d2 ; each sprite is 32 bytes
lea tiles(pc,d2),a1
bsr drawSpriteAligned
movem.w (sp)+,d0-d3 ; retrieve pushed values
add.w #16,d0 ; move over 16 pixels to draw next sprite
dbra.w d2,dTM_horiz
add.b #16,d1
mapWidth:
adda.w #00,a2
dbra.w d3,dTM_vert
rts

;----------------------------
; drawSpriteAligned: draw an aligned sprite to LCD
; d0 = X position
; d1 = Y position
; a2 = sprite location
drawSpriteAligned:
mulu.b #30,d1 ; screen is 30 bytes wide
lea LCD_MEM,a0 ; start of LCD_MEM
add d1,a0 ; add the Y offset to a0
divu.b #8,d0 ; divide d2 by 8
add d0,a0 ; add X offset to a0
move.w #15,d2 ; display 16 rows
dSA_loop:
move.w (a1)+,d1 ; put the word of data into d1
eor.w d1,(a0) ; xor (ExclusiveOR) the byte (well, word) into a0 (the LCD)
lea 30(a0),a0 ; shift down a row
dbra d2,dSA_loop ; decrement and repeat until d2=0 (after the routine, d2 will = -1)
rts
Which results in:

(there are two leftover rows on the bottom, is that how the screen is set up?)

Also, does anyone have any saferam information for the 89? And is there an easy way to shift a byte across registers? It's something you do all the time in z80...

Offline TIfanx1999

  • ಠ_ಠ ( ͡° ͜ʖ ͡°)
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 6173
  • Rating: +191/-9
    • View Profile
Re: My first 68k asm program: a small sprite routine
« Reply #3 on: June 20, 2012, 04:13:15 am »
I know nothing about 68k, but I think it's really cool that you're fooling around with it. Also, I recognize those sprites. ;D

Offline Jim Bauwens

  • Lua! Nspire! Linux!
  • Editor
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1881
  • Rating: +206/-7
  • Linux!
    • View Profile
    • nothing...
Re: My first 68k asm program: a small sprite routine
« Reply #4 on: June 20, 2012, 04:15:31 am »
Aw, I'm sorry that nobody is responding. I would if I knew a bit more.
Anyway I see you got your saferam solution on yAronet ^^

And that screenshot looks nice :)

Edit: hey some else responded too :D
« Last Edit: June 20, 2012, 04:17:00 am by jimbauwens »

Offline chickendude

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 817
  • Rating: +90/-1
  • Pro-Riot Squad
    • View Profile
Re: My first 68k asm program: a small sprite routine
« Reply #5 on: June 20, 2012, 07:29:02 am »
Yeah, i guess you generally just create your own space in RAM to use for storage. And yes, those sprites do look surprisingly familiar... ;)

Offline aeTIos

  • Nonbinary computing specialist
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3915
  • Rating: +184/-32
    • View Profile
    • wank.party
Re: My first 68k asm program: a small sprite routine
« Reply #6 on: June 20, 2012, 10:54:21 am »
Ok what are these sprites from then?
I'm not a nerd but I pretend:

Offline Lionel Debroux

  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2135
  • Rating: +290/-45
    • View Profile
    • TI-Chess Team
Re: My first 68k asm program: a small sprite routine
« Reply #7 on: June 21, 2012, 01:35:34 am »
I'm supposed to be notified of new topics in this section of Omnimaga (where more _active_ TI-68k programmers gather than on yAronet), but it didn't seem to work this time...

Several notes about your code:
* your current code works, but in general, for readability, all of your instructions should have a size (.b, .w or .l) at the end of the mnemonic :)
* mulu and divu usually have .w size, and they're not used in the usual sprite routines because they're very slow. mulu.w #30,dn is replaced by a series of add.w, lsl.w and sub.w; divu.w #8,dn is simply the much faster lsr.w #3, dn ;)
* strictly speaking, the correct mnemonic for "dbra" is "dbf";
* "lea LCD_MEM,a0" should be "lea LCD_MEM.w,a0", to make sure that the assembler uses the shorter form;
* "add d1,a0" should be "adda.w d1,a0".
* "adda.w #00,a2" is superfluous :)
« Last Edit: June 21, 2012, 01:47:59 am by Lionel Debroux »
Member of the TI-Chess Team.
Co-maintainer of GCC4TI (GCC4TI online documentation), TILP and TIEmu.
Co-admin of TI-Planet.

Offline TIfanx1999

  • ಠ_ಠ ( ͡° ͜ʖ ͡°)
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 6173
  • Rating: +191/-9
    • View Profile
Re: My first 68k asm program: a small sprite routine
« Reply #8 on: June 21, 2012, 02:42:33 am »
@aeTIos:The sprites are from a TI 83+ RPG that chickendude has been progamming on and off. :) It's was posted on Revsoft's old site. I cant recall if it's been posted on the new site atm.

Offline chickendude

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 817
  • Rating: +90/-1
  • Pro-Riot Squad
    • View Profile
Re: My first 68k asm program: a small sprite routine
« Reply #9 on: June 21, 2012, 08:31:25 am »
* mulu and divu usually have .w size, and they're not used in the usual sprite routines because they're very slow. mulu.w #30,dn is replaced by a series of add.w, lsl.w and sub.w; divu.w #8,dn is simply the much faster lsr.w #3, dn ;)
I wasn't sure about that, i figured the mul/div instructions would be slower, but i didn't know. In z80 i would just shift over a few times or add the number to it's self. So divu.w #8 would be faster than lsr.w #3? Does multiplication take up the same number of clocks for every calculation? That is, if i multiply by two will it take the same number of clocks as multiplying by 2555? Where can i find the clock cycles each instruction takes? I'm gonna try to add smoothscrolling and see how the speed compares to the z80. I imagine even this bloated code will run faster than my z80 tilemap routine, especially without the slow LCD.

* strictly speaking, the correct mnemonic for "dbra" is "dbf";
I read this in the manual :)
* "lea LCD_MEM,a0" should be "lea LCD_MEM.w,a0", to make sure that the assembler uses the shorter form;
And it gets sign extended to a long-word?
Quote
* "add d1,a0" should be "adda.w d1,a0".
The compiler fixed this for me, right?
Quote
* "adda.w #00,a2" is superfluous :)
Actually, the #00 gets overwritten through SMC: "move.b (a2)+,mapWidth+3" I'm not sure if this is good practice or not on the 68k, but it's something i do all the time in z80 :)
@aeTIos: they're taken from an RPG i was working on before my old laptop blew up and i lost a lot of the code:

Offline Lionel Debroux

  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2135
  • Rating: +290/-45
    • View Profile
    • TI-Chess Team
Re: My first 68k asm program: a small sprite routine
« Reply #10 on: June 21, 2012, 09:38:45 am »
Quote
So divu.w #8 would be faster than lsr.w #3?
No, divu.w #8,dn is more than an order of magnitude slower than lsr.w #3,dn :)

Quote
Quote
"lea LCD_MEM,a0" should be "lea LCD_MEM.w,a0", to make sure that the assembler uses the shorter form;
And it gets sign extended to a long-word?
Yes, lea LCD_MEM.w,a0 extends to a long word.

Quote
Quote
"add d1,a0" should be "adda.w d1,a0".
The compiler fixed this for me, right?
Yes.

Quote
Actually, the #00 gets overwritten through SMC: "move.b (a2)+,mapWidth+3" I'm not sure if this is good practice or not on the 68k, but it's something i do all the time in z80 :)
yeah, I missed the fact that you're using SMC :)
An adda.w to a2 should do the job; so adda.w #00,a2 and before that, move.b (a2)+,mapWidth+1 , would save a couple bytes.
Member of the TI-Chess Team.
Co-maintainer of GCC4TI (GCC4TI online documentation), TILP and TIEmu.
Co-admin of TI-Planet.

Offline chickendude

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 817
  • Rating: +90/-1
  • Pro-Riot Squad
    • View Profile
Re: My first 68k asm program: a small sprite routine
« Reply #11 on: June 24, 2012, 02:49:40 am »
How do the shift instructions work? Will an lsr.w #3,dn perform three shifts (like z80's slr rr \ slr rr \ slr rr)? Or will shifting 1 bit use the same number of clocks as shifting 8 bits? Do you know where i can find information on how long instructions take to execute? In the programmer's manual it lists the binary construction of each of the instructions, but i can't seem to find how many cycles an instruction will take.

Offline Lionel Debroux

  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2135
  • Rating: +290/-45
    • View Profile
    • TI-Chess Team
Re: My first 68k asm program: a small sprite routine
« Reply #12 on: June 24, 2012, 03:09:42 am »
Quote
How do the shift instructions work? Will an lsr.w #3,dn perform three shifts (like z80's slr rr \ slr rr \ slr rr)?
Yup :)

Quote
Or will shifting 1 bit use the same number of clocks as shifting 8 bits?
Unfortunately, no, not on a 68000. It's the case on an ARM, though.

Quote
Do you know where i can find information on how long instructions take to execute? In the programmer's manual it lists the binary construction of each of the instructions, but i can't seem to find how many cycles an instruction will take.
The Motorola 68000 PRM does, indeed, not contain cycle counts, because it covers all of the members of the 68000 family. What you need is the 68000 User Manual, usually named 68000UM.pdf :)
Member of the TI-Chess Team.
Co-maintainer of GCC4TI (GCC4TI online documentation), TILP and TIEmu.
Co-admin of TI-Planet.

Offline chickendude

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 817
  • Rating: +90/-1
  • Pro-Riot Squad
    • View Profile
Re: My first 68k asm program: a small sprite routine
« Reply #13 on: June 24, 2012, 03:30:26 am »
Awesome, thanks. I just downloaded it, though i must admit it's a little overwhelming, i'll have to sit down some time and try reading through it.