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