Code: Select all
; 'Pixel Perfect'
; by Indy
; A big thanks to KeithS the author of Chibiakumas game.
; You encouraged me to learn assembly again.
;
;
;
; Just a simple program to learn how to program in Z80 in particular the 
; Amstrad CPC range of 8 bit computers. I grew up with these machines and have always
; aspired to one day make a simple game for my kids.
;
; Use the cursor keys to move a 'dash' around the screen.
scradd equ &c000 
pixelval equ 255 ;%00010000 ;%00110011 ;255
xmin equ 1
ymin equ 1
xmax equ 81
ymax equ 200
scrbor 	equ	3	;screen border colour
org &4000
;nolist
run &4000
	ld a,1		;screen mode
	call &BC0E
	ld b,0		;screen background colour
	ld c,0
	call &BC32
	ld b,0		;screen border colour
	ld c,0
	call &BC38
	
	ld a,pixelval 	;load pixel bit mask
	ld hl,scradd
	ld (hl),a
	ld (pxpos),hl   ;; for xpos
	ld a,0
	;ld (pypos),a   ;; for xpos
loop: 			;program loop ******
	
	ld a,66		;ESC key. 66=ESC key code
	call &BB1E	;key press check
	
	jp nz,finish	;if ESC pressed then goto Finish
	
	ld a,8		;Left arrow key. 
	call &BB1E	;key press check
lk:	call nz,goleft	;if Left pressed
	
	
	ld a,1		;Right arrow key. 
	call &BB1E	;key press check
rk:	call nz,goright	;if Right pressed
	
	ld a,2		;Down arrow key. 
	call &BB1E	;key press check
dk:	call nz,godown	;if Right pressed
	
	ld a,0		;Up arrow key. 
	call &BB1E	;key press check
uk:	call nz,goup	;if Right pressed
	call hline
	
plotpixel:
	ld hl,(pxpos)	;get current screen location pointer
	ld a,pixelval 	;load pixel value	
	;and %10000000	;change bits to show pixel(s)/colour required
	ld (hl),a	;plot pixel value to screen
	push de
	push hl
	
	ld a,1		;lets check sound channel 1 if it's still playing something
	call &bcad
	
	pop hl
	pop de
	bit 7,a		;check if sound still playing using bit 7
	call z,staticborder
	call &BD19 	;v-sync
	jp loop 	;keep looping main logic ******
goleft:	
	
	ld hl,(pxpos)
	xor a	
	ld a,(xpos)	;load current xpos and check if we hit screen min
	cp xmin
	jp z,crashed
	ret z
	dec a	
	ld (xpos),a	;save new xpos
	ld (hl),0	;clear current pixel
	dec hl		;decrement pixel location
	ld (pxpos),hl   ;; for xpos
	ret 
goright:
	
	ld hl,(pxpos)
	xor a
		
	ld a,(xpos)	;load current xpos and check if we hit screen max
	inc a	
	cp xmax
	jp z,crashed
	ret z
	ld (xpos),a	;save new xpos
	ld (hl),0	;clear current pixel	
	inc hl		;increment pixel location	
	ld (pxpos),hl   ;; for xpos
	
	ret 
goup:
	ld hl,(pxpos)
	xor a
		
	ld a,(ypos)	;load current ypos and check if we hit screen min
	cp ymin
	jp z,crashed
	ret z
	dec a	
	ld (ypos),a	;save new ypos
	
	ld (hl),0	;clear current pixel	
	
	ld a,h
	or a
	sub a,&08	;sub 1 for previous scanline
	
	ret z
	ld h,a	
	bit 6,a		;get zero flag status
	
	call z,prevrow	;if zero set then top of row reached
			;we need to decrement row
	
	ld (pxpos),hl   ;save new screen pos to memory
	ret 
prevrow:
	ld hl,(pxpos)	;get current screen pos
	or a		;reset carry flag
	ld a,l		;get HL low byte
	sub a,&50	;subtract &50 to move to next row end address
	ld l,a		;place low byte back into HL
	
	
	ld a,h		;get HL high byte
	bit 1,a		;check to see if carry was set during row increment
	
	jr nc,skippr	;if not, no need to increment row start address
	sub a,&01
skippr:	add a,&38	;reset scanlines back to start
	ld h,a		;save value back to HL high byte
	
	ret	
godown:
	
	ld hl,(pxpos)
	xor a
	ld a,(ypos)	;load current ypos and check if we hit screen max
	cp ymax
	jp z,crashed
	ret z
	inc a	
	ld (ypos),a	;save new pos
	ld (hl),0	;clear current pixel	
	
	ld a,h
	add a,&08	;add 1 for next scanline
	ld h,a
	bit 6,h		;get zero flag status
	
	call z,nextrow	;if zero set then end of row reached
			;we need to increment row
	ld (pxpos),hl   ;save new screen pos to memory
	ret 
nextrow:
	ld hl,(pxpos)	;get current screen pos
	or a		;reset carry flag
	ld a,l		;get HL low byte
	add a,&50	;add &50 to move to next row end address
	ld l,a		;place low byte back into HL
	
	
	ld a,h		;get HL high byte
	;bit 0,a	;check to see if carry was set during row increment
	jr nc,skipnr	;if not, no need to increment row start address
	add a,&01
skipnr:	sub a,&38	;reset scanlines back to start
	ld h,a		;save value back to HL high byte
	;add a,&01
	;ld h,a
	ret		;return
.vline
	ret
.hline
	ld hl,(scradd)
	ld (hl),128
	
	ret
.crashed
	push hl
	push de
	ld hl,snddata
	call &bcaa	;play sound queue	
	ld b,3		;set screen border colour
	ld c,6		;set c to different value so the border flashes
	call &BC38
	ld h,1		;set flashing speed in 1/50s of a second
	ld l,1
	call &BC3E
	pop de
	pop hl
	ret ;jp loop
staticborder:
	push de
	push hl
	
	ld b,scrbor	;set screen border colour
	ld c,b		;b/c have to have the same value otherwise the border will flash
	call &BC38
	
	pop hl
	pop de
	ret ;jr loop
finish:
	;ret
	call &4000	;Reset program
.pypos	defw 0
.pxpos	defw 0
.xpos	defb 1
.ypos	defb 1
.snddata
	defb 1,0,0,0,0,20,5,1,0