It's a nice idea, but what about this? Willy goes back in time to the land of the dinosaurs, with nothing but his fists and a cool pair of sunglasses...
The new ZXDB database update will be applied today at 1600BST. The site goes down whilst this happens, and normally takes 30 minutes.
how about a more modern miner willy sprite?
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
actually… no, don't give him a gun. one of the games i am planning to do for a long time is a platformer. with guns and grenades. and it will even start in the central cavern. of course, it won't be such straightforward, there will be a twist you've never seen in spectrum games before. no, really! ;-)
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
- gabriele amore
- Microbot
- Posts: 183
- Joined: Thu Apr 16, 2020 11:28 pm
- Location: Palermo
Re: how about a more modern miner willy sprite?
looks lovely!ParadigmShifter wrote: ↑Sun Jun 23, 2024 7:40 pm
Quick and hacky implementation of collision map... so Willy can pass over objects in the collision map and it redraws them instead of erasing.
Get my AY games here https://www.dropbox.com/sh/tfo83j5lzwmh ... Kkk7a?dl=0
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
Looks better now I have unhacked it since the quick hack was make anything you moved over a spiky bush
So now it has a tile table (which will be length 15 max) to do a lookup of collision map to tile graphics.
Code is totally unoptimised and the level drawing and contents of the collision map are hardcoded.
Collision map:
0: blank
1: wall
2: platform
3: bush
4-15: unused atm
Each level can have a unique tilemap of course. I may also allow any number of walls/platforms, I think my last version only allowed 1 tile type for a wall.
EDIT: Code as is will handle all tile types moving over them... but conveyor belts need a special case since the graphics have to change each frame and it needs to draw the conveyor belt on the correct animation frame when redrawing if Willy is standing in front of them. Luckily conveyor belts will have a bit set so it is quick to check and call a special drawing function just for them.
EDIT2: Crumbly platforms also need special case code. I don't intend to use a backbuffer this time so they need a special drawing function too.
Code also needs modifying to redraw more cells once Willy can be drawn at an arbitrary Y position, since then it may span 2x3 cells instead of 2x2, need to check them all when erasing.
That's probably enough coding (at least complicated coding) for today, since beer o'clock has arrived. I'll probably add your new sprite set while drinking my beers.
So now it has a tile table (which will be length 15 max) to do a lookup of collision map to tile graphics.
Code is totally unoptimised and the level drawing and contents of the collision map are hardcoded.
Collision map:
0: blank
1: wall
2: platform
3: bush
4-15: unused atm
Each level can have a unique tilemap of course. I may also allow any number of walls/platforms, I think my last version only allowed 1 tile type for a wall.
EDIT: Code as is will handle all tile types moving over them... but conveyor belts need a special case since the graphics have to change each frame and it needs to draw the conveyor belt on the correct animation frame when redrawing if Willy is standing in front of them. Luckily conveyor belts will have a bit set so it is quick to check and call a special drawing function just for them.
EDIT2: Crumbly platforms also need special case code. I don't intend to use a backbuffer this time so they need a special drawing function too.
Code also needs modifying to redraw more cells once Willy can be drawn at an arbitrary Y position, since then it may span 2x3 cells instead of 2x2, need to check them all when erasing.
Code: Select all
ORGADDR EQU #8000
; sjasmplus.exe --sym=out.sym --syntax=f --raw=out.bin modernmm.asm
ORG ORGADDR
DISPLAY "ORIGIN ", /A, ORGADDR
SCRBASE EQU #4000
ATTRIBS EQU #5800
TIMING EQU 1
MACRO DWXYTOSCRADDR _x_, _y_
dw SCRBASE + (((_y_)|((_y_&#C0)>>3))<<8)|((_x_F)|((_y_&)<<2))
ENDM
MACRO SETBORDER bdr
ld a, bdr
out (#FE), a
ENDM
MACRO COLLMAPTOTILE
exx
dec a ; tile map is collision map data - 1
rlca ; *2
ld h, level_tiles/256
ld l, a
ld a, (hl)
inc l
ex af, af'
ld a, (hl)
exx
ld d, a
ex af, af'
ld e, a
ENDM
main:
call draw_level
mainloop:
IF TIMING
SETBORDER 7
ENDIF
halt
IF TIMING
SETBORDER 1
ENDIF
ld hl, willy_oldpos
ld a, (hl)
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
and ~7
rrca
rrca
rrca
ld b, a
call erase_willy
IF TIMING
SETBORDER 2
ENDIF
ld hl, willy_xpos
ld a, (hl)
ld d, a
and 7
rrca
rrca
rrca
ld e, a
ld a, d
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
and ~7
rrca
rrca
rrca
ld b, a
ld d, gfx_willy0/256
ld a, (willy_facing)
dec a
jr z, .dontadjustdbottomsprite
inc d
.dontadjustdbottomsprite
call sprite16x16ra
IF TIMING
SETBORDER 1
ENDIF
ld hl, willy_oldpos
ld a, (hl)
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
sub 32
and ~7
rrca
rrca
rrca
ld b, a
call erase_willy
IF TIMING
SETBORDER 2
ENDIF
ld hl, willy_xpos
ld a, (hl)
ld d, a
and 7
rrca
rrca
rrca
ld e, a
ld a, d
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
sub 32
and ~7
rrca
rrca
rrca
ld b, a
ld d, gfx_gwilly0/256
ld a, (willy_facing)
dec a
jr z, .dontadjustdtopsprite
inc d
.dontadjustdtopsprite
call sprite16x16ra
IF TIMING
SETBORDER 4
ENDIF
ld de, willy_oldpos
ld hl, willy_xpos
ldi
ldi
call read_keyboard
ld hl, willy_xpos
ld a, (hl)
add c
cp 8
jr c, .doneupatepos
cp 240
jr nc, .doneupatepos
ld (hl), a
.doneupatepos
jp mainloop
ret
; B: row (in character cells, so [0-23])
; C: column
sprite16x16ra:
ld a, b
add b ; A = B*2
ld h, tbl_rows/256 ; high byte of screen address lookup table. Aligned 256 so low byte will be just row*2
ld l, a ; index into table
ld a, (hl) ; low byte of screen address
inc l ; point HL to high byte of screen address
ld h, (hl) ; read high byte of screen address
add c ; add on column to low byte of screen address
ld l, a ; and write it back. HL now holds correct screen address
; so we now know the address...
; HL: screen address
sprite16x16raKnowAddr:
REPT 8
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
or (hl)
ld (hl), a
inc l
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
or (hl)
ld (hl), a
inc h ; next row of pixels down
dec l
ENDR
; we could split this into 2 routines depending on whether we straddle a screen third boundary or not
; which we could work out before calling
; then we could remove the jr c
ld a, #20
add l
ld l, a
jr c, .ok
ld a, h
sub #8
ld h, a
.ok
REPT 7
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
or (hl)
ld (hl), a
inc l
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
or (hl)
ld (hl), a
inc h ; next row of pixels down
dec l
ENDR
; last row, don't need to increment gfx data pointer or screen row
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
or (hl)
ld (hl), a
inc l
ld a, (de)
or (hl)
ld (hl), a
ret
; B: row
; C: column
erase_willy:
; I think there's a much faster way of doing this involving rrca
ld de, collision_map
ld l, b
ld h, e ; E = 0
REPT 5
add hl, hl ; *2, ... , *32
ENDR
add hl, de
ld a, l
or c ; add on column
ld l, a
; hl now has collision map address
push hl
ld a, (hl)
or a
jr nz, .tlnotblank
call erase8x8a
jp .topright
.tlnotblank
COLLMAPTOTILE
call sprite8x8a
.topright
pop hl
inc l ; look at top right cell
inc c ; which is one column over
push hl
ld a, (hl)
or a
jr nz, .trnotblank
call erase8x8a
jp .botright
.trnotblank
COLLMAPTOTILE
call sprite8x8a
.botright
pop hl
ld de, 32
add hl, de
inc b ; move 1 cell down
push hl
ld a, (hl)
or a
jr nz, .brnotblank
call erase8x8a
jp .botleft
.brnotblank
COLLMAPTOTILE
call sprite8x8a
.botleft
pop hl
dec l ; look at bottom left cell
dec c ; which is one column left
ld a, (hl)
or a
jr nz, .blnotblank
call erase8x8a
ret
.blnotblank
COLLMAPTOTILE
call sprite8x8a
ret
; B: row (in character cells, so [0-23])
; C: column
erase8x8a:
ld a, b
add b ; A = B*2
ld h, tbl_rows/256 ; high byte of screen address lookup table. Aligned 256 so low byte will be just row*2
ld l, a ; index into table
ld a, (hl) ; low byte of screen address
inc l ; point HL to high byte of screen address
ld h, (hl) ; read high byte of screen address
add c ; add on column to low byte of screen address
ld l, a ; and write it back. HL now holds correct screen address
; so we now know the address...
; HL: screen address
erase8x8aKnowAddr:
xor a
REPT 7
ld (hl), a
inc h ; next row of pixels down
ENDR
ld (hl), a
ret
; B: row (in character cells, so [0-23])
; C: column
erase16x16ra:
ld a, b
add b ; A = B*2
ld h, tbl_rows/256 ; high byte of screen address lookup table. Aligned 256 so low byte will be just row*2
ld l, a ; index into table
ld a, (hl) ; low byte of screen address
inc l ; point HL to high byte of screen address
ld h, (hl) ; read high byte of screen address
add c ; add on column to low byte of screen address
ld l, a ; and write it back. HL now holds correct screen address
; so we now know the address...
; HL: screen address
erase16x16raKnowAddr:
xor a
REPT 8
ld (hl), a
inc l
ld (hl), a
inc h ; next row of pixels down
dec l
ENDR
; we could split this into 2 routines depending on whether we straddle a screen third boundary or not
; which we could work out before calling
; then we could remove the jr c
ld a, #20
add l
ld l, a
jr c, .ok
ld a, h
sub #8
ld h, a
.ok
xor a
REPT 7
ld (hl), a
inc l
ld (hl), a
inc h ; next row of pixels down
dec l
ENDR
ld (hl), a
inc l
ld (hl), a
ret
; B: row (in character cells, so [0-23])
; C: column
; DE: 8 rows 8x1 sprite data (8 byte aligned)
sprite8x8a:
ld a, b
add b ; A = B*2
ld h, tbl_rows/256 ; high byte of screen address lookup table. Aligned 256 so low byte will be just row*2
ld l, a ; index into table
ld a, (hl) ; low byte of screen address
inc l ; point HL to high byte of screen address
ld h, (hl) ; read high byte of screen address
add c ; add on column to low byte of screen address
ld l, a ; and write it back. HL now holds correct screen address
; so we now know the address...
; HL: screen address
; DE: 8 rows 8x1 sprite data (8 byte aligned)
sprite8x8aKnowAddr:
REPT 7
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
ld (hl), a
inc h ; next row of pixels down
ENDR
; last row, don't need to increment gfx data pointer or screen row
ld a, (de)
ld (hl), a
ret
draw_level:
SETBORDER 2
ld a, 7 ; white ink, non bright
call cls
ld b, 30
.floorloop
push bc
ld c, b
ld b, 15
ld de, gfx_platform0
call sprite8x8a
pop bc
ld hl, ATTRIBS+15*32
ld a, l
add b
ld l, a
ld (hl), 64+2 ; bright red
push bc
ld c, b
ld b, 11
ld de, gfx_platform0
call sprite8x8a
pop bc
ld hl, ATTRIBS+11*32
ld a, l
add b
ld l, a
ld (hl), 64+2 ; bright red
djnz .floorloop
ld b, 16
.wallloop
push bc
ld c, 0
dec b
ld de, gfx_wall0
call sprite8x8a
pop bc
ld l, b
dec l
ld h, 0
ld de, ATTRIBS
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, de
ld (hl), 64+(2*8)+6 ; bright paper, yellow ink
push bc
ld c, 31
dec b
ld de, gfx_wall0
call sprite8x8a
pop bc
ld l, b
dec l
ld h, 0
ld de, ATTRIBS+31
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, de
ld (hl), 64+(2*8)+6 ; bright paper, yellow ink
djnz .wallloop
; add a bush at row 14, column 21
ld bc, (14*256)+21
ld de, gfx_spiky0
call sprite8x8a
ld hl, ATTRIBS+(14*32)+21
ld (hl), 64+4 ; bright green
; draw some ledges too
ld b, 22
.ledgeloop
push bc
ld a, b
add 4
ld c, a
ld b, 13
ld de, gfx_platform0
call sprite8x8a
pop bc
ld hl, ATTRIBS+4+13*32
ld a, l
add b
ld l, a
ld (hl), 64+2 ; bright red
push bc
ld a, b
add 4
ld c, a
ld b, 9
ld de, gfx_platform0
call sprite8x8a
pop bc
ld hl, ATTRIBS+4+9*32
ld a, l
add b
ld l, a
ld (hl), 64+2 ; bright red
djnz .ledgeloop
ret
; A -> attrib to set when clearing screen
cls:
; set attribs
ld hl, #5800+767
ld de, #5800+766
ld bc, 768
ld (hl), a
lddr
; clear pixels
ld (hl), b ; since B=0 here
ld bc, 6144-1
lddr
ret
; at exit, C contains 1 if we pressed right and -1 if we pressed left
read_keyboard:
; Read these ports to scan keyboard
; bit N (0-based) is clear if the key is being pressed
; #FE - SHIFT, Z, X, C, & V
; #FD - A, S, D, F, & G
; #FB - Q, W, E, R, & T
; #F7 - 1, 2, 3, 4, & 5
; #EF - 0, 9, 8, 7, & 6
; #DF - P, O, I, U, & Y
; #BF - ENTER, L, K, J, & H
; #7F - SPACE, FULL-STOP, M, N, & B
; ld a, port
; in a, (#FE)
; to do the read of the port
ld bc, 0
; are we pressing W?
ld a, #FB
in a, (#FE)
bit 1, a
jr nz, .notpressingW
inc c
.notpressingW
; are we pressing Q?
bit 0, a
jr nz, .notpressingQ
dec c
.notpressingQ
ld a, c
or a
ret z ; not moving
ld hl, willy_facing
ld (hl), c
ret
ALIGN 256
gfx_willy0
dg .....##......... ;0
dg ..##.##......... ;1
dg .##............. ;2
dg .#..#........... ;3
dg ..###.#......... ;4
dg ...###.......... ;5
dg ................ ;6
dg .##.#.#......... ;7
dg #...###......... ;8
dg #....###........ ;9
dg .....###........ ;10
dg ###.###......... ;11
dg ##.#####........ ;12
dg ...##.##........ ;13
dg ................ ;14
dg ...###.#........ ;15
gfx_willy1
dg ......##........ ;0
dg ...##.##........ ;1
dg ..##............ ;2
dg ..#..#.......... ;3
dg ...###.#........ ;4
dg ....###......... ;5
dg ..##............ ;6
dg .#...#.#........ ;7
dg .....###........ ;8
dg .#....###....... ;9
dg ####..###....... ;10
dg ###..###........ ;11
dg ...###.##....... ;12
dg ...##........... ;13
dg .......###...... ;14
dg ...###.......... ;15
gfx_willy2
dg .......##....... ;0
dg ....##.##....... ;1
dg ...##........... ;2
dg ...#..#......... ;3
dg ....###.#....... ;4
dg .....###........ ;5
dg ...##........... ;6
dg ..#...#.#....... ;7
dg ..#...###....... ;8
dg ...###.###...... ;9
dg ..###..###...... ;10
dg ...#..###....... ;11
dg ....###......... ;12
dg ....##..###..... ;13
dg ...#............ ;14
dg ...##........... ;15
gfx_willy3
dg ........##...... ;0
dg .....##.##...... ;1
dg ....##.......... ;2
dg ....#..#........ ;3
dg .....###.#...... ;4
dg ......###....... ;5
dg .....#.......... ;6
dg ....#...#....... ;7
dg ....#.#..#...... ;8
dg .....###.##..... ;9
dg ......##.##..... ;10
dg ........##...... ;11
dg ....#.##..#..... ;12
dg ....#.#..###.... ;13
dg ....#........... ;14
dg ................ ;15
gfx_willy4
dg .........##..... ;0
dg ......##.##..... ;1
dg .....##......... ;2
dg .....#..#....... ;3
dg ......###.#..... ;4
dg .......###...... ;5
dg ......#......... ;6
dg .....#.......... ;7
dg .....#....#..... ;8
dg ......#..####... ;9
dg .......#..###... ;10
dg .....#.......... ;11
dg .....#.##....... ;12
dg .....#....###... ;13
dg ................ ;14
dg ................ ;15
gfx_willy5
dg ................ ;0
dg ..........##.... ;1
dg .......##.##.... ;2
dg ......##........ ;3
dg ......#..#...... ;4
dg .......###.#.... ;5
dg ........###..... ;6
dg .......#........ ;7
dg ......#......... ;8
dg ......#....#.... ;9
dg .......##.####.. ;10
dg .....#...#.###.. ;11
dg .....#.##....... ;12
dg .....#..####.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_willy6
dg ................ ;0
dg ...........##... ;1
dg ........##.##... ;2
dg .......##....... ;3
dg .......#..#..... ;4
dg ........###.#... ;5
dg .........###.... ;6
dg ........#....... ;7
dg .......#........ ;8
dg .......#..#..... ;9
dg ........#.##.... ;10
dg .......#..##.... ;11
dg ......##.#..#... ;12
dg ......#...##.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_willy7
dg .............##. ;0
dg ..........##.##. ;1
dg .........##..... ;2
dg .........#..#... ;3
dg ..........###.#. ;4
dg ...........###.. ;5
dg ................ ;6
dg .........#..#... ;7
dg ........#....#.. ;8
dg ........#.#..##. ;9
dg .........###.##. ;10
dg ..........##.##. ;11
dg ............###. ;12
dg ...........###.. ;13
dg ................ ;14
dg ...........###.. ;15
gfx_willy8
dg .##............. ;0
dg .##.##.......... ;1
dg .....##......... ;2
dg ...#..#......... ;3
dg .#.###.......... ;4
dg ..###........... ;5
dg ................ ;6
dg ...#..#......... ;7
dg ..#....#........ ;8
dg .##....#........ ;9
dg .##...#......... ;10
dg .##..###........ ;11
dg .###.##......... ;12
dg ..###........... ;13
dg ................ ;14
dg ..###........... ;15
gfx_willy9
dg ................ ;0
dg ...##........... ;1
dg ...##.##........ ;2
dg .......##....... ;3
dg .....#..#....... ;4
dg ...#.###........ ;5
dg ....###......... ;6
dg .......#........ ;7
dg ........#....... ;8
dg .....#..#....... ;9
dg ....##.#........ ;10
dg ....##..#....... ;11
dg ...#..#.##...... ;12
dg ....##...#...... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_willy10
dg ................ ;0
dg ....##.......... ;1
dg ....##.##....... ;2
dg ........##...... ;3
dg ......#..#...... ;4
dg ....#.###....... ;5
dg .....###........ ;6
dg ........#....... ;7
dg .........#...... ;8
dg ....#....#...... ;9
dg ..####.##....... ;10
dg ..###.#...#..... ;11
dg .......##.#..... ;12
dg ....####..#..... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_willy11
dg .....##......... ;0
dg .....##.##...... ;1
dg .........##..... ;2
dg .......#..#..... ;3
dg .....#.###...... ;4
dg ......###....... ;5
dg .........#...... ;6
dg ..........#..... ;7
dg .....#....#..... ;8
dg ...####..#...... ;9
dg ...###..#....... ;10
dg ..........#..... ;11
dg .......##.#..... ;12
dg ...###....#..... ;13
dg ................ ;14
dg ................ ;15
gfx_willy12
dg ......##........ ;0
dg ......##.##..... ;1
dg ..........##.... ;2
dg ........#..#.... ;3
dg ......#.###..... ;4
dg .......###...... ;5
dg ..........#..... ;6
dg .......#...#.... ;7
dg ......#..#.#.... ;8
dg .....##.###..... ;9
dg .....##.##...... ;10
dg ......##........ ;11
dg .....#..##.#.... ;12
dg ....###..#.#.... ;13
dg ...........#.... ;14
dg ................ ;15
gfx_willy13
dg .......##....... ;0
dg .......##.##.... ;1
dg ...........##... ;2
dg .........#..#... ;3
dg .......#.###.... ;4
dg ........###..... ;5
dg ...........##... ;6
dg .......#.#...#.. ;7
dg .......###...#.. ;8
dg ......###.###... ;9
dg ......###..###.. ;10
dg .......###..#... ;11
dg .........###.... ;12
dg .....###..##.... ;13
dg ............#... ;14
dg ...........##... ;15
gfx_willy14
dg ........##...... ;0
dg ........##.##... ;1
dg ............##.. ;2
dg ..........#..#.. ;3
dg ........#.###... ;4
dg .........###.... ;5
dg ............##.. ;6
dg ........#.#...#. ;7
dg ........###..... ;8
dg .......###....#. ;9
dg .......###..#### ;10
dg ........###..### ;11
dg .......##.###... ;12
dg ...........##... ;13
dg ......###....... ;14
dg ..........###... ;15
gfx_willy15
dg .........##..... ;0
dg .........##.##.. ;1
dg .............##. ;2
dg ...........#..#. ;3
dg .........#.###.. ;4
dg ..........###... ;5
dg ................ ;6
dg .........#.#.##. ;7
dg .........###...# ;8
dg ........###....# ;9
dg ........###..... ;10
dg .........###.### ;11
dg ........#####.## ;12
dg ........##.##... ;13
dg ................ ;14
dg ........#.###... ;15
gfx_gwilly0
dg .....##......... ;0
dg ..##.##......... ;1
dg .##............. ;2
dg .#..#........... ;3
dg ..###.#......... ;4
dg ...###.......... ;5
dg ................ ;6
dg .##.#.#......... ;7
dg #...###......... ;8
dg #....###........ ;9
dg .....###........ ;10
dg ###.###......... ;11
dg ##.#####........ ;12
dg ...##.##........ ;13
dg ................ ;14
dg ...###.#........ ;15
gfx_gwilly1
dg ......##........ ;0
dg ...##.##........ ;1
dg ..##............ ;2
dg ..#..#.......... ;3
dg ...###.#........ ;4
dg ....###......... ;5
dg ..##............ ;6
dg .#...#.#........ ;7
dg .....###........ ;8
dg .#....###....... ;9
dg ####..###....... ;10
dg ###..###........ ;11
dg ...###.##....... ;12
dg ...##........... ;13
dg .......###...... ;14
dg ...###.......... ;15
gfx_gwilly2
dg .......##....... ;0
dg ....##.##....... ;1
dg ...##........... ;2
dg ...#..#......... ;3
dg ....###.#....... ;4
dg .....###........ ;5
dg ...##........... ;6
dg ..#...#.#....... ;7
dg ..#...###....... ;8
dg ...###.###...... ;9
dg ..###..###...... ;10
dg ...#..###....... ;11
dg ....###......... ;12
dg ....##..###..... ;13
dg ...#............ ;14
dg ...##........... ;15
gfx_gwilly3
dg ................ ;0
dg ........##...... ;1
dg .....##.##...... ;2
dg ....##.......... ;3
dg ....#..#........ ;4
dg .....###.#...... ;5
dg ......###....... ;6
dg .....#.......... ;7
dg ....#...#....... ;8
dg ....#.#..#...... ;9
dg .....###.##..... ;10
dg ......##.##..... ;11
dg ........##...... ;12
dg ....#.##..#..... ;13
dg ....#.#..###.... ;14
dg ....#........... ;15
gfx_gwilly4
dg ................ ;0
dg ................ ;1
dg .........##..... ;2
dg ......##.##..... ;3
dg .....##......... ;4
dg .....#..#....... ;5
dg ......###.#..... ;6
dg .......###...... ;7
dg ......#......... ;8
dg .....#.......... ;9
dg .....#....#..... ;10
dg ......#..####... ;11
dg .......#..###... ;12
dg .....#.......... ;13
dg .....#.##....... ;14
dg .....#....###... ;15
gfx_gwilly5
dg ................ ;0
dg ..........##.... ;1
dg .......##.##.... ;2
dg ......##........ ;3
dg ......#..#...... ;4
dg .......###.#.... ;5
dg ........###..... ;6
dg .......#........ ;7
dg ......#......... ;8
dg ......#....#.... ;9
dg .......##.####.. ;10
dg .....#...#.###.. ;11
dg .....#.##....... ;12
dg .....#..####.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_gwilly6
dg ................ ;0
dg ...........##... ;1
dg ........##.##... ;2
dg .......##....... ;3
dg .......#..#..... ;4
dg ........###.#... ;5
dg .........###.... ;6
dg ........#....... ;7
dg .......#........ ;8
dg .......#..#..... ;9
dg ........#.##.... ;10
dg .......#..##.... ;11
dg ......##.#..#... ;12
dg ......#...##.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_gwilly7
dg .............##. ;0
dg ..........##.##. ;1
dg .........##..... ;2
dg .........#..#... ;3
dg ..........###.#. ;4
dg ...........###.. ;5
dg ................ ;6
dg .........#..#... ;7
dg ........#....#.. ;8
dg ........#.#..##. ;9
dg .........###.##. ;10
dg ..........##.##. ;11
dg ............###. ;12
dg ...........###.. ;13
dg ................ ;14
dg ...........###.. ;15
gfx_gwilly8
dg .##............. ;0
dg .##.##.......... ;1
dg .....##......... ;2
dg ...#..#......... ;3
dg .#.###.......... ;4
dg ..###........... ;5
dg ................ ;6
dg ...#..#......... ;7
dg ..#....#........ ;8
dg .##....#........ ;9
dg .##...#......... ;10
dg .##..###........ ;11
dg .###.##......... ;12
dg ..###........... ;13
dg ................ ;14
dg ..###........... ;15
gfx_gwilly9
dg ................ ;0
dg ...##........... ;1
dg ...##.##........ ;2
dg .......##....... ;3
dg .....#..#....... ;4
dg ...#.###........ ;5
dg ....###......... ;6
dg .......#........ ;7
dg ........#....... ;8
dg .....#..#....... ;9
dg ....##.#........ ;10
dg ....##..#....... ;11
dg ...#..#.##...... ;12
dg ....##...#...... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_gwilly10
dg ................ ;0
dg ....##.......... ;1
dg ....##.##....... ;2
dg ........##...... ;3
dg ......#..#...... ;4
dg ....#.###....... ;5
dg .....###........ ;6
dg ........#....... ;7
dg .........#...... ;8
dg ....#....#...... ;9
dg ..####.##....... ;10
dg ..###.#...#..... ;11
dg .......##.#..... ;12
dg ....####..#..... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_gwilly11
dg ................ ;0
dg ................ ;1
dg .....##......... ;2
dg .....##.##...... ;3
dg .........##..... ;4
dg .......#..#..... ;5
dg .....#.###...... ;6
dg ......###....... ;7
dg .........#...... ;8
dg ..........#..... ;9
dg .....#....#..... ;10
dg ...####..#...... ;11
dg ...###..#....... ;12
dg ..........#..... ;13
dg .......##.#..... ;14
dg ...###....#..... ;15
gfx_gwilly12
dg ................ ;0
dg ......##........ ;1
dg ......##.##..... ;2
dg ..........##.... ;3
dg ........#..#.... ;4
dg ......#.###..... ;5
dg .......###...... ;6
dg ..........#..... ;7
dg .......#...#.... ;8
dg ......#..#.#.... ;9
dg .....##.###..... ;10
dg .....##.##...... ;11
dg ......##........ ;12
dg .....#..##.#.... ;13
dg ....###..#.#.... ;14
dg ...........#.... ;15
gfx_gwilly13
dg .......##....... ;0
dg .......##.##.... ;1
dg ...........##... ;2
dg .........#..#... ;3
dg .......#.###.... ;4
dg ........###..... ;5
dg ...........##... ;6
dg .......#.#...#.. ;7
dg .......###...#.. ;8
dg ......###.###... ;9
dg ......###..###.. ;10
dg .......###..#... ;11
dg .........###.... ;12
dg .....###..##.... ;13
dg ............#... ;14
dg ...........##... ;15
gfx_gwilly14
dg ........##...... ;0
dg ........##.##... ;1
dg ............##.. ;2
dg ..........#..#.. ;3
dg ........#.###... ;4
dg .........###.... ;5
dg ............##.. ;6
dg ........#.#...#. ;7
dg ........###..... ;8
dg .......###....#. ;9
dg .......###..#### ;10
dg ........###..### ;11
dg .......##.###... ;12
dg ...........##... ;13
dg ......###....... ;14
dg ..........###... ;15
gfx_gwilly15
dg .........##..... ;0
dg .........##.##.. ;1
dg .............##. ;2
dg ...........#..#. ;3
dg .........#.###.. ;4
dg ..........###... ;5
dg ................ ;6
dg .........#.#.##. ;7
dg .........###...# ;8
dg ........###....# ;9
dg ........###..... ;10
dg .........###.### ;11
dg ........#####.## ;12
dg ........##.##... ;13
dg ................ ;14
dg ........#.###... ;15
ALIGN 256
collision_map:
REPT 9
db 1
REPT 30
db 0
ENDR
db 1
ENDR
db 1
REPT 4
db 0
ENDR
REPT 22
db 2
ENDR
REPT 4
db 0
ENDR
db 1
db 1
REPT 30
db 0
ENDR
db 1
db 1
REPT 30
db 2
ENDR
db 1
db 1
REPT 30
db 0
ENDR
db 1
db 1
REPT 4
db 0
ENDR
REPT 22
db 2
ENDR
REPT 4
db 0
ENDR
db 1
db 1
REPT 20
db 0
ENDR
db 3
REPT 9
db 0
ENDR
db 1
db 1
REPT 30
db 2
ENDR
db 1
ASSERT $ - collision_map == 512
gfx_8x8page:
gfx_platform0 ; Spectrum platform sprite1
dg ######## ; ff
dg ######## ; ff
dg ##.##.## ; db
dg ###.###. ; ee
dg ##...#.# ; c5
dg .#...... ; 40
dg ........ ; 00
dg ........ ; 00
gfx_wall0 ; Spectrum wall sprite2
dg ..#...#. ; 22
dg ######## ; ff
dg #...#... ; 88
dg ######## ; ff
dg ..#...#. ; 22
dg ######## ; ff
dg #...#... ; 88
dg ######## ; ff
gfx_spiky0 ; Spectrum bush sprite3
dg .#...#.. ; 44
dg ..#.#... ; 28
dg #..#.#.. ; 94
dg .#.#...# ; 51
dg ..##.#.# ; 35
dg ##.#.##. ; d6
dg .#.##... ; 58
dg ...#.... ; 10
ALIGN 256
tbl_rows
REPT 24, row
DWXYTOSCRADDR 0, row*8
ENDR
ALIGN 2
willy_xpos db 8
willy_ypos db 104
willy_oldpos db 8, 104
willy_facing db 1 ; facing. 1 for right, -1 for left
ALIGN 256 ; align this for faster access
level_tiles:
dw gfx_wall0 ; collision map 1
dw gfx_platform0 ; collision map 2
dw gfx_spiky0 ; collision map 3
IF 0
dg ................ ;0
dg ................ ;1
dg ................ ;2
dg ................ ;3
dg ................ ;4
dg ................ ;5
dg ................ ;6
dg ................ ;7
dg ................ ;8
dg ................ ;9
dg ................ ;10
dg ................ ;11
dg ................ ;12
dg ................ ;13
dg ................ ;14
dg ................ ;15
ENDIF
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
These are the tile graphics from original MM I have used to far
So if anyone thinks they can do better by all means do so.
Because there are more allowed tiles (I think there were 8 or 9 tile types per level in my previous version?) it is possible to make platforms out of more than 1 tile, so you could add variety, make them repeat over 2 cells instead of 2, have a beginning/middle/end graphic, etc. As long as you don't go over the 15 tile types (type 0 is always blank tile) on any given level.
EDIT: Also the level format will store the colour for each tile type (but the same tile with 2 different colourings counts as 2 different tiles).
Code: Select all
gfx_platform0 ; Spectrum platform sprite1
dg ######## ; ff
dg ######## ; ff
dg ##.##.## ; db
dg ###.###. ; ee
dg ##...#.# ; c5
dg .#...... ; 40
dg ........ ; 00
dg ........ ; 00
gfx_wall0 ; Spectrum wall sprite2
dg ..#...#. ; 22
dg ######## ; ff
dg #...#... ; 88
dg ######## ; ff
dg ..#...#. ; 22
dg ######## ; ff
dg #...#... ; 88
dg ######## ; ff
gfx_spiky0 ; Spectrum bush sprite3
dg .#...#.. ; 44
dg ..#.#... ; 28
dg #..#.#.. ; 94
dg .#.#...# ; 51
dg ..##.#.# ; 35
dg ##.#.##. ; d6
dg .#.##... ; 58
dg ...#.... ; 10
Because there are more allowed tiles (I think there were 8 or 9 tile types per level in my previous version?) it is possible to make platforms out of more than 1 tile, so you could add variety, make them repeat over 2 cells instead of 2, have a beginning/middle/end graphic, etc. As long as you don't go over the 15 tile types (type 0 is always blank tile) on any given level.
EDIT: Also the level format will store the colour for each tile type (but the same tile with 2 different colourings counts as 2 different tiles).
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
Did you intend to have the head position of the last sprite advance by 2 pixels instead of 1 there? I can always shift it if you didn't.gabriele amore wrote: ↑Sun Jun 23, 2024 2:49 pm please don't hate me but i thoght the white shirt looked better
also made a small improvement to the connection between last and first frame (first frame being also the standing willie)
EDIT: Also on the sixth frame the lamp is not in the usual position suggesting hat is tilted upwards? Dunno if that was intended either. I'm going with the graphics you did for now anyway.
- gabriele amore
- Microbot
- Posts: 183
- Joined: Thu Apr 16, 2020 11:28 pm
- Location: Palermo
Re: how about a more modern miner willy sprite?
Yes on both countsParadigmShifter wrote: ↑Sun Jun 23, 2024 9:38 pm Did you intend to have the head position of the last sprite advance by 2 pixels instead of 1 there? I can always shift it if you didn't.
EDIT: Also on the sixth frame the lamp is not in the usual position suggesting hat is tilted upwards? Dunno if that was intended either. I'm going with the graphics you did for now anyway.
Get my AY games here https://www.dropbox.com/sh/tfo83j5lzwmh ... Kkk7a?dl=0
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
New graphics done then, again I have gone for the topmost Willy is always on the ground, one below it has midair frames.
Code dump, also speeded up the lookup collision map -> tile gfx, since I wasn't using DE register I could remove a lot of exx faffing.
So fairly productive day that was (day 2).
Pretty confident I will be able to update up to 4 guardians per frame and still run at 50fps. Max guardians is 8 but I only need to update half of them per frame since usual update speed is every other frame now Willy has 8 frames of animation. I may be able to update all 8 if I am clever about the order I redraw things.
Code dump, also speeded up the lookup collision map -> tile gfx, since I wasn't using DE register I could remove a lot of exx faffing.
Code: Select all
ORGADDR EQU #8000
; sjasmplus.exe --sym=out.sym --syntax=f --raw=out.bin modernmm.asm
ORG ORGADDR
DISPLAY "ORIGIN ", /A, ORGADDR
SCRBASE EQU #4000
ATTRIBS EQU #5800
TIMING EQU 1
MACRO DWXYTOSCRADDR _x_, _y_
dw SCRBASE + (((_y_)|((_y_&#C0)>>3))<<8)|((_x_F)|((_y_&)<<2))
ENDM
MACRO SETBORDER bdr
ld a, bdr
out (#FE), a
ENDM
MACRO COLLMAPTOTILE
ex de, hl
dec a ; tile map is collision map data - 1
rlca ; *2
ld h, level_tiles/256
ld l, a
ld a, (hl)
inc l
ld h, (hl)
ld l, a
ex de, hl
ENDM
main:
call draw_level
mainloop:
IF TIMING
SETBORDER 7
ENDIF
halt
IF TIMING
SETBORDER 1
ENDIF
ld hl, willy_oldpos
ld a, (hl)
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
and ~7
rrca
rrca
rrca
ld b, a
call erase_willy
IF TIMING
SETBORDER 2
ENDIF
ld hl, willy_xpos
ld a, (hl)
ld d, a
and 7
rrca
rrca
rrca
ld e, a
ld a, d
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
and ~7
rrca
rrca
rrca
ld b, a
ld d, gfx_willy0/256
ld a, (willy_facing)
dec a
jr z, .dontadjustdbottomsprite
inc d
.dontadjustdbottomsprite
call sprite16x16ra
IF TIMING
SETBORDER 1
ENDIF
ld hl, willy_oldpos
ld a, (hl)
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
sub 32
and ~7
rrca
rrca
rrca
ld b, a
call erase_willy
IF TIMING
SETBORDER 2
ENDIF
ld hl, willy_xpos
ld a, (hl)
ld d, a
and 7
rrca
rrca
rrca
ld e, a
ld a, d
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
sub 32
and ~7
rrca
rrca
rrca
ld b, a
ld d, gfx_gwilly0/256
ld a, (willy_facing)
dec a
jr z, .dontadjustdtopsprite
inc d
.dontadjustdtopsprite
call sprite16x16ra
IF TIMING
SETBORDER 1
ENDIF
ld hl, willy_oldpos
ld a, (hl)
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
sub 64
and ~7
rrca
rrca
rrca
ld b, a
call erase_willy
IF TIMING
SETBORDER 2
ENDIF
ld hl, willy_xpos
ld a, (hl)
ld d, a
and 7
rrca
rrca
rrca
ld e, a
ld a, d
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
sub 64
and ~7
rrca
rrca
rrca
ld b, a
ld d, gfx_newwilly0/256
ld a, (willy_facing)
dec a
jr z, .dontadjustdtopbotsprite
inc d
.dontadjustdtopbotsprite
call sprite16x16ra
IF TIMING
SETBORDER 1
ENDIF
ld hl, willy_oldpos
ld a, (hl)
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
sub 96
and ~7
rrca
rrca
rrca
ld b, a
call erase_willy
IF TIMING
SETBORDER 2
ENDIF
ld hl, willy_xpos
ld a, (hl)
ld d, a
and 7
rrca
rrca
rrca
ld e, a
ld a, d
and ~7
rrca
rrca
rrca
ld c, a
inc l
ld a, (hl)
sub 96
and ~7
rrca
rrca
rrca
ld b, a
ld d, gfx_gnewwilly0/256
ld a, (willy_facing)
dec a
jr z, .dontadjustdtoptopsprite
inc d
.dontadjustdtoptopsprite
call sprite16x16ra
IF TIMING
SETBORDER 4
ENDIF
ld de, willy_oldpos
ld hl, willy_xpos
ldi
ldi
call read_keyboard
ld hl, willy_xpos
ld a, (hl)
add c
cp 8
jr c, .doneupatepos
cp 240
jr nc, .doneupatepos
ld (hl), a
.doneupatepos
jp mainloop
ret
; B: row (in character cells, so [0-23])
; C: column
sprite16x16ra:
ld a, b
add b ; A = B*2
ld h, tbl_rows/256 ; high byte of screen address lookup table. Aligned 256 so low byte will be just row*2
ld l, a ; index into table
ld a, (hl) ; low byte of screen address
inc l ; point HL to high byte of screen address
ld h, (hl) ; read high byte of screen address
add c ; add on column to low byte of screen address
ld l, a ; and write it back. HL now holds correct screen address
; so we now know the address...
; HL: screen address
sprite16x16raKnowAddr:
REPT 8
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
or (hl)
ld (hl), a
inc l
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
or (hl)
ld (hl), a
inc h ; next row of pixels down
dec l
ENDR
; we could split this into 2 routines depending on whether we straddle a screen third boundary or not
; which we could work out before calling
; then we could remove the jr c
ld a, #20
add l
ld l, a
jr c, .ok
ld a, h
sub #8
ld h, a
.ok
REPT 7
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
or (hl)
ld (hl), a
inc l
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
or (hl)
ld (hl), a
inc h ; next row of pixels down
dec l
ENDR
; last row, don't need to increment gfx data pointer or screen row
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
or (hl)
ld (hl), a
inc l
ld a, (de)
or (hl)
ld (hl), a
ret
; B: row
; C: column
erase_willy:
; I think there's a much faster way of doing this involving rrca
ld de, collision_map
ld l, b
ld h, e ; E = 0
REPT 5
add hl, hl ; *2, ... , *32
ENDR
add hl, de
ld a, l
or c ; add on column
ld l, a
; hl now has collision map address
push hl
ld a, (hl)
or a
jr nz, .tlnotblank
call erase8x8a
jp .topright
.tlnotblank
COLLMAPTOTILE
call sprite8x8a
.topright
pop hl
inc l ; look at top right cell
inc c ; which is one column over
push hl
ld a, (hl)
or a
jr nz, .trnotblank
call erase8x8a
jp .botright
.trnotblank
COLLMAPTOTILE
call sprite8x8a
.botright
pop hl
ld de, 32
add hl, de
inc b ; move 1 cell down
push hl
ld a, (hl)
or a
jr nz, .brnotblank
call erase8x8a
jp .botleft
.brnotblank
COLLMAPTOTILE
call sprite8x8a
.botleft
pop hl
dec l ; look at bottom left cell
dec c ; which is one column left
ld a, (hl)
or a
jr nz, .blnotblank
call erase8x8a
ret
.blnotblank
COLLMAPTOTILE
call sprite8x8a
ret
; B: row (in character cells, so [0-23])
; C: column
erase8x8a:
ld a, b
add b ; A = B*2
ld h, tbl_rows/256 ; high byte of screen address lookup table. Aligned 256 so low byte will be just row*2
ld l, a ; index into table
ld a, (hl) ; low byte of screen address
inc l ; point HL to high byte of screen address
ld h, (hl) ; read high byte of screen address
add c ; add on column to low byte of screen address
ld l, a ; and write it back. HL now holds correct screen address
; so we now know the address...
; HL: screen address
erase8x8aKnowAddr:
xor a
REPT 7
ld (hl), a
inc h ; next row of pixels down
ENDR
ld (hl), a
ret
; B: row (in character cells, so [0-23])
; C: column
erase16x16ra:
ld a, b
add b ; A = B*2
ld h, tbl_rows/256 ; high byte of screen address lookup table. Aligned 256 so low byte will be just row*2
ld l, a ; index into table
ld a, (hl) ; low byte of screen address
inc l ; point HL to high byte of screen address
ld h, (hl) ; read high byte of screen address
add c ; add on column to low byte of screen address
ld l, a ; and write it back. HL now holds correct screen address
; so we now know the address...
; HL: screen address
erase16x16raKnowAddr:
xor a
REPT 8
ld (hl), a
inc l
ld (hl), a
inc h ; next row of pixels down
dec l
ENDR
; we could split this into 2 routines depending on whether we straddle a screen third boundary or not
; which we could work out before calling
; then we could remove the jr c
ld a, #20
add l
ld l, a
jr c, .ok
ld a, h
sub #8
ld h, a
.ok
xor a
REPT 7
ld (hl), a
inc l
ld (hl), a
inc h ; next row of pixels down
dec l
ENDR
ld (hl), a
inc l
ld (hl), a
ret
; B: row (in character cells, so [0-23])
; C: column
; DE: 8 rows 8x1 sprite data (8 byte aligned)
sprite8x8a:
ld a, b
add b ; A = B*2
ld h, tbl_rows/256 ; high byte of screen address lookup table. Aligned 256 so low byte will be just row*2
ld l, a ; index into table
ld a, (hl) ; low byte of screen address
inc l ; point HL to high byte of screen address
ld h, (hl) ; read high byte of screen address
add c ; add on column to low byte of screen address
ld l, a ; and write it back. HL now holds correct screen address
; so we now know the address...
; HL: screen address
; DE: 8 rows 8x1 sprite data (8 byte aligned)
sprite8x8aKnowAddr:
REPT 7
ld a, (de)
inc e ; ok because gfx data is 8 byte aligned
ld (hl), a
inc h ; next row of pixels down
ENDR
; last row, don't need to increment gfx data pointer or screen row
ld a, (de)
ld (hl), a
ret
draw_level:
SETBORDER 2
ld a, 7 ; white ink, non bright
call cls
ld b, 30
.floorloop
push bc
ld c, b
ld b, 15
ld de, gfx_platform0
call sprite8x8a
pop bc
ld hl, ATTRIBS+15*32
ld a, l
add b
ld l, a
ld (hl), 64+2 ; bright red
push bc
ld c, b
ld b, 11
ld de, gfx_platform0
call sprite8x8a
pop bc
ld hl, ATTRIBS+11*32
ld a, l
add b
ld l, a
ld (hl), 64+2 ; bright red
push bc
ld c, b
ld b, 7
ld de, gfx_platform1
call sprite8x8a
pop bc
ld hl, ATTRIBS+7*32
ld a, l
add b
ld l, a
ld (hl), 64+5 ; bright cyan
push bc
ld c, b
ld b, 3
ld de, gfx_platform1
call sprite8x8a
pop bc
ld hl, ATTRIBS+3*32
ld a, l
add b
ld l, a
ld (hl), 64+5 ; bright cyan
djnz .floorloop
ld b, 16
.wallloop
push bc
ld c, 0
dec b
ld de, gfx_wall0
call sprite8x8a
pop bc
ld l, b
dec l
ld h, 0
ld de, ATTRIBS
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, de
ld (hl), 64+(2*8)+6 ; bright paper, yellow ink
push bc
ld c, 31
dec b
ld de, gfx_wall0
call sprite8x8a
pop bc
ld l, b
dec l
ld h, 0
ld de, ATTRIBS+31
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, de
ld (hl), 64+(2*8)+6 ; bright paper, yellow ink
djnz .wallloop
; add a bush at row 14, column 21
ld bc, (14*256)+21
ld de, gfx_spiky0
call sprite8x8a
ld hl, ATTRIBS+(14*32)+21
ld (hl), 64+4 ; bright green
; draw some ledges too
ld b, 22
.ledgeloop
push bc
ld a, b
add 4
ld c, a
ld b, 13
ld de, gfx_platform0
call sprite8x8a
pop bc
ld hl, ATTRIBS+4+13*32
ld a, l
add b
ld l, a
ld (hl), 64+2 ; bright red
push bc
ld a, b
add 4
ld c, a
ld b, 9
ld de, gfx_platform0
call sprite8x8a
pop bc
ld hl, ATTRIBS+4+9*32
ld a, l
add b
ld l, a
ld (hl), 64+2 ; bright red
djnz .ledgeloop
ret
; A -> attrib to set when clearing screen
cls:
; set attribs
ld hl, #5800+767
ld de, #5800+766
ld bc, 768
ld (hl), a
lddr
; clear pixels
ld (hl), b ; since B=0 here
ld bc, 6144-1
lddr
ret
; at exit, C contains 1 if we pressed right and -1 if we pressed left
read_keyboard:
; Read these ports to scan keyboard
; bit N (0-based) is clear if the key is being pressed
; #FE - SHIFT, Z, X, C, & V
; #FD - A, S, D, F, & G
; #FB - Q, W, E, R, & T
; #F7 - 1, 2, 3, 4, & 5
; #EF - 0, 9, 8, 7, & 6
; #DF - P, O, I, U, & Y
; #BF - ENTER, L, K, J, & H
; #7F - SPACE, FULL-STOP, M, N, & B
; ld a, port
; in a, (#FE)
; to do the read of the port
ld bc, 0
; are we pressing W?
ld a, #FB
in a, (#FE)
bit 1, a
jr nz, .notpressingW
inc c
.notpressingW
; are we pressing Q?
bit 0, a
jr nz, .notpressingQ
dec c
.notpressingQ
ld a, c
or a
ret z ; not moving
ld hl, willy_facing
ld (hl), c
ret
ALIGN 256
gfx_willy0
dg .....##......... ;0
dg ..##.##......... ;1
dg .##............. ;2
dg .#..#........... ;3
dg ..###.#......... ;4
dg ...###.......... ;5
dg ................ ;6
dg .##.#.#......... ;7
dg #...###......... ;8
dg #....###........ ;9
dg .....###........ ;10
dg ###.###......... ;11
dg ##.#####........ ;12
dg ...##.##........ ;13
dg ................ ;14
dg ...###.#........ ;15
gfx_willy1
dg ......##........ ;0
dg ...##.##........ ;1
dg ..##............ ;2
dg ..#..#.......... ;3
dg ...###.#........ ;4
dg ....###......... ;5
dg ..##............ ;6
dg .#...#.#........ ;7
dg .....###........ ;8
dg .#....###....... ;9
dg ####..###....... ;10
dg ###..###........ ;11
dg ...###.##....... ;12
dg ...##........... ;13
dg .......###...... ;14
dg ...###.......... ;15
gfx_willy2
dg .......##....... ;0
dg ....##.##....... ;1
dg ...##........... ;2
dg ...#..#......... ;3
dg ....###.#....... ;4
dg .....###........ ;5
dg ...##........... ;6
dg ..#...#.#....... ;7
dg ..#...###....... ;8
dg ...###.###...... ;9
dg ..###..###...... ;10
dg ...#..###....... ;11
dg ....###......... ;12
dg ....##..###..... ;13
dg ...#............ ;14
dg ...##........... ;15
gfx_willy3
dg ........##...... ;0
dg .....##.##...... ;1
dg ....##.......... ;2
dg ....#..#........ ;3
dg .....###.#...... ;4
dg ......###....... ;5
dg .....#.......... ;6
dg ....#...#....... ;7
dg ....#.#..#...... ;8
dg .....###.##..... ;9
dg ......##.##..... ;10
dg ........##...... ;11
dg ....#.##..#..... ;12
dg ....#.#..###.... ;13
dg ....#........... ;14
dg ................ ;15
gfx_willy4
dg .........##..... ;0
dg ......##.##..... ;1
dg .....##......... ;2
dg .....#..#....... ;3
dg ......###.#..... ;4
dg .......###...... ;5
dg ......#......... ;6
dg .....#.......... ;7
dg .....#....#..... ;8
dg ......#..####... ;9
dg .......#..###... ;10
dg .....#.......... ;11
dg .....#.##....... ;12
dg .....#....###... ;13
dg ................ ;14
dg ................ ;15
gfx_willy5
dg ................ ;0
dg ..........##.... ;1
dg .......##.##.... ;2
dg ......##........ ;3
dg ......#..#...... ;4
dg .......###.#.... ;5
dg ........###..... ;6
dg .......#........ ;7
dg ......#......... ;8
dg ......#....#.... ;9
dg .......##.####.. ;10
dg .....#...#.###.. ;11
dg .....#.##....... ;12
dg .....#..####.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_willy6
dg ................ ;0
dg ...........##... ;1
dg ........##.##... ;2
dg .......##....... ;3
dg .......#..#..... ;4
dg ........###.#... ;5
dg .........###.... ;6
dg ........#....... ;7
dg .......#........ ;8
dg .......#..#..... ;9
dg ........#.##.... ;10
dg .......#..##.... ;11
dg ......##.#..#... ;12
dg ......#...##.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_willy7
dg .............##. ;0
dg ..........##.##. ;1
dg .........##..... ;2
dg .........#..#... ;3
dg ..........###.#. ;4
dg ...........###.. ;5
dg ................ ;6
dg .........#..#... ;7
dg ........#....#.. ;8
dg ........#.#..##. ;9
dg .........###.##. ;10
dg ..........##.##. ;11
dg ............###. ;12
dg ...........###.. ;13
dg ................ ;14
dg ...........###.. ;15
gfx_willy8
dg .##............. ;0
dg .##.##.......... ;1
dg .....##......... ;2
dg ...#..#......... ;3
dg .#.###.......... ;4
dg ..###........... ;5
dg ................ ;6
dg ...#..#......... ;7
dg ..#....#........ ;8
dg .##....#........ ;9
dg .##...#......... ;10
dg .##..###........ ;11
dg .###.##......... ;12
dg ..###........... ;13
dg ................ ;14
dg ..###........... ;15
gfx_willy9
dg ................ ;0
dg ...##........... ;1
dg ...##.##........ ;2
dg .......##....... ;3
dg .....#..#....... ;4
dg ...#.###........ ;5
dg ....###......... ;6
dg .......#........ ;7
dg ........#....... ;8
dg .....#..#....... ;9
dg ....##.#........ ;10
dg ....##..#....... ;11
dg ...#..#.##...... ;12
dg ....##...#...... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_willy10
dg ................ ;0
dg ....##.......... ;1
dg ....##.##....... ;2
dg ........##...... ;3
dg ......#..#...... ;4
dg ....#.###....... ;5
dg .....###........ ;6
dg ........#....... ;7
dg .........#...... ;8
dg ....#....#...... ;9
dg ..####.##....... ;10
dg ..###.#...#..... ;11
dg .......##.#..... ;12
dg ....####..#..... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_willy11
dg .....##......... ;0
dg .....##.##...... ;1
dg .........##..... ;2
dg .......#..#..... ;3
dg .....#.###...... ;4
dg ......###....... ;5
dg .........#...... ;6
dg ..........#..... ;7
dg .....#....#..... ;8
dg ...####..#...... ;9
dg ...###..#....... ;10
dg ..........#..... ;11
dg .......##.#..... ;12
dg ...###....#..... ;13
dg ................ ;14
dg ................ ;15
gfx_willy12
dg ......##........ ;0
dg ......##.##..... ;1
dg ..........##.... ;2
dg ........#..#.... ;3
dg ......#.###..... ;4
dg .......###...... ;5
dg ..........#..... ;6
dg .......#...#.... ;7
dg ......#..#.#.... ;8
dg .....##.###..... ;9
dg .....##.##...... ;10
dg ......##........ ;11
dg .....#..##.#.... ;12
dg ....###..#.#.... ;13
dg ...........#.... ;14
dg ................ ;15
gfx_willy13
dg .......##....... ;0
dg .......##.##.... ;1
dg ...........##... ;2
dg .........#..#... ;3
dg .......#.###.... ;4
dg ........###..... ;5
dg ...........##... ;6
dg .......#.#...#.. ;7
dg .......###...#.. ;8
dg ......###.###... ;9
dg ......###..###.. ;10
dg .......###..#... ;11
dg .........###.... ;12
dg .....###..##.... ;13
dg ............#... ;14
dg ...........##... ;15
gfx_willy14
dg ........##...... ;0
dg ........##.##... ;1
dg ............##.. ;2
dg ..........#..#.. ;3
dg ........#.###... ;4
dg .........###.... ;5
dg ............##.. ;6
dg ........#.#...#. ;7
dg ........###..... ;8
dg .......###....#. ;9
dg .......###..#### ;10
dg ........###..### ;11
dg .......##.###... ;12
dg ...........##... ;13
dg ......###....... ;14
dg ..........###... ;15
gfx_willy15
dg .........##..... ;0
dg .........##.##.. ;1
dg .............##. ;2
dg ...........#..#. ;3
dg .........#.###.. ;4
dg ..........###... ;5
dg ................ ;6
dg .........#.#.##. ;7
dg .........###...# ;8
dg ........###....# ;9
dg ........###..... ;10
dg .........###.### ;11
dg ........#####.## ;12
dg ........##.##... ;13
dg ................ ;14
dg ........#.###... ;15
gfx_gwilly0
dg .....##......... ;0
dg ..##.##......... ;1
dg .##............. ;2
dg .#..#........... ;3
dg ..###.#......... ;4
dg ...###.......... ;5
dg ................ ;6
dg .##.#.#......... ;7
dg #...###......... ;8
dg #....###........ ;9
dg .....###........ ;10
dg ###.###......... ;11
dg ##.#####........ ;12
dg ...##.##........ ;13
dg ................ ;14
dg ...###.#........ ;15
gfx_gwilly1
dg ......##........ ;0
dg ...##.##........ ;1
dg ..##............ ;2
dg ..#..#.......... ;3
dg ...###.#........ ;4
dg ....###......... ;5
dg ..##............ ;6
dg .#...#.#........ ;7
dg .....###........ ;8
dg .#....###....... ;9
dg ####..###....... ;10
dg ###..###........ ;11
dg ...###.##....... ;12
dg ...##........... ;13
dg .......###...... ;14
dg ...###.......... ;15
gfx_gwilly2
dg .......##....... ;0
dg ....##.##....... ;1
dg ...##........... ;2
dg ...#..#......... ;3
dg ....###.#....... ;4
dg .....###........ ;5
dg ...##........... ;6
dg ..#...#.#....... ;7
dg ..#...###....... ;8
dg ...###.###...... ;9
dg ..###..###...... ;10
dg ...#..###....... ;11
dg ....###......... ;12
dg ....##..###..... ;13
dg ...#............ ;14
dg ...##........... ;15
gfx_gwilly3
dg ................ ;0
dg ........##...... ;1
dg .....##.##...... ;2
dg ....##.......... ;3
dg ....#..#........ ;4
dg .....###.#...... ;5
dg ......###....... ;6
dg .....#.......... ;7
dg ....#...#....... ;8
dg ....#.#..#...... ;9
dg .....###.##..... ;10
dg ......##.##..... ;11
dg ........##...... ;12
dg ....#.##..#..... ;13
dg ....#.#..###.... ;14
dg ....#........... ;15
gfx_gwilly4
dg ................ ;0
dg ................ ;1
dg .........##..... ;2
dg ......##.##..... ;3
dg .....##......... ;4
dg .....#..#....... ;5
dg ......###.#..... ;6
dg .......###...... ;7
dg ......#......... ;8
dg .....#.......... ;9
dg .....#....#..... ;10
dg ......#..####... ;11
dg .......#..###... ;12
dg .....#.......... ;13
dg .....#.##....... ;14
dg .....#....###... ;15
gfx_gwilly5
dg ................ ;0
dg ..........##.... ;1
dg .......##.##.... ;2
dg ......##........ ;3
dg ......#..#...... ;4
dg .......###.#.... ;5
dg ........###..... ;6
dg .......#........ ;7
dg ......#......... ;8
dg ......#....#.... ;9
dg .......##.####.. ;10
dg .....#...#.###.. ;11
dg .....#.##....... ;12
dg .....#..####.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_gwilly6
dg ................ ;0
dg ...........##... ;1
dg ........##.##... ;2
dg .......##....... ;3
dg .......#..#..... ;4
dg ........###.#... ;5
dg .........###.... ;6
dg ........#....... ;7
dg .......#........ ;8
dg .......#..#..... ;9
dg ........#.##.... ;10
dg .......#..##.... ;11
dg ......##.#..#... ;12
dg ......#...##.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_gwilly7
dg .............##. ;0
dg ..........##.##. ;1
dg .........##..... ;2
dg .........#..#... ;3
dg ..........###.#. ;4
dg ...........###.. ;5
dg ................ ;6
dg .........#..#... ;7
dg ........#....#.. ;8
dg ........#.#..##. ;9
dg .........###.##. ;10
dg ..........##.##. ;11
dg ............###. ;12
dg ...........###.. ;13
dg ................ ;14
dg ...........###.. ;15
gfx_gwilly8
dg .##............. ;0
dg .##.##.......... ;1
dg .....##......... ;2
dg ...#..#......... ;3
dg .#.###.......... ;4
dg ..###........... ;5
dg ................ ;6
dg ...#..#......... ;7
dg ..#....#........ ;8
dg .##....#........ ;9
dg .##...#......... ;10
dg .##..###........ ;11
dg .###.##......... ;12
dg ..###........... ;13
dg ................ ;14
dg ..###........... ;15
gfx_gwilly9
dg ................ ;0
dg ...##........... ;1
dg ...##.##........ ;2
dg .......##....... ;3
dg .....#..#....... ;4
dg ...#.###........ ;5
dg ....###......... ;6
dg .......#........ ;7
dg ........#....... ;8
dg .....#..#....... ;9
dg ....##.#........ ;10
dg ....##..#....... ;11
dg ...#..#.##...... ;12
dg ....##...#...... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_gwilly10
dg ................ ;0
dg ....##.......... ;1
dg ....##.##....... ;2
dg ........##...... ;3
dg ......#..#...... ;4
dg ....#.###....... ;5
dg .....###........ ;6
dg ........#....... ;7
dg .........#...... ;8
dg ....#....#...... ;9
dg ..####.##....... ;10
dg ..###.#...#..... ;11
dg .......##.#..... ;12
dg ....####..#..... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_gwilly11
dg ................ ;0
dg ................ ;1
dg .....##......... ;2
dg .....##.##...... ;3
dg .........##..... ;4
dg .......#..#..... ;5
dg .....#.###...... ;6
dg ......###....... ;7
dg .........#...... ;8
dg ..........#..... ;9
dg .....#....#..... ;10
dg ...####..#...... ;11
dg ...###..#....... ;12
dg ..........#..... ;13
dg .......##.#..... ;14
dg ...###....#..... ;15
gfx_gwilly12
dg ................ ;0
dg ......##........ ;1
dg ......##.##..... ;2
dg ..........##.... ;3
dg ........#..#.... ;4
dg ......#.###..... ;5
dg .......###...... ;6
dg ..........#..... ;7
dg .......#...#.... ;8
dg ......#..#.#.... ;9
dg .....##.###..... ;10
dg .....##.##...... ;11
dg ......##........ ;12
dg .....#..##.#.... ;13
dg ....###..#.#.... ;14
dg ...........#.... ;15
gfx_gwilly13
dg .......##....... ;0
dg .......##.##.... ;1
dg ...........##... ;2
dg .........#..#... ;3
dg .......#.###.... ;4
dg ........###..... ;5
dg ...........##... ;6
dg .......#.#...#.. ;7
dg .......###...#.. ;8
dg ......###.###... ;9
dg ......###..###.. ;10
dg .......###..#... ;11
dg .........###.... ;12
dg .....###..##.... ;13
dg ............#... ;14
dg ...........##... ;15
gfx_gwilly14
dg ........##...... ;0
dg ........##.##... ;1
dg ............##.. ;2
dg ..........#..#.. ;3
dg ........#.###... ;4
dg .........###.... ;5
dg ............##.. ;6
dg ........#.#...#. ;7
dg ........###..... ;8
dg .......###....#. ;9
dg .......###..#### ;10
dg ........###..### ;11
dg .......##.###... ;12
dg ...........##... ;13
dg ......###....... ;14
dg ..........###... ;15
gfx_gwilly15
dg .........##..... ;0
dg .........##.##.. ;1
dg .............##. ;2
dg ...........#..#. ;3
dg .........#.###.. ;4
dg ..........###... ;5
dg ................ ;6
dg .........#.#.##. ;7
dg .........###...# ;8
dg ........###....# ;9
dg ........###..... ;10
dg .........###.### ;11
dg ........#####.## ;12
dg ........##.##... ;13
dg ................ ;14
dg ........#.###... ;15
gfx_newwilly0
dg .....##......... ;0
dg ..##.##......... ;1
dg .##............. ;2
dg .#..#........... ;3
dg ..###.#......... ;4
dg ...###.......... ;5
dg ................ ;6
dg .##.#..#........ ;7
dg ####.##......... ;8
dg ##..####........ ;9
dg ...##..#........ ;10
dg ##..####........ ;11
dg ##.####......... ;12
dg ..##.##......... ;13
dg ................ ;14
dg ..###.##........ ;15
gfx_newwilly1
dg ......##........ ;0
dg ...##.##........ ;1
dg ..##............ ;2
dg ..#..#.......... ;3
dg ...###.#........ ;4
dg ....###......... ;5
dg .##............. ;6
dg ####.#..#....... ;7
dg ...#.###........ ;8
dg ##...####....... ;9
dg ##.###..#....... ;10
dg ....#####....... ;11
dg ...###.......... ;12
dg ...##..###...... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_newwilly2
dg .......##....... ;0
dg ....##.##....... ;1
dg ...##........... ;2
dg ...#..#......... ;3
dg ....###.#....... ;4
dg ......##........ ;5
dg ..###........... ;6
dg .##...#..#...... ;7
dg .#.##..##....... ;8
dg ...##.###....... ;9
dg .....#####...... ;10
dg ...####......... ;11
dg ...###..###..... ;12
dg ....##.......... ;13
dg ...#............ ;14
dg ....##.......... ;15
gfx_newwilly3
dg ........##...... ;0
dg .....##.##...... ;1
dg ....##.......... ;2
dg ....#..#........ ;3
dg .....###.#...... ;4
dg ......###....... ;5
dg .....#.......... ;6
dg ....####.##..... ;7
dg .....###.##..... ;8
dg ................ ;9
dg ....#.#.##...... ;10
dg ...#.####.#..... ;11
dg ...#..##........ ;12
dg .........###.... ;13
dg ................ ;14
dg ................ ;15
gfx_newwilly4
dg .........##..... ;0
dg ......##.##..... ;1
dg .....##......... ;2
dg .....#..#....... ;3
dg ......###.#..... ;4
dg .......###...... ;5
dg ......#....##... ;6
dg ......####.##... ;7
dg .......####..... ;8
dg .....#.......... ;9
dg ....#.#####..... ;10
dg ....#.##..##.... ;11
dg ..........##.... ;12
dg ................ ;13
dg ..........###... ;14
dg ................ ;15
gfx_newwilly5
dg ..........##.... ;0
dg ..........##.... ;1
dg .......##....... ;2
dg ......##........ ;3
dg ......#..#...... ;4
dg .......###.#.... ;5
dg ........###..... ;6
dg .......#........ ;7
dg ......###....... ;8
dg ......####.#.... ;9
dg .......##.###... ;10
dg .....#...#.##... ;11
dg .....#.##.#..... ;12
dg .....#....##.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_newwilly6
dg ................ ;0
dg ...........##... ;1
dg ........##.##... ;2
dg .......##....... ;3
dg .......#..#..... ;4
dg ........###.#... ;5
dg .........###.... ;6
dg ........#....... ;7
dg .......###.#.... ;8
dg .......###...... ;9
dg ........#.##.... ;10
dg .......#..##.... ;11
dg ........##...... ;12
dg .........###.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_newwilly7
dg .............##. ;0
dg ..........##.##. ;1
dg .........##..... ;2
dg .........#..#... ;3
dg ..........###.#. ;4
dg ...........###.. ;5
dg ................ ;6
dg .........##.#... ;7
dg ........####.#.. ;8
dg ........##..###. ;9
dg ..........##.##. ;10
dg ..........##.##. ;11
dg ............##.. ;12
dg ...........###.. ;13
dg ................ ;14
dg ..........###... ;15
gfx_newwilly8
dg .##............. ;0
dg .##.##.......... ;1
dg .....##......... ;2
dg ...#..#......... ;3
dg .#.###.......... ;4
dg ..###........... ;5
dg ................ ;6
dg ...#.##......... ;7
dg ..#.####........ ;8
dg .###..##........ ;9
dg .##.##.......... ;10
dg .##.##.......... ;11
dg ..##............ ;12
dg ..###........... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_newwilly9
dg ................ ;0
dg ...##........... ;1
dg ...##.##........ ;2
dg .......##....... ;3
dg .....#..#....... ;4
dg ...#.###........ ;5
dg ....###......... ;6
dg .......#........ ;7
dg ....#.###....... ;8
dg ......###....... ;9
dg ....##.#........ ;10
dg ....##..#....... ;11
dg ......##........ ;12
dg ....###......... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_newwilly10
dg ....##.......... ;0
dg ....##.......... ;1
dg .......##....... ;2
dg ........##...... ;3
dg ......#..#...... ;4
dg ....#.###....... ;5
dg .....###........ ;6
dg ........#....... ;7
dg .......###...... ;8
dg ....#.####...... ;9
dg ...###.##....... ;10
dg ...##.#...#..... ;11
dg .....#.##.#..... ;12
dg ....##....#..... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_newwilly11
dg .....##......... ;0
dg .....##.##...... ;1
dg .........##..... ;2
dg .......#..#..... ;3
dg .....#.###...... ;4
dg ......###....... ;5
dg ...##....#...... ;6
dg ...##.####...... ;7
dg .....####....... ;8
dg ..........#..... ;9
dg .....#####.#.... ;10
dg ....##..##.#.... ;11
dg ....##.......... ;12
dg ................ ;13
dg ...###.......... ;14
dg ................ ;15
gfx_newwilly12
dg ......##........ ;0
dg ......##.##..... ;1
dg ..........##.... ;2
dg ........#..#.... ;3
dg ......#.###..... ;4
dg .......###...... ;5
dg ..........#..... ;6
dg .....##.####.... ;7
dg .....##.###..... ;8
dg ................ ;9
dg ......##.#.#.... ;10
dg .....#.####.#... ;11
dg ........##..#... ;12
dg ....###......... ;13
dg ................ ;14
dg ................ ;15
gfx_newwilly13
dg .......##....... ;0
dg .......##.##.... ;1
dg ...........##... ;2
dg .........#..#... ;3
dg .......#.###.... ;4
dg ........##...... ;5
dg ...........###.. ;6
dg ......#..#...##. ;7
dg .......##..##.#. ;8
dg .......###.##... ;9
dg ......#####..... ;10
dg .........####... ;11
dg .....###..###... ;12
dg ..........##.... ;13
dg ............#... ;14
dg ..........##.... ;15
gfx_newwilly14
dg ........##...... ;0
dg ........##.##... ;1
dg ............##.. ;2
dg ..........#..#.. ;3
dg ........#.###... ;4
dg .........###.... ;5
dg .............##. ;6
dg .......#..#.#### ;7
dg ........###.#... ;8
dg .......####...## ;9
dg .......#..###.## ;10
dg .......#####.... ;11
dg ..........###... ;12
dg ......###..##... ;13
dg ................ ;14
dg ..........###... ;15
gfx_newwilly15
dg .........##..... ;0
dg .........##.##.. ;1
dg .............##. ;2
dg ...........#..#. ;3
dg .........#.###.. ;4
dg ..........###... ;5
dg ................ ;6
dg ........#..#.##. ;7
dg .........##.#### ;8
dg ........####..## ;9
dg ........#..##... ;10
dg ........####..## ;11
dg .........####.## ;12
dg .........##.##.. ;13
dg ................ ;14
dg ........##.###.. ;15
gfx_gnewwilly0
dg .....##......... ;0
dg ..##.##......... ;1
dg .##............. ;2
dg .#..#........... ;3
dg ..###.#......... ;4
dg ...###.......... ;5
dg ................ ;6
dg .##.#..#........ ;7
dg ####.##......... ;8
dg ##..####........ ;9
dg ...##..#........ ;10
dg ##..####........ ;11
dg ##.####......... ;12
dg ..##.##......... ;13
dg ................ ;14
dg ..###.##........ ;15
gfx_gnewwilly1
dg ......##........ ;0
dg ...##.##........ ;1
dg ..##............ ;2
dg ..#..#.......... ;3
dg ...###.#........ ;4
dg ....###......... ;5
dg .##............. ;6
dg ####.#..#....... ;7
dg ...#.###........ ;8
dg ##...####....... ;9
dg ##.###..#....... ;10
dg ....#####....... ;11
dg ...###.......... ;12
dg ...##..###...... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_gnewwilly2
dg .......##....... ;0
dg ....##.##....... ;1
dg ...##........... ;2
dg ...#..#......... ;3
dg ....###.#....... ;4
dg ......##........ ;5
dg ..###........... ;6
dg .##...#..#...... ;7
dg .#.##..##....... ;8
dg ...##.###....... ;9
dg .....#####...... ;10
dg ...####......... ;11
dg ...###..###..... ;12
dg ....##.......... ;13
dg ...#............ ;14
dg ....##.......... ;15
gfx_gnewwilly3
dg ................ ;0
dg ................ ;1
dg ........##...... ;2
dg .....##.##...... ;3
dg ....##.......... ;4
dg ....#..#........ ;5
dg .....###.#...... ;6
dg ......###....... ;7
dg .....#.......... ;8
dg ....####.##..... ;9
dg .....###.##..... ;10
dg ................ ;11
dg ....#.#.##...... ;12
dg ...#.####.#..... ;13
dg ...#..##........ ;14
dg .........###.... ;15
gfx_gnewwilly4
dg ................ ;0
dg .........##..... ;1
dg ......##.##..... ;2
dg .....##......... ;3
dg .....#..#....... ;4
dg ......###.#..... ;5
dg .......###...... ;6
dg ......#....##... ;7
dg ......####.##... ;8
dg .......####..... ;9
dg .....#.......... ;10
dg ....#.#####..... ;11
dg ....#.##..##.... ;12
dg ..........##.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_gnewwilly5
dg ..........##.... ;0
dg ..........##.... ;1
dg .......##....... ;2
dg ......##........ ;3
dg ......#..#...... ;4
dg .......###.#.... ;5
dg ........###..... ;6
dg .......#........ ;7
dg ......###....... ;8
dg ......####.#.... ;9
dg .......##.###... ;10
dg .....#...#.##... ;11
dg .....#.##.#..... ;12
dg .....#....##.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_gnewwilly6
dg ................ ;0
dg ...........##... ;1
dg ........##.##... ;2
dg .......##....... ;3
dg .......#..#..... ;4
dg ........###.#... ;5
dg .........###.... ;6
dg ........#....... ;7
dg .......###.#.... ;8
dg .......###...... ;9
dg ........#.##.... ;10
dg .......#..##.... ;11
dg ........##...... ;12
dg .........###.... ;13
dg ................ ;14
dg ..........###... ;15
gfx_gnewwilly7
dg .............##. ;0
dg ..........##.##. ;1
dg .........##..... ;2
dg .........#..#... ;3
dg ..........###.#. ;4
dg ...........###.. ;5
dg ................ ;6
dg .........##.#... ;7
dg ........####.#.. ;8
dg ........##..###. ;9
dg ..........##.##. ;10
dg ..........##.##. ;11
dg ............##.. ;12
dg ...........###.. ;13
dg ................ ;14
dg ..........###... ;15
gfx_gnewwilly8
dg .##............. ;0
dg .##.##.......... ;1
dg .....##......... ;2
dg ...#..#......... ;3
dg .#.###.......... ;4
dg ..###........... ;5
dg ................ ;6
dg ...#.##......... ;7
dg ..#.####........ ;8
dg .###..##........ ;9
dg .##.##.......... ;10
dg .##.##.......... ;11
dg ..##............ ;12
dg ..###........... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_gnewwilly9
dg ................ ;0
dg ...##........... ;1
dg ...##.##........ ;2
dg .......##....... ;3
dg .....#..#....... ;4
dg ...#.###........ ;5
dg ....###......... ;6
dg .......#........ ;7
dg ....#.###....... ;8
dg ......###....... ;9
dg ....##.#........ ;10
dg ....##..#....... ;11
dg ......##........ ;12
dg ....###......... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_gnewwilly10
dg ....##.......... ;0
dg ....##.......... ;1
dg .......##....... ;2
dg ........##...... ;3
dg ......#..#...... ;4
dg ....#.###....... ;5
dg .....###........ ;6
dg ........#....... ;7
dg .......###...... ;8
dg ....#.####...... ;9
dg ...###.##....... ;10
dg ...##.#...#..... ;11
dg .....#.##.#..... ;12
dg ....##....#..... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_gnewwilly11
dg ................ ;0
dg .....##......... ;1
dg .....##.##...... ;2
dg .........##..... ;3
dg .......#..#..... ;4
dg .....#.###...... ;5
dg ......###....... ;6
dg ...##....#...... ;7
dg ...##.####...... ;8
dg .....####....... ;9
dg ..........#..... ;10
dg .....#####.#.... ;11
dg ....##..##.#.... ;12
dg ....##.......... ;13
dg ................ ;14
dg ...###.......... ;15
gfx_gnewwilly12
dg ................ ;0
dg ................ ;1
dg ......##........ ;2
dg ......##.##..... ;3
dg ..........##.... ;4
dg ........#..#.... ;5
dg ......#.###..... ;6
dg .......###...... ;7
dg ..........#..... ;8
dg .....##.####.... ;9
dg .....##.###..... ;10
dg ................ ;11
dg ......##.#.#.... ;12
dg .....#.####.#... ;13
dg ........##..#... ;14
dg ....###......... ;15
gfx_gnewwilly13
dg .......##....... ;0
dg .......##.##.... ;1
dg ...........##... ;2
dg .........#..#... ;3
dg .......#.###.... ;4
dg ........##...... ;5
dg ...........###.. ;6
dg ......#..#...##. ;7
dg .......##..##.#. ;8
dg .......###.##... ;9
dg ......#####..... ;10
dg .........####... ;11
dg .....###..###... ;12
dg ..........##.... ;13
dg ............#... ;14
dg ..........##.... ;15
gfx_gnewwilly14
dg ........##...... ;0
dg ........##.##... ;1
dg ............##.. ;2
dg ..........#..#.. ;3
dg ........#.###... ;4
dg .........###.... ;5
dg .............##. ;6
dg .......#..#.#### ;7
dg ........###.#... ;8
dg .......####...## ;9
dg .......#..###.## ;10
dg .......#####.... ;11
dg ..........###... ;12
dg ......###..##... ;13
dg ................ ;14
dg ..........###... ;15
gfx_gnewwilly15
dg .........##..... ;0
dg .........##.##.. ;1
dg .............##. ;2
dg ...........#..#. ;3
dg .........#.###.. ;4
dg ..........###... ;5
dg ................ ;6
dg ........#..#.##. ;7
dg .........##.#### ;8
dg ........####..## ;9
dg ........#..##... ;10
dg ........####..## ;11
dg .........####.## ;12
dg .........##.##.. ;13
dg ................ ;14
dg ........##.###.. ;15
ALIGN 256
collision_map:
REPT 9
db 1
REPT 30
db 0
ENDR
db 1
ENDR
db 1
REPT 4
db 0
ENDR
REPT 22
db 2
ENDR
REPT 4
db 0
ENDR
db 1
db 1
REPT 30
db 0
ENDR
db 1
db 1
REPT 30
db 2
ENDR
db 1
db 1
REPT 30
db 0
ENDR
db 1
db 1
REPT 4
db 0
ENDR
REPT 22
db 2
ENDR
REPT 4
db 0
ENDR
db 1
db 1
REPT 20
db 0
ENDR
db 3
REPT 9
db 0
ENDR
db 1
db 1
REPT 30
db 2
ENDR
db 1
ASSERT $ - collision_map == 512
gfx_8x8page:
gfx_platform0 ; Spectrum platform sprite1
dg ######## ; ff
dg ######## ; ff
dg ##.##.## ; db
dg ###.###. ; ee
dg ##...#.# ; c5
dg .#...... ; 40
dg ........ ; 00
dg ........ ; 00
gfx_wall0 ; Spectrum wall sprite2
dg ..#...#. ; 22
dg ######## ; ff
dg #...#... ; 88
dg ######## ; ff
dg ..#...#. ; 22
dg ######## ; ff
dg #...#... ; 88
dg ######## ; ff
gfx_spiky0 ; Spectrum bush sprite3
dg .#...#.. ; 44
dg ..#.#... ; 28
dg #..#.#.. ; 94
dg .#.#...# ; 51
dg ..##.#.# ; 35
dg ##.#.##. ; d6
dg .#.##... ; 58
dg ...#.... ; 10
gfx_platform1 ; Menagerie platform sprite4
dg ######## ; ff
dg ######## ; ff
dg .##..##. ; 66
dg #..##..# ; 99
dg .##..##. ; 66
dg #..##..# ; 99
dg ######## ; ff
dg ........ ; 00
ALIGN 256
tbl_rows
REPT 24, row
DWXYTOSCRADDR 0, row*8
ENDR
ALIGN 2
willy_xpos db 8
willy_ypos db 104
willy_oldpos db 8, 104
willy_facing db 1 ; facing. 1 for right, -1 for left
ALIGN 256 ; align this for faster access
level_tiles:
dw gfx_wall0 ; collision map 1
dw gfx_platform0 ; collision map 2
dw gfx_spiky0 ; collision map 3
dw gfx_platform1 ; collision map 4
IF 0
dg ................ ;0
dg ................ ;1
dg ................ ;2
dg ................ ;3
dg ................ ;4
dg ................ ;5
dg ................ ;6
dg ................ ;7
dg ................ ;8
dg ................ ;9
dg ................ ;10
dg ................ ;11
dg ................ ;12
dg ................ ;13
dg ................ ;14
dg ................ ;15
ENDIF
Pretty confident I will be able to update up to 4 guardians per frame and still run at 50fps. Max guardians is 8 but I only need to update half of them per frame since usual update speed is every other frame now Willy has 8 frames of animation. I may be able to update all 8 if I am clever about the order I redraw things.
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
That's how much time it takes (black border) to update the tune though when that goes off (every 4 frames). So I definitely don't want to do expensive stuff on a frame the tune may be played lol So make sure the solar power beams are processed on odd numbered frames when the tune can't be playing.
If you want to add the tune to the code, add this to the end of the mainloop (before jp mainloop). This was Matthew Smith's code IIRC.
Code: Select all
ld hl, framecounter
inc (hl)
; play tune
ld a, (tune_tick)
dec a
ld (tune_tick), a
jr nz, .skipnote
ld a, (tune_offset)
inc a
ld (tune_offset), a
ld a, 4
.playnote
ld (tune_tick), a
ld a, (tune_offset)
and #7e
rrca
ld e, a
ld d, 0
ld hl, tune_data
add hl, de
;ld a, (bdr_colour)
xor a
ld e, (hl)
ld bc, 3
.tuneloop
out (#fe), a
dec e
jr nz, .noflip
ld e, (hl)
xor #18
.noflip
djnz .tuneloop
dec c
jr nz, .tuneloop
.skipnote
willy_facing db 1
Code: Select all
framecounter db 0
tune_offset db 0
tune_tick db 4
tune_data db #80, #72, #66, #60, #56, #66, #56, #56, #51, #60, #51, #51, #56, #66
db #56, #56, #80, #72, #66, #60, #56, #66, #56, #56, #51, #60, #51, #51
db #56, #56, #56, #56, #80, #72, #66, #60, #56, #66, #56, #56, #51, #60
db #51, #51, #56, #66, #56, #56, #80, #72, #66, #60, #56, #66, #56, #40
db #56, #66, #80, #66, #56, #56, #56, #56
To remove the flicker (but lose the tune timing info)
replace this
Code: Select all
;ld a, (bdr_colour)
xor a
Code: Select all
;ld a, (bdr_colour)
;xor a
ld a, 7
EDIT2: Hmm the tune sounds the correct speed if I replace tune_tick initial value with 5 and reset it to 5 when it gets reset. Does Manic Miner really only update every 5 frames (10 fps)??? Download link is denied
That's not good since 5 is a PRIME NUMBER any prime > 2 (the oddest prime!) will alternate between updating on odd and even frames
Setting the initial tick/reinit tick to 6 makes the tune too slow
- Lee Bee
- Dynamite Dan
- Posts: 1567
- Joined: Sat Nov 16, 2019 11:01 pm
- Location: Devon, England
- Contact:
Re: how about a more modern miner willy sprite?
Speaking of tunes, I believe AY tunes are less processor-intensive. If you wanted one making, I can gladly provide it! I've already composed a brand new 8-minute tune for Jet Set Willy and I'd happily do a Manic Miner one, too.
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
Yeah they are much less processor intensive (just need to do some stuff in an interrupt I think), but I've never programmed for the 128K and I still want to make sure the 48K version is good as well. Once the 48K version is playable we can think about that. You can compose an AY tune in meantime or dig out an old one you have if you like. EDIT: 8 minutes long sounds a bit like it will eat a lot of memory though, lol
The 48K beeper really does suck it's basically just a doorbell circuit lol
I'm not too sure about at least one of the animation frames... specifically this one
Which I think needs at least a hint of him having another leg.
Anyone who wants to help out should definitely download sjasmplus if they haven't got it already (since that is what I use to build the code and it's an excellent assembler) to compile the source code so they can check it out themselves btw.
I'm also adding a Copyright message to the source this is it so far
Which I can change on request of contributors.
All you need to do to be added to the copyright message is to make a contribution of course!
My policy on this source code is that it will be freely available and anyone can do what they like with it (maybe setup a GIT repo once it is in a playable state so people can fork the source code if they like)... I assume no one would have a problem with that (free and available for anyone to modify as they see fit). As long as they keep the copyright message of course and include the full source with any binaries.
I'll probably think about doing a crap level editor but once I explain the level format anyone is welcome to have a go at writing one (I won't spend much time on it until project is done I think). Note: level format may change since I know I can compress it better than I did previously (e.g. packing the level name string into 5 bits per char instead of 8 bits), etc.
I may even double compress the levels with Einar's ZX0 (?) compressor at some point. (i.e. I'll run length compress it like I do atm and then compress that data afterwards). I'm budgeting 8K for level data (addresses #6000 to #7FFF) but I can easily change that to allow more level data. Note that graphics data is not part of level data (unlike in MM original version).
All 20 levels of Manic Miner with my compression scheme used up 4605 bytes (which is a bit too much really, really want to allow 80 levels if poss!).
Maybe 8192 - 4605 bytes = 3587 bytes. It's way past beer o' clock. I think that is right, I think it is 4605 bytes free in the 8K budget.
Since I am not planning on using a backbuffer this time (which was at least 5K wasted memory) I will probably up the level data budget to at least 12K.
The 48K beeper really does suck it's basically just a doorbell circuit lol
I'm not too sure about at least one of the animation frames... specifically this one
Which I think needs at least a hint of him having another leg.
Anyone who wants to help out should definitely download sjasmplus if they haven't got it already (since that is what I use to build the code and it's an excellent assembler) to compile the source code so they can check it out themselves btw.
I'm also adding a Copyright message to the source this is it so far
Code: Select all
; Original game by Matthew Smith (C) Bug Byte 1983, (C) 1983 Software Projects
; Engine Rewrite (C) 2010-2024 ParadigmShifter (aka Paradigm Shifter on WoS): https://spectrumcomputing.co.uk/forums/memberlist.php?mode=viewprofile&u=2484
; Miner Willy 8 frame animation sprites: (C) 2024 gabriel amore (Spectrum Computing forum) https://spectrumcomputing.co.uk/forums/memberlist.php?mode=viewprofile&u=959
All you need to do to be added to the copyright message is to make a contribution of course!
My policy on this source code is that it will be freely available and anyone can do what they like with it (maybe setup a GIT repo once it is in a playable state so people can fork the source code if they like)... I assume no one would have a problem with that (free and available for anyone to modify as they see fit). As long as they keep the copyright message of course and include the full source with any binaries.
I'll probably think about doing a crap level editor but once I explain the level format anyone is welcome to have a go at writing one (I won't spend much time on it until project is done I think). Note: level format may change since I know I can compress it better than I did previously (e.g. packing the level name string into 5 bits per char instead of 8 bits), etc.
I may even double compress the levels with Einar's ZX0 (?) compressor at some point. (i.e. I'll run length compress it like I do atm and then compress that data afterwards). I'm budgeting 8K for level data (addresses #6000 to #7FFF) but I can easily change that to allow more level data. Note that graphics data is not part of level data (unlike in MM original version).
All 20 levels of Manic Miner with my compression scheme used up 4605 bytes (which is a bit too much really, really want to allow 80 levels if poss!).
Maybe 8192 - 4605 bytes = 3587 bytes. It's way past beer o' clock. I think that is right, I think it is 4605 bytes free in the 8K budget.
Since I am not planning on using a backbuffer this time (which was at least 5K wasted memory) I will probably up the level data budget to at least 12K.
- gabriele amore
- Microbot
- Posts: 183
- Joined: Thu Apr 16, 2020 11:28 pm
- Location: Palermo
Re: how about a more modern miner willy sprite?
love the way this is takong shape!
Get my AY games here https://www.dropbox.com/sh/tfo83j5lzwmh ... Kkk7a?dl=0
Re: how about a more modern miner willy sprite?
you can have AY music on 48K with Fuller device! ;-) actually, you can detect if AY is present (i can dig the code from XTE if you want to). there is nothing 128K-specific, just plain OUTs to AY ports.ParadigmShifter wrote: ↑Mon Jun 24, 2024 3:01 am Yeah they are much less processor intensive (just need to do some stuff in an interrupt I think), but I've never programmed for the 128K and I still want to make sure the 48K version is good as well.
- MustardTiger
- Microbot
- Posts: 143
- Joined: Tue May 02, 2023 8:05 pm
Re: how about a more modern miner willy sprite?
Most of the tiles in a level are blank so not storing those at all would make levels more compressable.ParadigmShifter wrote: ↑Mon Jun 24, 2024 3:01 am
All 20 levels of Manic Miner with my compression scheme used up 4605 bytes (which is a bit too much really, really want to allow 80 levels if poss!).
Maybe 8192 - 4605 bytes = 3587 bytes. It's way past beer o' clock. I think that is right, I think it is 4605 bytes free in the 8K budget.
You could store levels as a list of spans of blocks. So data might look like this:
startx,starty,blocktype,direction(right or down),numblocks
Central cavern is essentially ~20 of these spans. If the data above is compressed into 18 bits (5:4:3:1:5) that would be ~60bytes. Add some more bytes for enemy positions etc.
Last edited by MustardTiger on Mon Jun 24, 2024 11:33 am, edited 1 time in total.
Re: how about a more modern miner willy sprite?
Yeah but an 8 minute AY symphony probably isn't going to fit in 48K along with the rest of the game.
Re: how about a more modern miner willy sprite?
dunno, tracker files are not that big. pt3 player (if i remember right) is only ~3000 ts, and the song will take only several kbs.
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
Yeah that's how I did it but I can compress it better I think. I can pack the level name better at least. I can probably pack row and column into less bits but I went for a readable format which is easily edited rather than a binary version which was hard to editMustardTiger wrote: ↑Mon Jun 24, 2024 11:27 am Most of the tiles in a level are blank so not storing those at all would make levels more compressable.
You could store levels as a list of spans of blocks. So data might look like this:
startx,starty,blocktype,direction(right or down),numblocks
Central cavern is essentially ~20 of these spans. If the data above is compressed into 18 bits (5:4:3:1:5) that would be ~60bytes. Add some more bytes for enemy positions etc.
Code: Select all
Central_Cavern:
dc "Central Cavern"
; border/paper
db 2
; cell graphics - these are 1 byte each
celltype gfx_platform0
celltype gfx_wall0
celltype gfx_spiky0
celltype gfx_crumbly0
celltype gfx_platform0
celltype gfx_platform0
celltype gfx_spiky1
celltype gfx_conveyor0
celltype gfx_conveyor0
; cell attribs. 1 byte each
IPB 2, 0, 1
IPB 6, 2, 0
IPB 4, 0, 1
IPB 2, 0, 0
IPB 0, 0, 0
IPB 0, 0, 0
IPB 5, 0, 0
IPB 4, 0, 0
IPB 4, 0, 0
; willy start position x, y. bit 4 of y is set if facing left
db 2, 13
; exit position
db 29, 13
; exit colour
IPB 6, 1, 0
; keytype
keytype gfx_key0
db 5 ; number of keys
db 9, 0
db 29, 0
db 16, 1
db 24, 4
db 30, 6
; guardians
db 1 ; number of guardians
db gfx_robot0/256, 0, 8, 7, 8, 15, 64+6, 0
; single blocks
db SPIKY_A, 23, 4
db SPIKY_A, 27, 4
db SPIKY_A, 21, 8
db SPIKY_A, 12, 12
db SPIKY_B, 11, 0
db SPIKY_B, 16, 0
; repeat blocks: platforms
db HORZ_REPEAT|PLATFORM_A, 1, 5, 30
db HORZ_REPEAT|PLATFORM_A, 1, 7, 3
db HORZ_REPEAT|PLATFORM_A, 1, 9, 4
db HORZ_REPEAT|PLATFORM_A, 29, 10, 2
db HORZ_REPEAT|PLATFORM_A, 28, 12, 3
db HORZ_REPEAT|PLATFORM_A, 5, 13, 15
db HORZ_REPEAT|PLATFORM_A, 1, 15, 30
; crumbly platforms
db HORZ_REPEAT|CRUMBLY, 14, 5, 4
db HORZ_REPEAT|CRUMBLY, 19, 5, 4
db HORZ_REPEAT|CRUMBLY, 23, 12, 5
; walls
db HORZ_REPEAT|WALL_A, 17, 8, 3
db HORZ_REPEAT|WALL_A, 20, 12, 3
; conveyor
db HORZ_REPEAT|CONVEYOR_L, 8, 9, 20
db #ff ; terminator
You can also "overwrite" parts with later defined tiles so I do that for the top platform in that level (I have a 30 length repeating tile but then overwrite 2 sections with repeating crumbly tile defs).
All the levels in that format was 3587 bytes so on average 180 bytes/level.
I can make the tile list variable size (I can indicate last tile by setting the FLASH bit of the colour). Or I can put the colour first and have a convention for "end of list" if we may want flashing level tiles I suppose.
I can pack num keys, num guardians, and some other fields into bits rather than using whole bytes. I can probably have a repeating set of tile definitions of same type so I could specify all the HORZ_REPEAT|PLATFORM_A at once (just need 1 bit for "that was the last tile of that type").
I can pack the level name into 5 bits per char. (0=space, 1-26=A-Z, always have an uppercase letter as first letter and after each space, except for special codes 27="of the", 28="the" and I need 29=apostrophe (for Amoebatron's Revenge) and I can use 30 = ? too (for "The Final Barrier?" which adds a question mark since it was not intended to be the last level). I can use 31 as "end of string" token. I could remove the "of" and "of the" codes and make them "change the capitalisation rule for next char" and "escape code - any character can follow" if wanted to have JSW room names which have more chars used "[" I think? Or maybe that was JSW2, and definitely "<" and ">" IIRC.
I may write a packer on PC in C# so it takes the easy to read format and outputs a .bin file.
Last edited by ParadigmShifter on Mon Jun 24, 2024 2:37 pm, edited 1 time in total.
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
I'll probably stick with that format for now anyway (I may change it so the level tile set can be variable size though - some levels don't use all 9 tile definitions so can save a few bytes there, and I may want to add more tile types for variety), since I already have code to set up the levels defined in that format.
I may also do a "repeating block" definition to handle stuff like the Skylab level (where left and right side of the platforms are different, and they repeat every 8 across, since that's how the skylabs work), if I have bits to spare.
Will defo add "horizontal and vertical repeat" flag for Vat, Warehouse, and the crumbly chimney in the Cold Room.
Max guardians will be 8 (don't think there's any chance of running at 50fps otherwise). Max keys is currently 8 I think but I can probably support up to 16 (JSW2 has up to 16 keys per level IIRC). I may make it so keys don't all have to be the same graphics as well.
Space saved by removing the exit definition can be used for JSW room connections (up/down/left/right room). EDIT: It seems I don't specify the exit graphics per level they are just sequential in memory... may change that if I add more levels/want to reuse exit graphics. That will use 1 extra byte per level but will be more flexible.
All levels in Manic Miner have the first wall tile at the right and left edge, you don't need to define that in the data either. Obvs JSW levels wouldn't have that.
I may also do a "repeating block" definition to handle stuff like the Skylab level (where left and right side of the platforms are different, and they repeat every 8 across, since that's how the skylabs work), if I have bits to spare.
Will defo add "horizontal and vertical repeat" flag for Vat, Warehouse, and the crumbly chimney in the Cold Room.
Max guardians will be 8 (don't think there's any chance of running at 50fps otherwise). Max keys is currently 8 I think but I can probably support up to 16 (JSW2 has up to 16 keys per level IIRC). I may make it so keys don't all have to be the same graphics as well.
Space saved by removing the exit definition can be used for JSW room connections (up/down/left/right room). EDIT: It seems I don't specify the exit graphics per level they are just sequential in memory... may change that if I add more levels/want to reuse exit graphics. That will use 1 extra byte per level but will be more flexible.
All levels in Manic Miner have the first wall tile at the right and left edge, you don't need to define that in the data either. Obvs JSW levels wouldn't have that.
- Lee Bee
- Dynamite Dan
- Posts: 1567
- Joined: Sat Nov 16, 2019 11:01 pm
- Location: Devon, England
- Contact:
Re: how about a more modern miner willy sprite?
I always prefer to write something specifically tailored to the game. With JSW, I took the original short tune from John Elliott's 128k version, then expanded it into something much bigger, and had lots of fun. Threw in a bit of Moonlight Sonata near the end for good measure. I even did a part where you can sing along "Jet Set Willy" to the tune Keep meaning to share it so it can be used in a mod.ParadigmShifter wrote: ↑Mon Jun 24, 2024 3:01 am You can compose an AY tune in meantime or dig out an old one you have if you like.
Yeah, I got a little carried away with that one. Generally I prefer to have some rough idea of how much memory I'd have before I begin. Busy for the next few days, but I will start coming up with ideas after that.ParadigmShifter wrote: ↑Mon Jun 24, 2024 3:01 am EDIT: 8 minutes long sounds a bit like it will eat a lot of memory though, lol
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
I think I may as well do the level data stuff tonight when I carry on. I'll add 2 levels for now (Central Cavern obvs, and also Amoebatron's Revenge since that is the level with 8 guardians and is the one I am most worried about for draw speed). Solar Power Generator is another worry not only does it have lots of Guardians (7) it also has the solar beam thing going on as well.
I'm definitely going to go with the "level tile" select thing so we can save space by having multiple position/repeat stuff. For horizontal/vertical repeats I can store xpos, ypos in 9 bits (for MM levels anyway, which are 32x16 = 512 cells big). Add another 5 bits for the repeat count leaves me with 2 spare bits so can use one of them as "this is the last definition with that tile type". That will save quite a few bytes. I wouldn't be able to do both horizontal and vertical repeats (i.e. draw a rectangle of same tile) that way though since it needs an extra 4 bits for the height, unless I think of something clever to do
I'll probably put the level names in a separate list which is packed into 5 bits per char when the code starts. I can stash those in the space where the collision map lives so they won't use any space after they get compressed (but it limits text size to 512 bytes total). I may have more buffers which can be used though if 512 bytes isn't enough.
Long term I may add a proportional font and renderer for that so level names could be longer than 32 characters. Not going to do that until the game is playable though.
I'm definitely going to go with the "level tile" select thing so we can save space by having multiple position/repeat stuff. For horizontal/vertical repeats I can store xpos, ypos in 9 bits (for MM levels anyway, which are 32x16 = 512 cells big). Add another 5 bits for the repeat count leaves me with 2 spare bits so can use one of them as "this is the last definition with that tile type". That will save quite a few bytes. I wouldn't be able to do both horizontal and vertical repeats (i.e. draw a rectangle of same tile) that way though since it needs an extra 4 bits for the height, unless I think of something clever to do
I'll probably put the level names in a separate list which is packed into 5 bits per char when the code starts. I can stash those in the space where the collision map lives so they won't use any space after they get compressed (but it limits text size to 512 bytes total). I may have more buffers which can be used though if 512 bytes isn't enough.
Long term I may add a proportional font and renderer for that so level names could be longer than 32 characters. Not going to do that until the game is playable though.
- Lee Bee
- Dynamite Dan
- Posts: 1567
- Joined: Sat Nov 16, 2019 11:01 pm
- Location: Devon, England
- Contact:
Re: how about a more modern miner willy sprite?
Extra levels vs music:
I love the idea of this new version having extra levels, which would make this title worth playing. I definitely think the game should have 20 extra levels, if not more. But, obviously, more levels leaves less room for AY music. So at some point, someone will need to make a definitive decision about how many levels there will be, and therefore how much space is left for music (which will depend how well the level compression is working).
Unlike with Jet Set Willy, I don't think one long piece of music is right for this game. Ideally I'd love to create between 2 and 5 short, simple in-game tunes which cycle between levels. The first tune would be a more polished and less irritating version of the original beeper tune (though without losing the fun energy of the original). Would also be nice to do a version of the Blue Danube (from the title screen). And then, it would also be nice to add a short "game complete" tune to provide a more rewarding ending (before the game loops back to level 1).
If pressed, I could do something with just a couple of k, though not much. ~4k would be better, ~8k would be far more comfortable, and 12k+ would be fantastic as I could 'go to town' more with the music. (Of course, all music would need to be approved by you guys.)
I love the idea of this new version having extra levels, which would make this title worth playing. I definitely think the game should have 20 extra levels, if not more. But, obviously, more levels leaves less room for AY music. So at some point, someone will need to make a definitive decision about how many levels there will be, and therefore how much space is left for music (which will depend how well the level compression is working).
Unlike with Jet Set Willy, I don't think one long piece of music is right for this game. Ideally I'd love to create between 2 and 5 short, simple in-game tunes which cycle between levels. The first tune would be a more polished and less irritating version of the original beeper tune (though without losing the fun energy of the original). Would also be nice to do a version of the Blue Danube (from the title screen). And then, it would also be nice to add a short "game complete" tune to provide a more rewarding ending (before the game loops back to level 1).
If pressed, I could do something with just a couple of k, though not much. ~4k would be better, ~8k would be far more comfortable, and 12k+ would be fantastic as I could 'go to town' more with the music. (Of course, all music would need to be approved by you guys.)
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
For 128K you can probably easily have 12K of music.
48K we're limited to Matthew Smith's beeper tune I think. Maths is needed to work out what the wave frequencies are, they are only 8 bits precision though, so there's definitely not much frequency range.
May be able to make the tune longer or have 16 bit precision in the notes for 48K... I don't know much about how the beeper works.
It does take a lot of time on 48K to wobble the beeper though but I was experimenting with it last night... Doing the speaker wobble loop twice instead of 3 times (so 256*2 iterations instead of 256*3 iterations) sounds fine to me and that's obviously 33% faster.
The original tune sounds best updating every 5 frames to me (4 is a bit too fast, 6 is too slow). Odd numbers are bad though but doing a compromise (play 3 loop iterations on odd multiples of 5, play 2 loop iterations on even multiples of 5) also sounded good to my ears.
Ideally I would like at least 60 levels (so could cope with JSW map), I have changed the run length encoding of the level a bit (and there is room for more improvement) so I think that is doable in 8K original level data budget, we will see. 80 levels would be my preference though.
JSW2 has a whopping 132 rooms, but many rooms are quite sparse so would compress better I think.
EDIT: Don't get too excited about the mention of JSW though - I think that is a terrible game compared to Manic Miner and porting it would mean I have to play it while testing lol I do like the ropes though! (And the lifts in JSW2 would be nice to add as well).
JSW and JSW2 has some important engine differences though (can have more than 1 horizontal and vertical guardian per room), also guardians can move behind items (so they may need to be redrawn instead of just changing colour like in MM).
Once the code has been ported (from my old source to new engine) I will have more of an idea how much memory we have to work with.
I also need to allow extra space for the frontend.
MM also has 2K of static image data + 256 bytes off attributes for that image, which is used for the title screen and also the top third of "The Final Barrier" level. I don't want to compress that really (cos then it will be variable length for different images, although the image size will of course go down so it might be ok).
I'll probably drop in a multichannel music player for 48K title screen so can get rid of the monstrosity that was Matthew Smith's version of the Blue Danube. That would mean I probably can't animate the keys on the keyboard when a note plays though.
Progress yesterday, didn't post an update since there wasn't much, mainly thinking about the level data format.
So just the exit position and the keys. I can compress to key data to 9 bits per key instead of the 16 bits I am currently using, so 8 keys will fit into 9 bytes instead of 16 (and 16 keys, which I believe is the max for JSW2, will fit into 18 bytes). But I'd probably compress that using a PC tool.
I've also got a basic level tile set going on but I didn't get around to drawing any parts of the level.
It will use a "brush" which stays the same until you change tile type which will also save a lot of memory.
Once I have a couple of levels defined in this format I will post some stats about what kind of compression we are achieving.
In the 2010 version of the level format, Central Cavern compressed into 130 bytes (and 14 of those are the string "Central Cavern", which I can compress into 10 bytes if I use 5 bits per character).
48K we're limited to Matthew Smith's beeper tune I think. Maths is needed to work out what the wave frequencies are, they are only 8 bits precision though, so there's definitely not much frequency range.
May be able to make the tune longer or have 16 bit precision in the notes for 48K... I don't know much about how the beeper works.
It does take a lot of time on 48K to wobble the beeper though but I was experimenting with it last night... Doing the speaker wobble loop twice instead of 3 times (so 256*2 iterations instead of 256*3 iterations) sounds fine to me and that's obviously 33% faster.
The original tune sounds best updating every 5 frames to me (4 is a bit too fast, 6 is too slow). Odd numbers are bad though but doing a compromise (play 3 loop iterations on odd multiples of 5, play 2 loop iterations on even multiples of 5) also sounded good to my ears.
Ideally I would like at least 60 levels (so could cope with JSW map), I have changed the run length encoding of the level a bit (and there is room for more improvement) so I think that is doable in 8K original level data budget, we will see. 80 levels would be my preference though.
JSW2 has a whopping 132 rooms, but many rooms are quite sparse so would compress better I think.
EDIT: Don't get too excited about the mention of JSW though - I think that is a terrible game compared to Manic Miner and porting it would mean I have to play it while testing lol I do like the ropes though! (And the lifts in JSW2 would be nice to add as well).
JSW and JSW2 has some important engine differences though (can have more than 1 horizontal and vertical guardian per room), also guardians can move behind items (so they may need to be redrawn instead of just changing colour like in MM).
Once the code has been ported (from my old source to new engine) I will have more of an idea how much memory we have to work with.
I also need to allow extra space for the frontend.
MM also has 2K of static image data + 256 bytes off attributes for that image, which is used for the title screen and also the top third of "The Final Barrier" level. I don't want to compress that really (cos then it will be variable length for different images, although the image size will of course go down so it might be ok).
I'll probably drop in a multichannel music player for 48K title screen so can get rid of the monstrosity that was Matthew Smith's version of the Blue Danube. That would mean I probably can't animate the keys on the keyboard when a note plays though.
Progress yesterday, didn't post an update since there wasn't much, mainly thinking about the level data format.
So just the exit position and the keys. I can compress to key data to 9 bits per key instead of the 16 bits I am currently using, so 8 keys will fit into 9 bytes instead of 16 (and 16 keys, which I believe is the max for JSW2, will fit into 18 bytes). But I'd probably compress that using a PC tool.
I've also got a basic level tile set going on but I didn't get around to drawing any parts of the level.
It will use a "brush" which stays the same until you change tile type which will also save a lot of memory.
Once I have a couple of levels defined in this format I will post some stats about what kind of compression we are achieving.
In the 2010 version of the level format, Central Cavern compressed into 130 bytes (and 14 of those are the string "Central Cavern", which I can compress into 10 bytes if I use 5 bits per character).
- ParadigmShifter
- Dynamite Dan
- Posts: 1296
- Joined: Sat Sep 09, 2023 4:55 am
Re: how about a more modern miner willy sprite?
Graphics that got added yesterday
Exit portal for Central Cavern. Looks like a shreddie.
Some new 8x8 level tiles (and the old ones as well)
So if anyone wants to have a go at improving the graphics on those you are welcome to do that.
Tonight I will probably get around to dropping in the Manic Mining Robot from Central Cavern, as well as the Amoebatrons from Amoebatrons' Revenge, and the weird pole on a wheel enemy from that level too, so I will post the graphics data for those once I have converted them to DG format.
EDIT: Some more stats: Current code size in bytes is just 1009, so less than 1KB. 326 bytes of that is the level unpacking (work in progress). That will go up quite quickly once I start adding the fast 16x16 sprite blitting routines which will be unrolled "up the wazoo" and abuse the stack for fast data copying.
Data size (not including level data which I will track separately) is currently 3400 bytes, but there are 4 versions of the Willy sprite and I only need 1 or 2 max of those, if I only use 1 version data will be reduced by 1536 bytes. Each 8 frame enemy will use 256 bytes of memory. (I could halve that for vertical guardians by mirroring them on entry to level though). 512 bytes of that is the collision map data. If I add a custom font that will be 768 bytes as well. The static image for "The Final Barrier" level will add an extra 2.5K as well.
There's also a lot of gaps in the data because I have aligned some tables for faster access.
Code: Select all
; exit portals
gfx_exit0 ; Central Cavern exit
dg ################ ;0 ffff
dg #..#..#..#..#..# ;1 9249
dg #.##.##.##.##.## ;2 b6db
dg ################ ;3 ffff
dg #..#..#..#..#..# ;4 9249
dg #.##.##.##.##.## ;5 b6db
dg ################ ;6 ffff
dg #..#..#..#..#..# ;7 9249
dg #.##.##.##.##.## ;8 b6db
dg ################ ;9 ffff
dg #..#..#..#..#..# ;a 9249
dg #.##.##.##.##.## ;b b6db
dg ################ ;c ffff
dg #..#..#..#..#..# ;d 9249
dg #.##.##.##.##.## ;e b6db
dg ################ ;f ffff
Some new 8x8 level tiles (and the old ones as well)
Code: Select all
gfx_platform0 ; Spectrum platform
dg ######## ; ff
dg ######## ; ff
dg ##.##.## ; db
dg ###.###. ; ee
dg ##...#.# ; c5
dg .#...... ; 40
dg ........ ; 00
dg ........ ; 00
gfx_platform1 ; Menagerie platform
dg ######## ; ff
dg ######## ; ff
dg .##..##. ; 66
dg #..##..# ; 99
dg .##..##. ; 66
dg #..##..# ; 99
dg ######## ; ff
dg ........ ; 00
gfx_wall0 ; Spectrum wall
dg ..#...#. ; 22
dg ######## ; ff
dg #...#... ; 88
dg ######## ; ff
dg ..#...#. ; 22
dg ######## ; ff
dg #...#... ; 88
dg ######## ; ff
gfx_spiky0 ; Spectrum bush
dg .#...#.. ; 44
dg ..#.#... ; 28
dg #..#.#.. ; 94
dg .#.#...# ; 51
dg ..##.#.# ; 35
dg ##.#.##. ; d6
dg .#.##... ; 58
dg ...#.... ; 10
gfx_spiky1 ; Spectrum Stalactite
dg ######## ; ff
dg #######. ; fe
dg .######. ; 7e
dg .#####.. ; 7c
dg .#..##.. ; 4c
dg .#..##.. ; 4c
dg ....##.. ; 0c
dg ....#... ; 08
gfx_crumbly0 ; Spectrum crumbly
dg ######## ; ff
dg ##.##.## ; db
dg #.#..#.# ; a5
dg ..#..#.. ; 24
dg .#.#..#. ; 52
dg ..#..... ; 20
dg ....#... ; 80
dg ........ ; 00
gfx_conveyor0 ; Spectrum conveyor
dg ####.... ; f0
dg .##..##. ; 66
dg ####.... ; f0
dg .##..##. ; 66
dg ........ ; 00
dg #..##..# ; 99
dg ######## ; ff
dg ........ ; 00
gfx_key0 ; Spectrum key sprite
dg ..##.... ; 30
dg .#..#... ; 48
dg #...#... ; 88
dg #..#.... ; 90
dg .##.#... ; 68
dg .....#.. ; 04
dg ....#.#. ; 0a
dg .....#.. ; 04
Tonight I will probably get around to dropping in the Manic Mining Robot from Central Cavern, as well as the Amoebatrons from Amoebatrons' Revenge, and the weird pole on a wheel enemy from that level too, so I will post the graphics data for those once I have converted them to DG format.
EDIT: Some more stats: Current code size in bytes is just 1009, so less than 1KB. 326 bytes of that is the level unpacking (work in progress). That will go up quite quickly once I start adding the fast 16x16 sprite blitting routines which will be unrolled "up the wazoo" and abuse the stack for fast data copying.
Data size (not including level data which I will track separately) is currently 3400 bytes, but there are 4 versions of the Willy sprite and I only need 1 or 2 max of those, if I only use 1 version data will be reduced by 1536 bytes. Each 8 frame enemy will use 256 bytes of memory. (I could halve that for vertical guardians by mirroring them on entry to level though). 512 bytes of that is the collision map data. If I add a custom font that will be 768 bytes as well. The static image for "The Final Barrier" level will add an extra 2.5K as well.
There's also a lot of gaps in the data because I have aligned some tables for faster access.