how about a more modern miner willy sprite?

Share graphical tips, notes and queries related to our favourite screen layout and its editors.
User avatar
clebin
Manic Miner
Posts: 992
Joined: Thu Jun 25, 2020 1:06 pm
Location: Vale of Glamorgan
Contact:

Re: how about a more modern miner willy sprite?

Post by clebin »

ketmar wrote: Sat Jun 22, 2024 4:57 pm gun! please, give him a gun! and some grenades! ;-)
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...
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

clebin wrote: Sun Jun 23, 2024 5:54 pm 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...
Well I'll be posting my code as I go along so feel free to mod it ;)
User avatar
ketmar
Manic Miner
Posts: 762
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: how about a more modern miner willy sprite?

Post by ketmar »

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! ;-)
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

Image

Quick and hacky implementation of collision map... so Willy can pass over objects in the collision map and it redraws them instead of erasing.
User avatar
gabriele amore
Microbot
Posts: 176
Joined: Thu Apr 16, 2020 11:28 pm
Location: Palermo

Re: how about a more modern miner willy sprite?

Post by gabriele amore »

ParadigmShifter wrote: Sun Jun 23, 2024 7:40 pm Image

Quick and hacky implementation of collision map... so Willy can pass over objects in the collision map and it redraws them instead of erasing.
looks lovely!
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

Looks better now I have unhacked it since the quick hack was make anything you moved over a spiky bush

Image

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_&#7)|((_y_&#C0)>>3))<<8)|((_x_&#1F)|((_y_&#38)<<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	
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.
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

These are the tile graphics from original MM I have used to far

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
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).
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

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)

Image

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.
User avatar
gabriele amore
Microbot
Posts: 176
Joined: Thu Apr 16, 2020 11:28 pm
Location: Palermo

Re: how about a more modern miner willy sprite?

Post by gabriele amore »

ParadigmShifter 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.
Yes on both counts
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

New graphics done then, again I have gone for the topmost Willy is always on the ground, one below it has midair frames.

Image

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_&#7)|((_y_&#C0)>>3))<<8)|((_x_&#1F)|((_y_&#38)<<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	
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.
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

Image

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
Then add these variables after
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
Beware that the border flickers if you do that so if you suffer from seizures probs best if you don't do that lol :)

To remove the flicker (but lose the tune timing info)

replace this

Code: Select all

	;ld a, (bdr_colour)
	xor a
with this

Code: Select all

	;ld a, (bdr_colour)
	;xor a
	ld a, 7
or if TIMING is 0: replace the LD A, 7 with LD A, 2

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 :(
User avatar
Lee Bee
Dynamite Dan
Posts: 1557
Joined: Sat Nov 16, 2019 11:01 pm
Location: Devon, England
Contact:

Re: how about a more modern miner willy sprite?

Post by Lee Bee »

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.
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

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

Image

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
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.
User avatar
gabriele amore
Microbot
Posts: 176
Joined: Thu Apr 16, 2020 11:28 pm
Location: Palermo

Re: how about a more modern miner willy sprite?

Post by gabriele amore »

love the way this is takong shape!
User avatar
ketmar
Manic Miner
Posts: 762
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: how about a more modern miner willy sprite?

Post by ketmar »

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.
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.
User avatar
MustardTiger
Microbot
Posts: 143
Joined: Tue May 02, 2023 8:05 pm

Re: how about a more modern miner willy sprite?

Post by MustardTiger »

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.
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.
Last edited by MustardTiger on Mon Jun 24, 2024 11:33 am, edited 1 time in total.
AndyC
Dynamite Dan
Posts: 1489
Joined: Mon Nov 13, 2017 5:12 am

Re: how about a more modern miner willy sprite?

Post by AndyC »

ketmar wrote: Mon Jun 24, 2024 11:08 am 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.
Yeah but an 8 minute AY symphony probably isn't going to fit in 48K along with the rest of the game.
User avatar
ketmar
Manic Miner
Posts: 762
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: how about a more modern miner willy sprite?

Post by ketmar »

AndyC wrote: Mon Jun 24, 2024 11:32 am Yeah but an 8 minute AY symphony probably isn't going to fit in 48K along with the rest of the game.
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.
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

MustardTiger 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.
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 edit

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
 
So it has repeat flag for blocks. I didn't do horizontal & vertical repeat last time I may add that this time (for levels like The Vat, The Warehouse).

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.
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

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.
User avatar
Lee Bee
Dynamite Dan
Posts: 1557
Joined: Sat Nov 16, 2019 11:01 pm
Location: Devon, England
Contact:

Re: how about a more modern miner willy sprite?

Post by Lee Bee »

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.
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 :D Keep meaning to share it so it can be used in a mod.
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
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.
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

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.
User avatar
Lee Bee
Dynamite Dan
Posts: 1557
Joined: Sat Nov 16, 2019 11:01 pm
Location: Devon, England
Contact:

Re: how about a more modern miner willy sprite?

Post by Lee Bee »

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.)
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

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.

Image

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).
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1245
Joined: Sat Sep 09, 2023 4:55 am

Re: how about a more modern miner willy sprite?

Post by ParadigmShifter »

Graphics that got added yesterday

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
Exit portal for Central Cavern. Looks like a shreddie.

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
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.
Post Reply