News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_EgoTrip

Tile routine

Started by EgoTrip, 18:51, 10 February 13

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

EgoTrip

I am in need of help creating a tile display routine for levels. I intend on LDIR'ing the level data into the workspace. It is laid out in 16x12 grid, with 0 a blank space, 01 a wall, 02 coin, thats all for now but there are more.


So, how do I go about displaying the levels?



I've got a sprite routine that LDIR's the sprite to its position as I do not need transparency for the tile display routine, but it uses up all the registers. How do I make a tile routine with it, or will I need another sprite routine?



I cant get my head around the example on the wiki, and thats in mode 0 anyway. I am working in mode 1, with a 16x16 tile (256x256 pixel) screen (the level area is 16x12 with the bottom 4 rows for the HUD).

redbox

Quote from: EgoTrip on 18:51, 10 February 13
[size=78%]I cant get my head around the example on the wiki, and thats in mode 0 anyway. I am working in mode 1, with a 16x16 tile (256x256 pixel) screen (the level area is 16x12 with the bottom 4 rows for the HUD).[/size]


If you're talking about Arnoldemu's routine then it would be a good idea to try and understand it because if you start using tilemaps then eventually you're also going to want to use them for collision detection etc and hence need a nice way of accessing them (such as the detailed 2d array/matrix approach in this example).


However, if you're just wanting to draw a screen from a tilemap, something quick and dirty like this might help you and be easier to understand:




org &4000


tile_start equ &6000
tile_size equ &40
tile_height equ 16 ; lines
tile_width equ 4 ; bytes


scr_set_mode equ &BC0E
scr_set_border equ &BC38
km_wait_key equ &BB18

ld a,1
call scr_set_mode ; change to MODE 1

call sub_init_crtc ; setup CRTC for 32x32 screen


ld bc,0
call scr_set_border ; BORDER 0

call sub_draw_tilemap ; draw the tilemap


call km_wait_key ; wait for keypress


ret ; and RETurn




sub_init_crtc: ld bc,&bc01 ; CRTC register 1
out (c),c
ld bc,&bd00+32 ; set width in characters
out (c),c


ld bc,&bc02 ; CRTC register 2
out (c),c
ld bc,&bd00+42 ; set horizontal position
out (c),c


ld bc,&bc06 ; CRTC register 6
out (c),c
ld bc,&bd00+32 ; set height in characters
out (c),c


ld bc,&bc07 ; CRTC regsiter 7
out (c),c
ld bc,&bd00+34 ; set vertical position
out (c),c


ret




sub_draw_tilemap: ld b,13 ; number of rows


main_loop: push bc ; preserve counter


ld b,16 ; number of tiles in a row
call row_loop


ld hl,(scr_addr_pointer) ; screen address two char lines down is &80
ld de,&40 ; we have already added &40 by printing a tile horizontal line
add hl,de ; so we only need to add &40 to get 2 char lines down
ld (scr_addr_pointer),hl


pop bc
djnz main_loop


ret


row_loop: push bc ; preserve counter


ld hl,(tilemap_01_pointer) ; load HL with tilemap
ld e,(hl) ; load E with tile number from tilemap
ld h,tile_size ; size of tile sprite
ld d,0 ; reset these ...
ld l,0 ; ... for multiply routine
call sub_multiply ; multiply together
ld de,tile_start ; to get the memory address of the tile we want
add hl,de ; HL equals tile memory address


ld de,(scr_addr_pointer)
ld b,tile_height
ld c,tile_width
call sub_sprite ; print the tile to the screen

ld hl,(tilemap_01_pointer) ; increase pointer to next tile in table
inc hl
ld (tilemap_01_pointer),hl ; and store it


ld hl,(scr_addr_pointer) ; increase pointer to next screen address for tile
inc hl
inc hl
inc hl
inc hl
ld (scr_addr_pointer),hl ; and store it


pop bc ; restore counter
djnz row_loop ; loop back if not all done


ret




