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

0 Members and 1 Guest are viewing this topic.

#### chickendude

• Posts: 816
• Rating: +90/-1
##### 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 locationdrawSprite: 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 rowsscreenLoop: 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? rtsspriteBox:.byte 0b11111111,0.byte 0b11111111,0.byte 0b11100111,0.byte 0b11000011,0.byte 0b11000011,0.byte 0b11100111,0.byte 0b11111111,0.byte 0b11111111,0It'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 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

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?

#### chickendude

• Posts: 816
• Rating: +90/-1
##### 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 »

#### chickendude

• Posts: 816
• Rating: +90/-1
##### 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 datadrawTileMap: 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=mappointerdTM_vert clr.l d0 move.w #9,d2dTM_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,d1mapWidth: 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 locationdrawSpriteAligned: 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 rowsdSA_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) rtsWhich 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...

#### TIfanx1999

• ಠ_ಠ ( ͡° ͜ʖ ͡°)
• CoT Emeritus
• LV13 Extreme Addict (Next: 9001)
• Posts: 6173
• Rating: +191/-9
##### 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.

#### Jim Bauwens

• Lua! Nspire! Linux!
• Editor
• LV10 31337 u53r (Next: 2000)
• Posts: 1881
• Rating: +206/-7
• Linux!
##### 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
« Last Edit: June 20, 2012, 04:17:00 am by jimbauwens »

#### chickendude

• Posts: 816
• Rating: +90/-1
##### 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...

#### aeTIos

• Nonbinary computing specialist
• LV12 Extreme Poster (Next: 5000)
• Posts: 3913
• Rating: +184/-32
##### 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:

#### Lionel Debroux

• LV11 Super Veteran (Next: 3000)
• Posts: 2135
• Rating: +290/-45
##### 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...

* 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;
« 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.

#### TIfanx1999

• ಠ_ಠ ( ͡° ͜ʖ ͡°)
• CoT Emeritus
• LV13 Extreme Addict (Next: 9001)
• Posts: 6173
• Rating: +191/-9
##### 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.

#### chickendude

• Posts: 816
• Rating: +90/-1
##### 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
The compiler fixed this for me, right?
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
@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:

#### Lionel Debroux

• LV11 Super Veteran (Next: 3000)
• Posts: 2135
• Rating: +290/-45
##### 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
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.

#### chickendude

• Posts: 816
• Rating: +90/-1
##### 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.

#### Lionel Debroux

• LV11 Super Veteran (Next: 3000)
• Posts: 2135
• Rating: +290/-45
##### 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.