Skip to content

Instantly share code, notes, and snippets.

@taylorza
Created August 17, 2024 17:34
Show Gist options
  • Save taylorza/f37c4eb2fb344ee2a8df5b9957b36cd0 to your computer and use it in GitHub Desktop.
Save taylorza/f37c4eb2fb344ee2a8df5b9957b36cd0 to your computer and use it in GitHub Desktop.

Revisions

  1. taylorza created this gist Aug 17, 2024.
    749 changes: 749 additions & 0 deletions isodemo.asm
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,749 @@
    ;SLDOPT COMMENT WPMEM, LOGPOINT, ASSERTION
    DEVICE ZXSPECTRUMNEXT
    CSPECTMAP "isodemo.map"

    org $8000

    ACTIVE_16K_BANK = 9
    SHADOW_16K_BANK = 12
    ACTIVE_8K_BANK = ACTIVE_16K_BANK*2
    SHADOW_8K_BANK = SHADOW_16K_BANK*2

    TILE_SIZE = 16
    HALF_TILE = TILE_SIZE/2
    MAP_WIDTH = 16
    MAP_HEIGHT = 16
    PLAYER_SPEED = 3

    main:
    ei

    nextreg 7, 3

    // Enable layer 2
    ld bc, $123b
    ld a, 2
    out (c), a

    // Setup initial layer 2 bank
    nextreg $12, ACTIVE_16K_BANK
    nextreg $56, ACTIVE_8K_BANK
    nextreg $14, $e3

    xor a
    out (254), a

    call flipScreen
    call cls

    call flipScreen
    call cls

    loop
    ld hl, (playerPos)
    call cartToIdx
    ld (playerIdx), a
    call cls
    call drawMap
    call flipScreen
    in a, ($1f)
    rra
    call c, moveRight
    rra
    call c, moveLeft
    rra
    call c, moveDown
    rra
    call c, moveUp
    jp loop
    jr $ ; Loop forever!

    moveRight
    ld hl, playerX
    ex af, af
    ld a, (hl)
    cp (MAP_WIDTH * HALF_TILE)-4
    jr nc, .done
    add PLAYER_SPEED
    ld (hl), a
    .done
    ex af, af
    ret
    moveLeft
    ld hl, playerX
    ex af, af
    ld a, (hl)
    cp TILE_SIZE
    jr c, .done
    add -PLAYER_SPEED
    ld (hl), a
    .done
    ex af, af
    ret

    moveDown
    ld hl, playerY
    ex af, af
    ld a, (hl)
    cp (MAP_WIDTH * HALF_TILE)-12
    jr nc, .done
    add PLAYER_SPEED
    ld (hl), a
    .done
    ex af, af
    ret
    moveUp
    ld hl, playerY
    ex af, af
    ld a, (hl)
    cp TILE_SIZE
    jr c, .done
    add -PLAYER_SPEED
    ld (hl), a
    .done
    ex af, af
    ret

    cls
    ld hl, shadow_bank
    ld a, (hl)
    exx
    ld b, 3
    .clsbank
    exx
    nextreg $56, a
    inc a
    nextreg $57, a
    ex af, af
    xor a
    ld hl, $c000
    ld bc, $4000
    call fillMemory
    ex af, af
    inc a
    exx
    djnz .clsbank
    exx
    ret

    flipScreen
    ld hl, visible_bank ; Point to visible_bank
    ld b, (hl) ; B = current visible bank
    inc hl ; Point to shadow_bank
    ld a, (hl) ; A = current shadow bank
    ld (visible_bank), a ; Switch visible bank
    srl a ; Calculate 16K Bank number

    halt ; Wait for refresh
    nextreg $12, a ; Switch to new visible bank
    ld a, b ; A = previous visible bank
    ld (shadow_bank), a ; Switch shadow bank
    ret
    ;------------------------------------------------------------------------------
    ; drawMap - Draws the isometric map
    drawMap
    ld bc, isoCoordTbl
    ld de, map
    ; Store loop counter in BC'
    exx ; Switch to secondary registers
    ld bc, MAP_WIDTH * MAP_HEIGHT
    xor a
    ld (tileIdx), a
    .drawTile
    exx ; Switch to primary registers
    ld a, (de) ; Load tile id from map
    add a, a
    ld hl, tileTbl
    add hl, a ; HL = Tile pointer

    ld a, (hl) ; HL = *HL
    inc hl
    ld h, (hl)
    ld l, a

    push hl:push de:push bc
    call drawIsoTile
    ld hl, playerIdx
    ld a, (tileIdx)
    cp (hl)
    pop bc:pop de:pop hl
    jr nz, .continue
    push hl:push de:push bc
    call drawIsoPlayer
    pop bc:pop de:pop hl

    .continue
    ld a, (tileIdx)
    inc a
    ld (tileIdx), a ; Update tile index
    inc bc:inc bc ; Move to next iso coordinate
    inc de ; Move to next map cell

    ; Decrement and check loop counter in secondary registers
    exx ; switch to secondary registers
    dec bc
    ld a, c
    or b
    jp nz, .drawTile

    exx ; switch to primary registers
    ret
    ;------------------------------------------------------------------------------
    ; drawIsoTile - Draws an isometric tile
    ; Input
    ; BC - Iso Coordinate entry
    ; HL - Pointer to tile data
    drawIsoTile
    ; Load coordinate from table in BC to into DE
    ld a, (bc)
    ld e, a ; E - isoX
    inc bc
    ld a, (bc)
    inc hl ; Point to tile height
    sub (hl) ; Offset isoY by the tile height
    ld d, a ; D - isoY
    ld c, (hl) ; load tile height
    inc hl ; move to first tile pixel

    ; D,E - isoY, isoX
    ; HL - tile data
    ; C - tile height
    .nextrow
    ; Set bank for the row
    push de ; Save iso coordinate
    ld a, d
    and %11100000 ; Mask off the relative bank
    rlca ; Shift bank to first 3 bits
    rlca
    rlca
    exx
    ld hl, shadow_bank
    add (hl)
    exx
    nextreg $56, a ; Set the bank in slot 6 ($C000)

    ld a, d
    and %00011111 ; Remove the relative bank
    or $c0 ; Add $c0 to A
    ld d, a ; Load DE with the $c000 relative address

    ; Render tile row
    push bc
    xor a ; A = Value not to transfer
    ld bc, TILE_SIZE
    ldirx ; BC x (*HL != A ? *DE++ = *HL++ : DE++, HL++)
    pop bc

    pop de ; Restore last iso coordinate
    inc d ; Move to next screen row
    dec c ; Decrement the remaining tile rows
    jp nz, .nextrow
    ret

    ;------------------------------------------------------------------------------
    ; drawIsoPlayer - Draws an isometric player
    ; Input
    ; BC - Iso Coordinate entry
    ; HL - Pointer to tile data
    drawIsoPlayer
    ; Load coordinate from table in BC to into DE
    ld a, (bc)
    ld e, a ; E - isoX
    inc bc
    ld a, (bc)
    sub (hl) ; Offset isoY by current tile base level
    ld d, a ; D - isoY

    ; Calculate sub cell position
    ld hl, (playerPos)
    ld a, h ; Mask bottom 3 bits of x
    and $7
    ld h, a

    ld a, l ; Mask bottom 3 bits of y
    and $7
    ld l, a
    call cartToIso ; Convert sub movement to iso offset
    ld a, d ; Add offset to isoY
    add h
    ld d, a

    ld a, e ; Add offset to isoX
    add l
    ld e, a
    ; Offset isoY by the player height
    ld hl, player
    ld c, (hl) ; load player height
    ld a, d ; load isoY into A
    sub c ; subtract player height
    ld d, a

    inc hl ; move to first tile pixel

    ; D,E - isoY, isoX
    ; HL - player data
    ; C - player height
    .nextrow
    ; Set bank for the row
    push de ; Save iso coordinate
    ld a, d
    and %11100000 ; Mask off the relative bank
    rlca ; Shift bank to first 3 bits
    rlca
    rlca
    exx
    ld hl, shadow_bank
    add (hl)
    exx
    nextreg $56, a ; Set the bank in slot 6 ($C000)

    ld a, d
    and %00011111 ; Remove the relative bank
    or $c0 ; Add $c0 to A
    ld d, a ; Load DE with the $c000 relative address

    ; Render player row
    push bc
    xor a ; A = Value not to transfer
    ld bc, TILE_SIZE
    ldirx ; BC x (*HL != A ? *DE++ = *HL++ : DE++, HL++)
    pop bc

    pop de ; Restore last iso coordinate
    inc d ; Move to next screen row
    dec c ; Decrement the remaining tile rows
    jp nz, .nextrow
    ret
    ;-------------------------------------------------------------------------------
    ; cartToIdx - convert cartesian coordinate to map index
    ; Input
    ; H = y-coordinate
    ; L = x-coordinate
    ; Output
    ; A = index into map
    cartToIdx
    ld a, h
    rra:rra:rra
    and %00011111 ; tileY = Y/8 (bottom 3 bits are sub cell)
    ld d, a
    ld e, MAP_WIDTH
    mul d,e ; rowIdx = tileY * MAP_WIDTH
    ld a, l
    rra:rra:rra
    and %00011111 ; tileX = X/8 (botton 3 bits are sub cell)
    add a, e ; idx = rowIdx + tileX
    ret

    ;-------------------------------------------------------------------------------
    ; cartToIso - convert cartesian coordinate to iso Coordinate
    ; Input
    ; H = y-coordinate
    ; L = x-coordinate
    ; Output
    ; H = isoY
    ; L = isoX
    cartToIso
    push de
    ; isoX = x-y
    ld a, l
    sub h
    ld e, a

    ; isoY = (x+y)/2
    ld a, l
    add h
    srl a
    ld d, a
    ex de, hl
    pop de
    ret

    ;-------------------------------------------------------------------------------
    ; fillMemory - Fill memory with byte using DMA
    ; Input
    ; A - Fill byte
    ; HL - Destination address
    ; BC - Fill count
    fillMemory
    ld (.fillByte), a
    ld (.dmaLen), bc
    ld (.dmaDst), hl
    ld hl, .dmaProgram
    ld bc, ((.dmaProgSize << 8) & 0xff00) | $6b
    otir
    ret
    .fillByte db 0
    .dmaProgram
    db %10000011 ; WR6: disable DMA
    db %01111101 ; WR0: address+length port A, A->B
    .dmaSrc
    dw .fillByte ; WR0: Address
    .dmaLen
    dw 0 ; WR0: Length
    db %00100100 ; WR1: A-Fixed, A=Memory
    db %00010000 ; WR2: B-Incr, B=Memory
    db %10101101 ; WR4 - continuous address port B
    .dmaDst
    dw 0 ; WR4: Address
    db %10000010 ; WR5: Stop on end of block
    db %11001111 ; WR6: Load address into DMA
    db %10000111 ; WR6: Enable DMA
    .dmaProgSize = $-.dmaProgram

    tileIdx db 0 ; Current tile index
    playerPos ; Player cartesian coordinate
    playerX db 20
    playerY db 20
    playerIdx db 0 ; Player location index

    visible_bank db ACTIVE_8K_BANK
    shadow_bank db SHADOW_8K_BANK

    map
    db 2,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3
    db 2,0,0,0,7,4,4,4,4,4,7,4,4,4,4,4
    db 1,0,0,0,7,4,4,4,4,4,7,4,4,4,4,4
    db 3,0,0,0,7,4,4,4,4,4,7,4,4,4,4,4
    db 3,4,4,4,7,7,7,7,7,7,7,7,7,7,7,7
    db 3,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0
    db 3,4,4,4,4,5,4,4,4,4,4,5,4,0,0,0
    db 3,4,4,4,7,4,4,4,4,4,6,4,4,0,0,0
    db 3,4,5,4,7,4,4,4,4,4,4,4,4,0,4,4
    db 3,4,4,4,7,9,8,8,8,9,4,4,4,0,4,4
    db 3,4,4,4,7,7,7,7,7,7,7,7,7,7,7,7
    db 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
    db 3,4,4,4,4,5,4,4,4,4,4,5,4,4,4,4
    db 3,4,5,4,4,4,4,4,4,4,4,4,4,4,4,4
    db 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
    db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3

    ; Tile index table
    tileTbl
    dw floor ; 0
    dw wall ; 1
    dw wall2 ; 2
    dw wall3 ; 3
    dw ground ; 4
    dw grass ; 5
    dw rock ; 6
    dw stone ; 7
    dw portal ; 8
    dw post ; 9

    floor: db 8, 8
    db $0, $0, $0, $0, $0, $0, $14, $14, $14, $14, $0, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $14, $14, $78, $78, $78, $78, $14, $14, $0, $0, $0, $0
    db $0, $0, $14, $14, $78, $78, $78, $78, $78, $78, $78, $78, $14, $14, $0, $0
    db $14, $14, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $14, $14
    db $14, $14, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $14, $14
    db $0, $0, $14, $14, $78, $78, $78, $78, $78, $78, $78, $78, $14, $14, $0, $0
    db $0, $0, $0, $0, $14, $14, $78, $78, $78, $78, $14, $14, $0, $0, $0, $0
    db $0, $0, $0, $0, $0, $0, $14, $14, $14, $14, $0, $0, $0, $0, $0, $0
    wall: db 16, 16
    db $0, $0, $0, $0, $0, $0, $84, $84, $84, $84, $0, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $84, $84, $e4, $e4, $e4, $e4, $84, $84, $0, $0, $0, $0
    db $0, $0, $84, $84, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $84, $84, $0, $0
    db $84, $84, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $84, $84
    db $84, $84, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $84, $84
    db $84, $c4, $84, $84, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $e4, $84, $84, $a4, $84
    db $84, $c4, $c4, $c4, $84, $84, $e4, $e4, $e4, $e4, $84, $84, $a4, $a4, $a4, $84
    db $84, $c4, $c4, $c4, $c4, $c4, $84, $84, $84, $84, $a4, $a4, $a4, $a4, $a4, $84
    db $84, $c4, $c4, $c4, $c4, $c4, $c4, $84, $84, $a4, $a4, $a4, $a4, $a4, $a4, $84
    db $84, $c4, $c4, $c4, $c4, $c4, $c4, $84, $84, $a4, $a4, $a4, $a4, $a4, $a4, $84
    db $84, $c4, $c4, $c4, $c4, $c4, $c4, $84, $84, $a4, $a4, $a4, $a4, $a4, $a4, $84
    db $84, $c4, $c4, $c4, $c4, $c4, $c4, $84, $84, $a4, $a4, $a4, $a4, $a4, $a4, $84
    db $84, $84, $c4, $c4, $c4, $c4, $c4, $84, $84, $a4, $a4, $a4, $a4, $a4, $84, $84
    db $0, $0, $84, $84, $c4, $c4, $c4, $84, $84, $a4, $a4, $a4, $84, $84, $0, $0
    db $0, $0, $0, $0, $84, $84, $c4, $84, $84, $a4, $84, $84, $0, $0, $0, $0
    db $0, $0, $0, $0, $0, $0, $84, $84, $84, $84, $0, $0, $0, $0, $0, $0

    wall2:
    db 24, 24
    db $0, $0, $0, $0, $0, $0, $5, $5, $5, $5, $0, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $5, $5, $f, $f, $f, $f, $5, $5, $0, $0, $0, $0
    db $0, $0, $5, $5, $f, $f, $f, $f, $f, $f, $f, $f, $5, $5, $0, $0
    db $5, $5, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $5, $5
    db $5, $5, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $5, $5
    db $5, $7, $5, $5, $f, $f, $f, $f, $f, $f, $f, $f, $5, $5, $6, $5
    db $5, $7, $7, $7, $5, $5, $f, $f, $f, $f, $5, $5, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $5, $5, $5, $5, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $5, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $5, $5
    db $0, $0, $5, $5, $7, $7, $7, $5, $5, $6, $6, $6, $5, $5, $0, $0
    db $0, $0, $0, $0, $5, $5, $7, $5, $5, $6, $5, $5, $0, $0, $0, $0
    db $0, $0, $0, $0, $0, $0, $5, $5, $5, $5, $0, $0, $0, $0, $0, $0

    wall3 db 16, 16
    db $0, $0, $0, $0, $0, $0, $50, $91, $91, $50, $0, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $50, $91, $91, $91, $91, $91, $91, $50, $0, $0, $0, $0
    db $0, $0, $50, $91, $91, $91, $91, $91, $50, $91, $91, $91, $91, $50, $0, $0
    db $50, $91, $91, $91, $91, $91, $50, $91, $91, $91, $50, $50, $91, $91, $91, $50
    db $28, $91, $91, $91, $91, $91, $91, $91, $91, $50, $91, $91, $91, $91, $b5, $24
    db $28, $28, $28, $91, $91, $91, $91, $91, $91, $91, $91, $91, $b5, $2c, $2c, $24
    db $28, $28, $28, $28, $28, $91, $91, $91, $91, $91, $b5, $2c, $50, $2c, $50, $24
    db $2c, $28, $28, $28, $28, $28, $28, $91, $b5, $2c, $2c, $2c, $50, $2c, $2c, $24
    db $48, $28, $28, $28, $28, $28, $2c, $28, $50, $2c, $50, $2c, $2c, $2c, $2c, $24
    db $48, $48, $48, $48, $28, $28, $28, $28, $2c, $2c, $2c, $2c, $48, $6d, $6d, $24
    db $48, $48, $48, $48, $48, $48, $28, $28, $50, $48, $6d, $8d, $6d, $6d, $6d, $24
    db $48, $48, $48, $48, $6d, $48, $48, $28, $2c, $6d, $8d, $6d, $8d, $6d, $8d, $24
    db $0, $24, $48, $48, $48, $48, $48, $48, $6d, $6d, $6d, $6d, $6d, $6d, $24, $0
    db $0, $0, $0, $24, $48, $48, $48, $48, $6d, $6d, $6d, $6d, $24, $0, $0, $0
    db $0, $0, $0, $0, $0, $24, $48, $48, $6d, $6d, $24, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $0, $0, $0, $24, $24, $0, $0, $0, $0, $0, $0, $0

    ground db 12, 12
    db $0, $0, $0, $0, $0, $0, $d1, $d1, $ad, $44, $0, $0, $0, $0, $0, $0
    db $0, $0, $d1, $69, $20, $69, $ad, $69, $44, $d1, $69, $69, $0, $0, $0, $0
    db $0, $d1, $d1, $69, $69, $44, $ad, $d1, $ad, $69, $69, $44, $69, $69, $0, $0
    db $d1, $ad, $69, $44, $d1, $69, $20, $69, $20, $69, $d1, $ad, $d1, $d1, $69, $20
    db $69, $44, $44, $d1, $d1, $69, $44, $ad, $69, $69, $44, $44, $69, $69, $20, $20
    db $44, $20, $69, $ad, $44, $ad, $d1, $d1, $d1, $ad, $69, $69, $44, $44, $20, $20
    db $69, $20, $69, $69, $20, $d1, $d1, $ad, $ad, $69, $44, $20, $20, $20, $20, $20
    db $69, $20, $69, $44, $44, $69, $69, $ad, $69, $44, $44, $20, $20, $20, $20, $20
    db $0, $20, $69, $69, $44, $44, $44, $20, $20, $20, $20, $20, $20, $20, $20, $0
    db $0, $0, $0, $20, $44, $69, $44, $20, $20, $20, $20, $20, $20, $0, $0, $0
    db $0, $0, $0, $0, $0, $44, $69, $44, $20, $20, $20, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $0, $0, $0, $20, $20, $0, $0, $0, $0, $0, $0, $0

    grass db 14, 14
    db $0, $0, $0, $0, $0, $0, $0, $0, $75, $50, $0, $0, $0, $0, $0, $0
    db $0, $0, $75, $0, $0, $75, $75, $0, $50, $75, $0, $0, $0, $0, $0, $0
    db $0, $0, $75, $50, $0, $50, $50, $b9, $50, $50, $50, $75, $0, $0, $0, $0
    db $0, $0, $50, $50, $b9, $4, $b9, $b9, $75, $4, $50, $b9, $28, $75, $50, $0
    db $75, $50, $b9, $4, $28, $b9, $75, $50, $50, $b9, $75, $28, $75, $75, $50, $0
    db $50, $28, $28, $b9, $75, $b9, $50, $4, $4, $75, $4, $4, $28, $50, $50, $50
    db $28, $50, $28, $4, $4, $75, $75, $28, $28, $75, $75, $50, $75, $75, $50, $4
    db $75, $50, $75, $50, $b9, $b9, $4, $4, $b9, $4, $28, $50, $50, $75, $4, $4
    db $28, $28, $28, $75, $50, $50, $50, $50, $b9, $28, $50, $28, $4, $50, $4, $1
    db $4, $28, $28, $4, $75, $28, $28, $75, $75, $4, $50, $50, $4, $4, $1, $1
    db $0, $4, $4, $4, $28, $4, $28, $4, $75, $4, $4, $4, $1, $1, $1, $0
    db $0, $0, $0, $4, $28, $4, $28, $4, $1, $4, $4, $4, $1, $0, $0, $0
    db $0, $0, $0, $0, $0, $4, $4, $4, $1, $4, $1, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $0, $0, $0, $4, $1, $0, $0, $0, $0, $0, $0, $0

    rock db 15, 15
    db $0, $0, $0, $0, $0, $0, $0, $b6, $b6, $92, $4d, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $0, $4d, $4d, $b6, $92, $92, $4d, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $b6, $4d, $29, $b6, $92, $92, $92, $4d, $0, $0, $0, $0
    db $0, $0, $0, $0, $b6, $4d, $b6, $b6, $92, $92, $92, $4d, $0, $0, $0, $0
    db $0, $0, $0, $b6, $92, $29, $b6, $b6, $92, $92, $92, $24, $0, $0, $0, $0
    db $0, $0, $0, $b6, $92, $92, $92, $4d, $92, $92, $4d, $29, $0, $0, $0, $0
    db $0, $0, $4d, $b6, $92, $92, $24, $4d, $4d, $4d, $4d, $24, $29, $0, $0, $0
    db $0, $0, $b6, $92, $92, $92, $4d, $24, $4d, $4d, $4, $29, $29, $4, $0, $0
    db $0, $0, $4d, $4d, $92, $4d, $92, $24, $4, $4, $29, $4d, $29, $4, $0, $0
    db $0, $0, $29, $4d, $4d, $24, $29, $24, $4d, $29, $4d, $4d, $29, $4, $0, $0
    db $0, $0, $4, $29, $29, $4d, $4d, $29, $4d, $4d, $4d, $4d, $4, $0, $0, $0
    db $0, $0, $92, $24, $29, $4d, $29, $1, $29, $29, $4d, $24, $29, $1, $0, $0
    db $0, $0, $4d, $92, $29, $29, $1, $24, $1, $24, $29, $29, $29, $24, $0, $0
    db $0, $0, $0, $4d, $29, $4d, $4d, $4d, $1, $29, $29, $29, $24, $0, $0, $0
    db $0, $0, $0, $0, $29, $4d, $4d, $1, $0, $24, $29, $0, $0, $0, $0, $0

    stone db 13, 13
    db $0, $0, $0, $0, $0, $0, $0, $92, $92, $0, $0, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $0, $0, $92, $92, $92, $92, $0, $0, $0, $0, $0, $0
    db $0, $0, $0, $92, $92, $29, $4d, $4d, $4d, $4d, $92, $92, $0, $0, $0, $0
    db $0, $0, $4d, $b6, $92, $4d, $92, $92, $4d, $4d, $b6, $92, $4d, $92, $92, $0
    db $92, $b6, $92, $29, $29, $b6, $92, $92, $4d, $29, $24, $29, $92, $92, $92, $4d
    db $4d, $b6, $92, $92, $92, $24, $4d, $4d, $92, $92, $92, $92, $29, $b6, $4d, $29
    db $29, $4d, $4d, $92, $92, $24, $92, $92, $b6, $92, $92, $92, $4d, $24, $29, $29
    db $29, $29, $4d, $4d, $4d, $b6, $92, $92, $4d, $4d, $29, $29, $29, $4, $24, $24
    db $4d, $4d, $24, $29, $29, $29, $4d, $92, $4d, $24, $29, $29, $1, $29, $29, $1
    db $0, $29, $24, $4d, $4d, $29, $4d, $4d, $29, $24, $29, $29, $1, $24, $1, $0
    db $0, $0, $0, $24, $29, $29, $24, $29, $1, $29, $29, $24, $1, $0, $0, $0
    db $0, $0, $0, $0, $0, $24, $4d, $29, $24, $24, $1, $0, $0, $0, $0, $0
    db $0, $0, $0, $0, $0, $0, $0, $29, $1, $0, $0, $0, $0, $0, $0, $0

    portal db 8, 48
    db $00, $00, $00, $00, $00, $00, $6, $6, $6, $6, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $6, $6, $f, $f, $f, $f, $6, $6, $00, $00, $00, $00
    db $00, $00, $6, $6, $f, $f, $f, $f, $f, $f, $f, $f, $6, $6, $00, $00
    db $6, $6, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $6, $6
    db $6, $6, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $6, $6
    db $00, $00, $6, $6, $f, $f, $f, $f, $f, $f, $f, $f, $6, $6, $00, $00
    db $00, $00, $00, $00, $6, $6, $f, $f, $f, $f, $6, $6, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $6, $6, $6, $6, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $14, $14, $14, $14, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $14, $14, $78, $78, $78, $78, $14, $14, $00, $00, $00, $00
    db $00, $00, $14, $14, $78, $78, $78, $78, $78, $78, $78, $78, $14, $14, $00, $00
    db $14, $14, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $14, $14
    db $14, $14, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $78, $14, $14
    db $00, $00, $14, $14, $78, $78, $78, $78, $78, $78, $78, $78, $14, $14, $00, $00
    db $00, $00, $00, $00, $14, $14, $78, $78, $78, $78, $14, $14, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $14, $14, $14, $14, $00, $00, $00, $00, $00, $00

    post db 48, 48
    db $00, $00, $00, $00, $00, $00, $5, $5, $5, $5, $00, $00, $00, $00, $00, $00
    db $00, $00, $00, $00, $5, $5, $f, $f, $f, $f, $5, $5, $00, $00, $00, $00
    db $00, $00, $5, $5, $f, $f, $f, $f, $f, $f, $f, $f, $5, $5, $00, $00
    db $5, $5, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $5, $5
    db $5, $5, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $f, $5, $5
    db $5, $7, $5, $5, $f, $f, $f, $f, $f, $f, $f, $f, $5, $5, $6, $5
    db $5, $7, $7, $7, $5, $5, $f, $f, $f, $f, $5, $5, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $5, $5, $5, $5, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $7, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $6, $5
    db $5, $5, $7, $7, $7, $7, $7, $5, $5, $6, $6, $6, $6, $6, $5, $5
    db $00, $00, $5, $5, $7, $7, $7, $5, $5, $6, $6, $6, $5, $5, $00, $00
    db $00, $00, $00, $00, $5, $5, $7, $5, $5, $6, $5, $5, $00, $00, $00, $00
    db $00, $00, $00, $00, $00, $00, $5, $5, $5, $5, $00, $00, $00, $00, $00, $00

    player db 16
    db $00, $00, $00, $00, $00, $1, $1, $1, $1, $1, $1, $00, $00, $00, $00, $00
    db $00, $00, $00, $1, $20, $20, $65, $65, $40, $40, $20, $44, $1, $00, $00, $00
    db $00, $00, $20, $20, $65, $41, $41, $41, $61, $61, $85, $41, $45, $20, $00, $00
    db $00, $1, $65, $41, $65, $81, $a6, $81, $81, $86, $61, $61, $41, $44, $1, $00
    db $00, $64, $65, $85, $85, $81, $ca, $c6, $c6, $c6, $81, $a5, $85, $65, $20, $00
    db $1, $40, $65, $85, $a6, $a6, $c6, $c6, $c6, $a2, $a6, $81, $a9, $41, $40, $1
    db $44, $45, $85, $85, $a1, $c6, $c6, $ea, $ea, $c6, $c6, $ca, $a6, $85, $20, $44
    db $20, $40, $61, $a6, $a6, $c6, $e6, $ee, $e6, $e6, $c6, $a6, $81, $85, $65, $44
    db $20, $60, $61, $a6, $a6, $a2, $ea, $ea, $ea, $ea, $c6, $a6, $a5, $85, $85, $1
    db $20, $40, $61, $a6, $c6, $c6, $a2, $c6, $c6, $e6, $a2, $a5, $61, $61, $41, $1
    db $1, $20, $65, $a5, $a6, $ea, $c6, $e6, $e6, $ca, $ca, $a5, $85, $65, $20, $1
    db $00, $20, $40, $85, $86, $a6, $a1, $a2, $a2, $a1, $81, $81, $61, $41, $44, $00
    db $00, $1, $44, $41, $a9, $85, $85, $aa, $86, $ca, $61, $89, $65, $20, $1, $00
    db $00, $00, $20, $20, $40, $61, $61, $61, $85, $61, $61, $60, $45, $24, $00, $00
    db $00, $00, $00, $1, $20, $45, $45, $45, $40, $20, $40, $44, $1, $00, $00, $00
    db $00, $00, $00, $00, $00, $1, $44, $20, $20, $20, $1, $00, $00, $00, $00, $00

    ; 16x16 cartesian to isometric coordinate lookup table
    ; Y in high byte, X in low byte
    isoCoordTbl
    dw $2078, $2480, $2888, $2C90, $3098, $34A0, $38A8, $3CB0, $40B8, $44C0, $48C8, $4CD0, $50D8, $54E0, $58E8, $5CF0
    dw $2470, $2878, $2C80, $3088, $3490, $3898, $3CA0, $40A8, $44B0, $48B8, $4CC0, $50C8, $54D0, $58D8, $5CE0, $60E8
    dw $2868, $2C70, $3078, $3480, $3888, $3C90, $4098, $44A0, $48A8, $4CB0, $50B8, $54C0, $58C8, $5CD0, $60D8, $64E0
    dw $2C60, $3068, $3470, $3878, $3C80, $4088, $4490, $4898, $4CA0, $50A8, $54B0, $58B8, $5CC0, $60C8, $64D0, $68D8
    dw $3058, $3460, $3868, $3C70, $4078, $4480, $4888, $4C90, $5098, $54A0, $58A8, $5CB0, $60B8, $64C0, $68C8, $6CD0
    dw $3450, $3858, $3C60, $4068, $4470, $4878, $4C80, $5088, $5490, $5898, $5CA0, $60A8, $64B0, $68B8, $6CC0, $70C8
    dw $3848, $3C50, $4058, $4460, $4868, $4C70, $5078, $5480, $5888, $5C90, $6098, $64A0, $68A8, $6CB0, $70B8, $74C0
    dw $3C40, $4048, $4450, $4858, $4C60, $5068, $5470, $5878, $5C80, $6088, $6490, $6898, $6CA0, $70A8, $74B0, $78B8
    dw $4038, $4440, $4848, $4C50, $5058, $5460, $5868, $5C70, $6078, $6480, $6888, $6C90, $7098, $74A0, $78A8, $7CB0
    dw $4430, $4838, $4C40, $5048, $5450, $5858, $5C60, $6068, $6470, $6878, $6C80, $7088, $7490, $7898, $7CA0, $80A8
    dw $4828, $4C30, $5038, $5440, $5848, $5C50, $6058, $6460, $6868, $6C70, $7078, $7480, $7888, $7C90, $8098, $84A0
    dw $4C20, $5028, $5430, $5838, $5C40, $6048, $6450, $6858, $6C60, $7068, $7470, $7878, $7C80, $8088, $8490, $8898
    dw $5018, $5420, $5828, $5C30, $6038, $6440, $6848, $6C50, $7058, $7460, $7868, $7C70, $8078, $8480, $8888, $8C90
    dw $5410, $5818, $5C20, $6028, $6430, $6838, $6C40, $7048, $7450, $7858, $7C60, $8068, $8470, $8878, $8C80, $9088
    dw $5808, $5C10, $6018, $6420, $6828, $6C30, $7038, $7440, $7848, $7C50, $8058, $8460, $8868, $8C70, $9078, $9480
    dw $5C00, $6008, $6410, $6818, $6C20, $7028, $7430, $7838, $7C40, $8048, $8450, $8858, $8C60, $9068, $9470, $9878

    ;------------------------------------------------------------------------------
    ; Stack reservation
    STACK_SIZE equ 200

    stack_bottom:
    defs STACK_SIZE * 2
    stack_top:
    defw 0

    ;------------------------------------------------------------------------------
    ; Output configuration
    SAVENEX OPEN "isodemo.nex", main, stack_top
    SAVENEX CORE 2,0,0
    SAVENEX CFG 7,0,0,0
    SAVENEX AUTO
    SAVENEX CLOSE