sub_multiply: sla ; optimised 1st iteration
jr nc,$+3
ld l,e


add hl,hl  ; unroll 7 times
jr nc,$+3  ; ...
add hl,de  ; ...


add hl,hl  ; unroll 7 times
jr nc,$+3  ; ...
add hl,de  ; ...


add hl,hl  ; unroll 7 times
jr nc,$+3  ; ...
add hl,de  ; ...


add hl,hl  ; unroll 7 times
jr nc,$+3  ; ...
add hl,de  ; ...


add hl,hl  ; unroll 7 times
jr nc,$+3  ; ...
add hl,de  ; ...


add hl,hl  ; unroll 7 times
jr nc,$+3  ; ...
add hl,de  ; ...


add hl,hl  ; unroll 7 times
jr nc,$+3  ; ...
add hl,de  ; ...


ret


sub_sprite: push de ; preserve screen address
        push bc          ; and the dimensions
        ld b,0          ; BC now equals the width in bytes
        ldir            ; copy the bytes!
        pop bc          ; get back the dimensions
        pop de          ; and then the screen address


        ex de,hl        ; to move DE onto the next screen line,
          call nline      ; we use the routine to move HL onto the
        ex de,hl        ; the next line, but swap DE and HL either side
        djnz sub_sprite      ; if not all lines done, loop back
        ret


nline:   ld a,8
        add a,h          ; add 8 to H (the high byte)
        ld h,a
        ret nc          ; return if no overflow


        push de          ; otherwise preserve DE
        ld de,&C040
        add hl,de        ; add &C000+&50 to HL
        pop de          ; and get DE back again!
        ret




scr_addr_pointer: defw &C000 ; sub_draw_tilemap


tilemap_01_pointer: defw tilemap_01 ; sub_draw_tilemap


tilemap_01: defb 06,08,08,08,06,01,06,08,06,00,00,00,00,00,00,00 ; sub_draw_tilemap
defb 07,00,00,00,00,03,00,00,06,08,08,08,08,08,08,06
defb 07,00,00,00,00,03,00,00,00,00,00,00,00,00,00,07
defb 07,00,00,00,00,03,00,00,00,00,00,00,00,00,00,07
defb 07,00,00,00,00,03,00,00,00,00,00,00,00,00,00,07
defb 06,00,00,00,00,03,00,00,00,00,00,00,00,00,00,06
defb 01,02,02,02,02,04,02,05,02,02,02,02,02,02,02,01
defb 06,00,00,00,00,00,00,03,00,00,00,00,00,00,00,06
defb 07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
defb 07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
defb 07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
defb 07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
defb 06,08,08,08,08,08,06,01,06,08,08,08,08,08,08,06




org &6000                   ; tile sprite data


db #00,#00,#00,#00,#00,#00,#00,#00
db #00,#00,#00,#00,#00,#00,#00,#00
db #00,#00,#00,#00,#00,#00,#00,#00
db #00,#00,#00,#00,#00,#00,#00,#00
db #00,#00,#00,#00,#00,#00,#00,#00
db #00,#00,#00,#00,#00,#00,#00,#00
db #00,#00,#00,#00,#00,#00,#00,#00
db #00,#00,#00,#00,#00,#00,#00,#00
db #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
db #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
db #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
db #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
db #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
db #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
db #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
db #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
db #f0,#f0,#f0,#f0,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#f0,#f0,#f0,#f0
db #d7,#5f,#5f,#5e,#a7,#af,#af,#be
db #d7,#5f,#5f,#5e,#a7,#af,#af,#be
db #d7,#5f,#5f,#5e,#a7,#af,#af,#be
db #d7,#5f,#5f,#5e,#a7,#af,#af,#be
db #d7,#5f,#5f,#5e,#a7,#af,#af,#be
db #d7,#5f,#5f,#5e,#a7,#af,#af,#be
db #d7,#5f,#5f,#5e,#a7,#af,#af,#be
db #d7,#5f,#5f,#5e,#a7,#af,#af,#be
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#f0,#f0,#f0,#f0
db #f0,#f0,#f0,#f0,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #5f,#5f,#5f,#5f,#af,#af,#af,#af
db #f0,#f0,#f0,#f0,#a5,#a5,#a5,#b4
db #c3,#0f,#0f,#1e,#87,#af,#af,#bc
db #d3,#ff,#ff,#1e,#87,#ff,#ff,#bc
db #d3,#ff,#ff,#1e,#87,#ff,#ff,#bc
db #d3,#ff,#ff,#1e,#87,#ff,#ff,#bc
db #d3,#ff,#ff,#1e,#87,#ff,#ff,#bc
db #d3,#5f,#5f,#1e,#87,#0f,#0f,#3c
db #d2,#5a,#5a,#5a,#f0,#f0,#f0,#f0
db #21,#3f,#ef,#c0,#30,#7f,#cf,#48
db #21,#3f,#ef,#c0,#30,#7f,#cf,#48
db #21,#3f,#ef,#c0,#30,#7f,#cf,#48
db #21,#3f,#ef,#c0,#30,#7f,#cf,#48
db #21,#3f,#ef,#c0,#30,#7f,#cf,#48
db #21,#3f,#ef,#c0,#30,#7f,#cf,#48
db #21,#3f,#ef,#c0,#30,#7f,#cf,#48
db #21,#3f,#ef,#c0,#30,#7f,#cf,#48
db #00,#00,#00,#00,#00,#00,#00,#00
db #f0,#f0,#f0,#f0,#a5,#a5,#a5,#a5
db #0f,#0f,#0f,#0f,#af,#af,#af,#af
db #ff,#ff,#ff,#ff,#ff,#ff,#ff,#ff
db #ff,#ff,#ff,#ff,#ff,#ff,#ff,#ff
db #5f,#5f,#5f,#5f,#0f,#0f,#0f,#0f
db #5a,#5a,#5a,#5a,#f0,#f0,#f0,#f0
db #00,#00,#00,#00,#00,#00,#00,#00



It basically takes a number from the tilemap (01,02,03 etc), then mutliplies it by the size of each tile sprite (&40 in this case) and this gives us the memory address of the tile (which start at &6000 onwards).  Once we've got the address of the tile, we simply print it to the screen like any other sprite and move onto the next tile in the tilemap until we're finished.

redbox


Or...

If you're using a 32 x 32 character screen and the tiles are 16 x 16, everything can be nicely page-aligned because you're not going to go past &FF (i.e. 256, which is 16 x 16).

Something like this:



            org     &4000

            tile_height    equ 16        ; lines
            tile_width    equ 4        ; bytes

            scr_set_mode    equ &BC0E
            scr_set_border    equ &BC38
            km_wait_key    equ &BB18
   

            ld    a,1
            call    scr_set_mode        ; MODE 1
           
            call    s_init_crtc        ; setup CRTC for 32x32 screen

            ld    bc,0
            call    scr_set_border        ; BORDER 0
   
            call    s_draw_tile_map        ; draw the tilemap

            call    km_wait_key        ; wait for keypress

            ret                ; and RETurn


s_init_crtc:        ld     bc,&bc01        ; CRTC register 1
            out     (c),c
            ld     bc,&bd00+32        ; set width in characters
            out     (c),c

            ld     bc,&bc02        ; CRTC register 2
            out     (c),c
            ld     bc,&bd00+42        ; set horizontal position
            out     (c),c

            ld     bc,&bc06        ; CRTC register 6
            out     (c),c
            ld     bc,&bd00+32        ; set height in characters
            out     (c),c       

            ld     bc,&bc07        ; CRTC regsiter 7
            out     (c),c
            ld     bc,&bd00+34        ; set vertical position
            out     (c),c

            ret


s_draw_tile_map:    ld    h,tile_map_01/256    ; load HL with start address of page-aligned...
            ld    l,&00            ; ...tile map table (16x16 tiles so 256 bytes in size)

            ld    b,16            ; number of rows

s_draw_tile_map_loop:    push    bc            ; preserve row counter

s_draw_row:        ld    b,16            ; number of tiles in a row
       
s_draw_row_loop:    push     bc            ; preserve tile counter
            push    hl            ; preserve table position

            ld    a,(hl)            ; load A with tile number from table

            ld    h,0            ; reset H
            ld    l,a            ; load L with tile number

            add    hl,hl            ; multiply it so we get the memory...
            add    hl,hl            ; ...address for the tile sprite...
            add    hl,hl            ; ...as they are &40 each in size
            add    hl,hl            ; e.g. tile 6 is &40 x 6 = &0180
            add    hl,hl
            add    hl,hl

            ld    a,tile_sprites/256    ; load A with the start of the tile sprites (&4200)
            add    a,h            ; and add it back to H (e.g. &0180 + &4200 = &4380)
            ld    h,a            ; HL now holds tile sprite location we want to print

            ld     de,(scr_addr_pointer)    ; DE is the screen address position
            ld    b,tile_height        ; BC is the height and width
            ld    c,tile_width

            call    s_sprite        ; print the tile to the screen
           
            ld    hl,(scr_addr_pointer)    ; increase pointer to next screen address for tile
            inc    l            ; which is 4 bytes away
            inc     l
            inc    l
            inc    l
            ld    (scr_addr_pointer),hl    ; and store it

            pop    hl            ; get table position back into HL
            inc    l            ; and move on one position in table

            pop     bc            ; restore tile counter

            djnz    s_draw_row_loop        ; loop back to do another tile if row not finished


            push    hl            ; preserve table position

            ld    hl,(scr_addr_pointer)    ; screen address two char lines down is &80
            ld    de,&40            ; we have already added &40 by printing a tile horizontal line
            add    hl,de            ; so we only need to add &40 to get 2 char lines down
            ld    (scr_addr_pointer),hl   

            pop    hl            ; get table position back into HL

            pop    bc            ; restore row counter

            djnz    s_draw_tile_map_loop    ; loop back to do another row if not finished

            ret


s_sprite:        push     de            ; preserve screen address
                push     bc                     ; and the dimensions
                    ld     b,0                  ; BC now equals the width in bytes
                ldir                    ; copy the bytes!
                pop     bc                  ; get back the dimensions
                pop     de                  ; and then the screen address

                    ex     de,hl                ; to move DE onto the next screen line,
                    call     s_sprite_nline         ; we use the routine to move HL onto the
                ex     de,hl                ; the next line, but swap DE and HL either side
                djnz     s_sprite             ; if not all lines done, loop back
                ret

s_sprite_nline:        ld     a,8
                    add     a,h                 ; add 8 to H (the high byte)
                ld     h,a
                ret     nc                  ; return if no overflow

                push     de                 ; otherwise preserve DE
                ld     de,&C040
                add     hl,de               ; add &C000+&40 to HL
                pop     de                  ; and get DE back again!
                ret


scr_addr_pointer:    defw    &C000           

            align    256

tile_map_01:        defb     06,08,08,08,06,01,06,08,06,00,00,00,00,00,00,00       
            defb    07,00,00,00,00,03,00,00,06,08,08,08,08,08,08,06
            defb    07,00,00,00,00,03,00,00,00,00,00,00,00,00,00,07
            defb    07,00,00,00,00,03,00,00,00,00,00,00,00,00,00,07
            defb    07,00,00,00,00,03,00,00,00,00,00,00,00,00,00,07
            defb    06,00,00,00,00,03,00,00,00,00,00,00,00,00,00,06
            defb    01,02,02,02,02,04,02,05,02,02,02,02,02,02,02,01
            defb    06,00,00,00,00,00,00,03,00,00,00,00,00,00,00,06
            defb    07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
            defb    07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
            defb    07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
            defb    07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
            defb    07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
            defb    07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
            defb    07,00,00,00,00,00,00,03,00,00,00,00,00,00,00,07
            defb    06,08,08,08,08,08,06,01,06,08,08,08,08,08,08,06

            align    256

tile_sprites:        db     #00,#00,#00,#00,#00,#00,#00,#00
            db     #00,#00,#00,#00,#00,#00,#00,#00
            db     #00,#00,#00,#00,#00,#00,#00,#00
            db     #00,#00,#00,#00,#00,#00,#00,#00
            db     #00,#00,#00,#00,#00,#00,#00,#00
            db     #00,#00,#00,#00,#00,#00,#00,#00
            db     #00,#00,#00,#00,#00,#00,#00,#00
            db     #00,#00,#00,#00,#00,#00,#00,#00
            db     #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
            db     #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
            db     #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
            db     #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
            db     #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
            db     #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
            db     #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
            db     #f0,#f0,#f0,#f0,#f0,#f0,#f0,#f0
            db     #f0,#f0,#f0,#f0,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#f0,#f0,#f0,#f0
            db     #d7,#5f,#5f,#5e,#a7,#af,#af,#be
            db     #d7,#5f,#5f,#5e,#a7,#af,#af,#be
            db     #d7,#5f,#5f,#5e,#a7,#af,#af,#be
            db     #d7,#5f,#5f,#5e,#a7,#af,#af,#be
            db     #d7,#5f,#5f,#5e,#a7,#af,#af,#be
            db     #d7,#5f,#5f,#5e,#a7,#af,#af,#be
            db     #d7,#5f,#5f,#5e,#a7,#af,#af,#be
            db     #d7,#5f,#5f,#5e,#a7,#af,#af,#be
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#f0,#f0,#f0,#f0
            db     #f0,#f0,#f0,#f0,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #5f,#5f,#5f,#5f,#af,#af,#af,#af
            db     #f0,#f0,#f0,#f0,#a5,#a5,#a5,#b4
            db     #c3,#0f,#0f,#1e,#87,#af,#af,#bc
            db     #d3,#ff,#ff,#1e,#87,#ff,#ff,#bc
            db     #d3,#ff,#ff,#1e,#87,#ff,#ff,#bc
            db     #d3,#ff,#ff,#1e,#87,#ff,#ff,#bc
            db     #d3,#ff,#ff,#1e,#87,#ff,#ff,#bc
            db     #d3,#5f,#5f,#1e,#87,#0f,#0f,#3c
            db     #d2,#5a,#5a,#5a,#f0,#f0,#f0,#f0
            db     #21,#3f,#ef,#c0,#30,#7f,#cf,#48
            db     #21,#3f,#ef,#c0,#30,#7f,#cf,#48
            db     #21,#3f,#ef,#c0,#30,#7f,#cf,#48
            db     #21,#3f,#ef,#c0,#30,#7f,#cf,#48
            db     #21,#3f,#ef,#c0,#30,#7f,#cf,#48
            db     #21,#3f,#ef,#c0,#30,#7f,#cf,#48
            db     #21,#3f,#ef,#c0,#30,#7f,#cf,#48
            db     #21,#3f,#ef,#c0,#30,#7f,#cf,#48
            db     #00,#00,#00,#00,#00,#00,#00,#00
            db     #f0,#f0,#f0,#f0,#a5,#a5,#a5,#a5
            db     #0f,#0f,#0f,#0f,#af,#af,#af,#af
            db     #ff,#ff,#ff,#ff,#ff,#ff,#ff,#ff
            db     #ff,#ff,#ff,#ff,#ff,#ff,#ff,#ff
            db     #5f,#5f,#5f,#5f,#0f,#0f,#0f,#0f
            db     #5a,#5a,#5a,#5a,#f0,#f0,#f0,#f0
            db     #00,#00,#00,#00,#00,#00,#00,#00


The code is completely unoptimised as it's proof of concept, but it's still less sloppy than the first one I posted. :D


EgoTrip

Thanks for the help, will reply if I get stuck, which I probably will.

Powered by SMFPacks Menu Editor Mod