;================================
;=	Program:	Ultra Bomber (512 byte game)	=
;=	Author:		Dmitry Egorov				=
;=	Platform:	ZX-SPECTRUM				=
;=	Compiler:	sjasm						=
;=	Date:		26.10.2012					=
;================================

	DEVICE ZXSPECTRUM48



;================================
;=	Defines.									=
;================================

HouseBuffer=#8200
MaxLevel=18



;================================
;=	Start.									=
;================================

	ORG #8000

Start:
	; Increment level.
	ld		hl, #0100
	ld		a, (vLevel)
	inc		a
	cp		MaxLevel
	jr		c, .noreset
	ld		a, h
.noreset:
	ld		(vLevel), a
	add		a, 5
	ld		c, a

; Set bomb.
	ld		(vBombX), hl
	push	hl

; Set houses data in loop.
	ld		hl, (23672)
	ld		h, 7
	ld		de, HouseBuffer
	ld		b, 24

.nl_loop:
	ld		a, (hl)
	inc		hl
	and		31
	jr		z, .nl_loop
	cp		c
	jr		nc, .nl_loop
	ld		(de), a
	inc		de
.reget_color:
	ld		a, (hl)
	inc		hl
	and		%00111000
	jr		z, .reget_color
	ld		(de), a
	inc		de
	djnz		.nl_loop
	pop		de

.draw_level:
	call		DrawLevel
	ld		b, 50
.draw_plane:
	push	de
	ld		a, e
	ld		(DrawPlane.to_a+1), a
	ld		(.to_a2+1), a
	and		248
	rrca
	rrca
	rrca
	ld		e, a
	ld		hl, PlaneSpr
	call		DrawPlane

	ei
.halt_loop:
	halt
	djnz		.halt_loop

; Check houses on plane and bomb.
	di
	ld		c, 4
	ld		hl, HouseBuffer
	ld		ix, vBombX

.house_loop:
	ld		a, 22
	sub		(hl)
	cp		22
	jr		nc, .house_next
	ld		b, a
	cp		d
	jr		nc, .check_bomb
	ld		a, c
	sub		4
	cp		e
	jr		nc, .check_bomb

; Plane crashed, reset.
	pop		hl
	dec		d
	ld		e, 0
	ld		(ix), e
	jr		.draw_level

.check_bomb:
	ld		a, c
	cp		(ix)
	jr		nz, .house_next
	ld		a, b
	cp		(ix+1)
	jr		nc, .move_bomb
	dec		(hl)
	jr		z, .null_bomb
	dec		(ix+2)
	jr		z, .null_bomb

.house_next:
	inc		hl
	inc		hl
	inc		c
	ld		a, c
	cp		28
	jr		c, .house_loop

; Move bomb.
.move_bomb:
	ld		a, (ix)
	or		a
	jr		z, .set_bomb
.clear_bomb:
	call		DrawBomb0
	jr		c, .bomb_down

.null_bomb:
; Play sound.
	push	hl
 	ld		b, 5
 	xor		a

.snd_loop:
 	xor		16
	out		(254), a
	ld		c, a
 	ld		h, 3
	xor		e
	ld		l, a

.snd_pause:
	dec		hl
	ld		a, h
	or		l
 	jr		nz, .snd_pause
	ld		a, c
	djnz		.snd_loop
	pop		hl

	call		DrawBomb0
	ld		(ix), 0
	jr		.move_plane

; Try set bomb.
.set_bomb:
	ld		a, d
	cp		22
	jr		nc, .move_plane
.to_a2:
	ld		a, 0
	and		7
	jr		nz, .move_plane
	ld		a, #7F
	in		a, (254)
	rrca
	jr		c, .move_plane
	ld		hl, 1
	add		hl, de
	ld		(vBombX), hl
	ld		(ix+2), 4

.bomb_down:
	call		DrawBomb1

.move_plane:
; Clear plane.
	ld		hl, #4000
	call		DrawPlane
	pop		de
	inc		e
	inc		e
	ld		a, e
	cp		232
	jr		c, .next
	ld		a, d
	cp		22
	jp		z, Start
	inc		d
	ld		e, 0

.next:
	ld		b, 1
	jp		.draw_plane



