[A83] Re: Tilemap
[Prev][Next][Index][Thread]
[A83] Re: Tilemap
And you would get absolutely _horrible_ performance. You can't make a
tilemap routine by calling a normal putsprite and expect to get any
performance out of it. Since it's aligned anyway, you are much better off
using an aligned putsprite routine.
When I started CnC86, I wrote a simple routine to draw part of a large
tilemap (64x64). It only did aligned, but if you run the demo, you will see
that it is quite fast. This was written a very long time ago, so the code
isn't that great, but it's not absolutely terrible. It's commented and you
can see what is going on. The sprite routine could be improved by not using
IX at all. Obviously, you want to intregrate everything. It's stupid to
calculate coordinates and pass them to a sprite routine, when you can just
calculate the address in the map routine and just increment the pointer. It
makes the code more complicated, but it will be faster. I'd been doing z80
for maybe six months when I wrote this, so I was just getting into writing
good code. It takes a while to really get a feel for how to put everything
together.
http://www.ticalc.org/pub/86/asm/source/cnc86.zip
(comments should be aligned when viewed in a fixed width font)
MapX = _textShadow + 10 ; [1] upper-left corner of the map display
MapY = _textShadow + 11 ; [1] ...
DrawMap:
ld de,(MapX) ; load the map coords (note: loaded in
reverse order!)
ld h,d ; move the y coord to the high byte (* 256)
srl h ; divide by two (* 128)
rra ; move overflow to low byte
srl h ; again, divide by two (* 64)
rra ; handle final overflow
and %11000000 ; clear lower 6 bits
or e ; add the x coord (x <= 63)
ld l,a ; move to low byte
ld de,Map ; point to the map
add hl,de ; add the map start to the offset
ld b,8 ; we need to draw 8 rows
ld d,0 ; start y draw coord at 0
DMYLoop:
push bc ; save the y counter
ld b,12 ; each row has 12 tiles in it
ld e,0 ; start x draw coord at 0
DMXLoop:
push bc ; save the x counter
push hl ; save the map pointer
push de ; save the tile draw coords
ld l,(hl) ; load the tile number into the low byte
ld h,0 ; clear the high byte
add hl,hl ; * 2
add hl,hl ; * 4
add hl,hl ; * 8, each sprite is 8 bytes
ld de,MapSprites ; point to the start of the map sprites
add hl,de ; point to the correct sprite
pop de ; restore the tile draw coords
push de ; save the tile draw coords
call GridPutSprite ; draw the sprite!
pop de ; restore the tile draw coords
pop hl ; restore the map pointer
inc hl ; move to the next tile
inc e ; move to next x position
pop bc ; restore the x counter
djnz DMXLoop ; loop for all tiles in the row
ld bc,64-12 ; each row is 64 bytes wide (12 on the screen)
add hl,bc ; move to next row
inc d ; move to next y position
pop bc ; restore the y counter
djnz DMYLoop ; draw all the rows
ret ; finally, and many t-states later, we're done!
;=====================================================================
; GridPutSprite:
; Puts an aligned sprite at (E, D), where HL -> Sprite
;=====================================================================
; IN : D = y (0-7 inclusive)
; E = x (0-15 inclusive)
; HL-> sprite
;
; OUT: AF, BC, DE, HL, IX modified
; Current total : 28b/567t (not counting ret)
;=====================================================================
GridPutSprite:
push hl
pop ix ; ix-> sprite
srl d ; de = 128y+x (16 bytes/row, 8 rows)
rra
and $80
or e ; add x offset (remember x <= 15)
ld e,a
ld hl,MapScr ; hl-> MapScr
add hl,de ; hl-> MapScr + offset
ld b,8 ; initialize loop counter
ld de,$10 ; initialize line increment
GPS_Loop
ld a,(ix+0) ; get byte from sprite
ld (hl),a ; put byte on screen
inc ix ; move to next byte in sprite
add hl,de ; move to next line on screen
djnz GPS_Loop
ret
> Looks like another one of them ionPutSprite tilemap routines, like the one
I
> started out with before switching to TCPA's tilemap routine. It would be
a
> lot better to use a clipped sprite routine, then change the origin by
pixels
> as well as tiles.
Follow-Ups:
References: