;; Example which draws a tilemap. ;; ;; A tilemap is an array of tile indexes. In the code it is stored as ;; a 1-dimensional linear array, but is accessed like it is a 2d array. ;; e.g. tilemap[(tiley*tilemap_width_tiles)+tilex] ;; ;; The tile indexes define the index of the tile who's graphics should ;; be drawn. ;; ;; Each tile is 8x16 pixels and they are stored uncompressed in a form ;; that can be poked direct to the screen. This example is designed for ;; mode 0. ;; ;; In this example there are multiple tilemaps. These do not scroll. ;; A simple map is stored where each tilemap is part of the map. Pressing ;; the cursor keys moves you between each tilemap left, right up and down. ;; ;; This source released under GNU Library License v1 or later. ;; ;; Code by Kevin Thacker, 2010. ;; ;; Tile graphics by Markus. ;; width of a tile tile_width_bytes equ 8/2 ;; height of a tile tile_height equ 16 ;; number of bytes used by tile (each tile uses same ;; number of bytes and stored uncompressed in a form ;; that can be poked direct to screen) tile_data_size equ tile_width_bytes*tile_height ;; number of tiles we handles num_tiles equ 4 ;; width of screen in pixels scr_width_pixels equ 160 ;; height of screen in pixels scr_height_pixels equ 200 scr_width_bytes equ scr_width_pixels/2 ;; width of screen in tiles tilemap_width_tiles equ scr_width_bytes/tile_width_bytes ;; height of screen in tiles tilemap_height_tiles equ scr_height_pixels/tile_height ;; index into directions for each tilemap ;; indicating which tilemap is to left/right/up/down of current tilemap_dir_left equ 0 tilemap_dir_right equ tilemap_dir_left+1 tilemap_dir_up equ tilemap_dir_right+1 tilemap_dir_down equ tilemap_dir_up+1 tilemap_num_dirs equ tilemap_dir_down+1 tilemap_dir_invalid equ &ff ;; size of table holding tilemap ptrs (in bytes) size_tilemap_ptrs equ end_tilemap_ptrs - tilemap_ptrs ;; each address is 16-bit, so number of tiles is size in bytes /2 num_tilemaps equ size_tilemap_ptrs/2 ;; firmware functions we use scr_next_line equ &bc26 scr_set_mode equ &bc0e scr_set_border equ &bc38 scr_set_ink equ &bc32 mc_wait_flyback equ &bd19 km_test_key equ &bb1e org &1000 nolist start: ;; set 16 colour mode 1 ld a,0 call scr_set_mode ;; set border to black ld bc,0 call scr_set_border ;; set pens ld hl,pens ld b,16 ;; 4 pens for mode 1 xor a ;; initial pen index set_pens push bc push af ld c,(hl) ;; B,C = inks for pen. If they are the same then no ;; flashing ld b,c inc hl push hl call scr_set_ink pop hl pop af pop bc inc a ;; increment pen index djnz set_pens call make_scr_table call make_tile_ptr_table xor a ld (tilemap_cur),a ld a,1 ld (tilemap_changed),a ;; the main loop which draws and updates sprite main_loop: call mc_wait_flyback ;; check keys and update sprite position call check_keys ld a,(tilemap_changed) or a jp z,main_loop xor a ld (tilemap_changed),a call tilemap_draw jp main_loop ;; check if a key has been pressed and perform action if it has check_keys: ld a,0 ;; cursor up call km_test_key jp nz,tilemap_up ld a,2 ;; cursor down call km_test_key jp nz,tilemap_down ld a,8 ;; cursor left call km_test_key jp nz,tilemap_left ld a,1 ;; cursor right call km_test_key jp nz,tilemap_right ret get_tilemap_dirs: ld a,(tilemap_cur) ld l,a ld h,0 add hl,hl ;; x2 add hl,hl ;; x2 ;; = x4 (number of directions) ld de,tilemap_dirs add hl,de push hl pop ix ret ;; based on current tilemap, move to next tilemap to left tilemap_left: call get_tilemap_dirs ld a,(ix+tilemap_dir_left) cp tilemap_dir_invalid ret z ld (tilemap_cur),a ld a,1 ld (tilemap_changed),a ret ;; based on current tilemap, move to next tilemap to right tilemap_right: call get_tilemap_dirs ld a,(ix+tilemap_dir_right) cp tilemap_dir_invalid ret z ld (tilemap_cur),a ld a,1 ld (tilemap_changed),a ret ;; based on current tilemap, move to next tilemap up tilemap_up: call get_tilemap_dirs ld a,(ix+tilemap_dir_up) cp tilemap_dir_invalid ret z ld (tilemap_cur),a ld a,1 ld (tilemap_changed),a ret ;; based on current tilemap, move to next tilemap to down tilemap_down: call get_tilemap_dirs ld a,(ix+tilemap_dir_down) cp tilemap_dir_invalid ret z ld (tilemap_cur),a ld a,1 ld (tilemap_changed),a ret ;; tilemap is drawn from left-to-right ;; top-to-bottom one tile at a time tilemap_draw: ;; get address of tilemap data ld a,(tilemap_cur) ld l,a ld h,0 add hl,hl ld de,tilemap_ptrs add hl,de ld a,(hl) inc hl ld h,(hl) ld l,a ;; HL = ptr to tilemap indices push hl pop ix ;; IX = ptr to tilemap indices ;; H = X screen coord of top-left of tilemap ld h,0 ;; L = Y screen coord of top-left of tilemap ld l,0 ;; width and height of tilemap in tiles ld b,tilemap_height_tiles ld c,tilemap_width_tiles tilemap_draw_y: push hl push bc ;; calc screen address ;; from x,y coord call get_scr_addr tilemap_draw_x: ;; read tile index ld a,(ix+0) inc ix push bc push hl ;; lookup ptr to tile pixels call get_tile_ptr ;; now draw tile call tile_draw pop hl ;; HL = screen address ;; increment by width of tile in bytes ld bc,tile_width_bytes add hl,bc pop bc dec c jr nz,tilemap_draw_x pop bc pop hl ;; H = x coordinate ;; L = y coordinate ;; update Y coordinate for next tilemap line ld a,l add a,tile_height ld l,a djnz tilemap_draw_y ret ;; IN: ;; A = tile index ;; OUT: ;; DE = tile pixel data get_tile_ptr: push hl ld l,a ld h,0 add hl,hl ld de,tile_ptr_table add hl,de ld e,(hl) inc hl ld d,(hl) pop hl ret ;; From our x,y coordinates generate ;; a screen address for top-left of sprite to be drawn at. ;; IN: ;; H = x byte coord ;; L = y line ;; OUT: ;; HL = screen address get_scr_addr: push bc push de ld c,h ld h,0 add hl,hl ld de,scr_addr_table add hl,de ld a,(hl) inc hl ld h,(hl) ld l,a ld b,0 add hl,bc pop de pop bc ret ;; generate table of screen addresses ;; one address per scanline. The address ;; is for the first byte of each line. make_scr_table: ld ix,scr_addr_table ;; address to store table ld hl,&c000 ;; start address of first scanline ld b,200 ;; number of scanlines on screen mst1: ld (ix+0),l ld (ix+1),h inc ix inc ix push bc call scr_next_line pop bc djnz mst1 ret ;; generate table/array of tile pixel ptrs ;; so that we can access tile pixels quickly based ;; on tile index make_tile_ptr_table: ld ix,tile_ptr_table ld hl,tile_gfx ;; start of tile pixels (tile 0) ld de,tile_data_size ;; size of each tile (all tiles same size in bytes) ld b,num_tiles ;; number of tiles to generate information for mtpt1: ld (ix+0),l ld (ix+1),h inc ix inc ix add hl,de djnz mtpt1 ret ;; IN: ;; DE = address of tile pixel data ;; HL = screen address tile_draw: ld b,tile_height ld c,tile_width_bytes tile_draw_height: push bc push hl tile_draw_width: ld a,(de) ;; read from pixels ld (hl),a ;; write to screen inc hl inc de dec c jr nz,tile_draw_width pop hl call scr_next_line pop bc djnz tile_draw_height ret ;; table/array for screen addresses for each scan line scr_addr_table: defs 200*2 ;; the inks for the pens pens: defb &00 defb &01 defb &01 defb &01 defb &02 defb &02 defb &06 defb &06 defb &0c defb &0a defb &0a defb &0e defb &18 defb &18 defb &1a defb &1a ;; current screen id tilemap_cur: defb 0 ;; indicates screen id has changed and screen needs redraw tilemap_changed: defb 0 ;; directions for each screen, gives id of ;; screen to move to ;; map arranged like this ;; ;; [3] ;; | ;; [1] - [0] - [2] ;; | ;; [4] tilemap_dirs: ;; tilemap 0 defb 1 ;; left defb 2 ;; right defb 3 ;; up defb 4 ;; down ;; tilemap 1 defb tilemap_dir_invalid ;; left defb 0 ;; right defb tilemap_dir_invalid ;; up defb tilemap_dir_invalid ;; down ;; tilemap 2 defb 0 ;; left defb tilemap_dir_invalid ;; right defb tilemap_dir_invalid ;; up defb tilemap_dir_invalid ;; down ;; tilemap 3 defb tilemap_dir_invalid ;; left defb tilemap_dir_invalid ;; right defb tilemap_dir_invalid ;; up defb 0 ;; down ;; tilemap 4 defb tilemap_dir_invalid ;; left defb tilemap_dir_invalid ;; right defb 0 ;; up defb tilemap_dir_invalid ;; down ;; pointer to screen data tilemap_ptrs: defw tilemap0 defw tilemap1 defw tilemap2 defw tilemap3 defw tilemap4 end_tilemap_ptrs: tile_ptr_table: defs num_tiles*2 tilemap0: ;; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 defb 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 ;; 0 defb 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 ;; 1 defb 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 ;; 2 defb 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 ;; 3 defb 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ;; 4 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 5 defb 0, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ;; 6 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 7 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 8 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0 ;; 9 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 10 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 11 tilemap1: ;; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 defb 0, 2, 1, 1, 2, 0, 1, 1, 1, 2, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0 ;; 0 defb 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ;; 1 defb 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0 ;; 2 defb 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0 ;; 3 defb 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0 ;; 4 defb 0, 2, 1, 1, 2, 0, 1, 0, 0, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0 ;; 5 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 6 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 7 defb 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 ;; 8 defb 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0 ;; 9 defb 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 ;; 10 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 11 tilemap2: ;; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 defb 0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 0 defb 0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 1 defb 0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 2 defb 0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 3 defb 0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 4 defb 0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 5 defb 0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 6 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 7 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 8 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 9 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 10 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 11 tilemap3: ;; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 defb 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1 ;; 0 defb 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 ;; 1 defb 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 ;; 2 defb 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 ;; 3 defb 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0 ;; 4 defb 0, 3, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 3, 0 ;; 5 defb 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0 ;; 6 defb 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 ;; 7 defb 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 ;; 8 defb 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 ;; 9 defb 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 ;; 10 defb 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ;; 11 tilemap4: ;; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 defb 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 0, 3, 3, 3, 0, 3, 3, 3, 0, 0 ;; 0 defb 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0 ;; 1 defb 0, 0, 0, 3, 0, 0, 0, 3, 3, 0, 0, 3, 3, 3, 0, 0, 3, 0, 0, 0 ;; 2 defb 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0 ;; 3 defb 0, 0, 0, 3, 0, 0, 0, 3, 3, 3, 0, 3, 3, 3, 0, 0, 3, 0, 0, 0 ;; 4 defb 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 5 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 6 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 7 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 8 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 9 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 10 defb 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;; 11 tile_gfx: defb &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 defb &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 defb &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 defb &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 defb &8c,&0c,&0c,&4c,&9a,&30,&30,&a4,&9a,&30,&30,&a4,&9a,&30,&30,&a4 defb &da,&4b,&87,&a4,&9a,&f0,&f0,&24,&da,&4b,&87,&a4,&9a,&f0,&f0,&24 defb &da,&4b,&87,&a4,&9a,&f0,&f0,&24,&da,&4b,&87,&a4,&9a,&f0,&f0,&24 defb &da,&4b,&87,&a4,&9a,&30,&30,&a4,&9a,&30,&30,&a4,&cf,&cf,&cf,&ca defb &03,&03,&03,&57,&53,&f3,&f3,&f7,&53,&33,&33,&77,&53,&33,&33,&77 defb &53,&b3,&73,&77,&53,&51,&a2,&f7,&53,&b3,&73,&77,&53,&33,&33,&77 defb &53,&b3,&73,&77,&53,&51,&a2,&f7,&53,&a2,&51,&77,&53,&73,&b3,&77 defb &53,&33,&33,&77,&53,&33,&33,&77,&53,&33,&33,&77,&bf,&3f,&3f,&7f defb &3c,&3c,&a8,&bc,&3c,&3c,&a8,&bc,&fc,&fc,&a8,&fc,&00,&00,&00,&00 defb &fc,&a8,&fc,&fc,&3c,&a8,&bc,&3c,&fc,&a8,&fc,&fc,&00,&00,&00,&00 defb &54,&fc,&fc,&54,&54,&3c,&7c,&54,&54,&fc,&fc,&54,&00,&00,&00,&00 defb &fc,&a8,&fc,&fc,&3c,&a8,&bc,&3c,&fc,&a8,&fc,&fc,&00,&00,&00,&00 ;; tiles