;================================
;=	Find screen address.						=
;=	E = x, D = y								=
;=	DE = address								=
;================================

FindScreen:
	ld		a, d
	push	af
	and		248
	add		a, 64
	ld		d, a
	pop		af
	rrca
	rrca
	rrca
	and		224
	add		a, e
	ld		e, a
	ret



;================================
;=	Draw bomb								=
;=	in:	ix = data							=
;================================

DrawBomb0:
	ld		hl, #3D00
	jr		draw_bomb_next:

DrawBomb1:
	inc		(ix+1)
	ld		hl, BombSpr

draw_bomb_next:
	push	de
	ld		de, (vBombX)
	ld		a, %01101000
	call		Draw8x8
	ld		a, d
	cp		22
	pop		de
	ret



;================================
;=	Draw symbol 8x8							=
;=	E = x, D = y, hl = mem, a = color			=
;================================

Draw8x8:
	push	hl
	push	de
	push	bc
	push	af
	call		FindScreen
	ld		b, 8

.loop:
	ld		a, (hl)
	ld		(de), a
	inc		hl
	inc		d
	djnz		.loop

	pop		af
	or		a
	jr		z, .exit
	ld		c, a
	dec		d
	ld		a, d
	rrca 
	rrca
	rrca
	and		31
	add		a, 80
	ld		d, a
	ld		a, c
	ld		(de), a

.exit:
	pop		bc
	pop		de
	pop		hl
	ret



;================================
;=	Draw level.								=
;================================

DrawLevel:
; Clear screen.
	push	de
	ld		hl, #4000
	ld		de, #4001
	ld		bc, 6143
	ld		a, l
	out		(254), a
	ld		(hl), a
	ldir

; Paint sky.
	ld		(hl), %01101000
	ld		b, 3
	ldir

; Draw grass.
	ld		hl, Grass
	ld		d, #17
	ld		a, %00100110
	ld		b, 32

.lp_grass:
	call		Draw8x8
	inc		e
	djnz		.lp_grass

; Draw houses.
	ld		hl, HouseBuffer
	ld		de, #1604
	ld		b, 24

.lp_house:
	push	bc
	push	de
	ld		b, (hl)
	inc		hl
	ld		c, (hl)
	inc		hl
	ld		a, b
	or		a
	jr		z, .next
	ld		a, c
	push	hl
	ld		hl, HouseBlock

.loop:
	call		Draw8x8
	dec		d
	djnz		.loop
	pop		hl

.next:
	pop		de
	pop		bc
	inc		e
	djnz		.lp_house

	pop		de
	ret



;================================
;=	Draw plane.								=
;=	E = x (in pixels), D = y (in symbols)			=
;================================

DrawPlane:
	push	de
	push	bc
	call		FindScreen
	ld		(.to_sp+1), sp
	ld		sp, hl
	ex		de, hl

.loop_lines:
	pop		de
	pop		bc
.to_a:
	ld		a, 0
	and		7
	jr		z, .no_roll

.loop_roll:
	srl		e
	rr		d
	rr		c
	rr		b
	dec		a
	jr		nz, .loop_roll

.no_roll:
	ld		(hl), e
	inc		l
	ld		(hl), d
	inc		l
	ld		(hl), c
	inc		l
	ld		(hl), b
	dec		l
	dec		l
	dec		l
	inc		h
	ld		a, h
	and		7
	jr		nz, .loop_lines

.to_sp:
	ld		sp, 0
	pop		bc
	pop		de
	ret

 

;================================

; Gfx.

HouseBlock
	defb		255,145,145,255,145,145,255,145

Grass
	defb		36,132,144,20,5,65,80,20

PlaneSpr
	defb		96,63,225,0
	defb		240,9,65,0
	defb		240,31,253,0
	defb		255,255,254,0
	defb		255,255,253,0
	defb		127,255,241,0
	defb		16,127,129,0
	defb		32,0,0

BombSpr
	defb		0,84,56,124,254,254,124,56



;================================

; Variables.

Variables

vLevel		defb		0

; Bomb data.
vBombX		defb		0
vBombY		defb		0
vBombExp	defb		4



;================================

End:
	SAVESNA "ultrabomber.sna",Start
	SAVEBIN "ultrabomber.bin",Start,End-Start
