ZX81 Machine Code demo: how to move a dot around
Posted: Wed Jan 27, 2021 2:33 am
a sample program that shows how to move a dot around the screen using the arrow keys
Attached is the Assembly file for ZX-IDE (get ZX-IDE for Windows at viewtopic.php?f=6&t=1064 -- download FASMW-ZX)
REQUIRES 4K OR MORE MEMORY AS IT USES A FULL SCREEN DISPLAY. Something similar can work for 1K but needs different code to handle a smaller display file.
Basically works like this.
The ASM file include the subroutines such as LEFT, RIGHT, etc. and the BASIC program to launch it
Attached is the Assembly file for ZX-IDE (get ZX-IDE for Windows at viewtopic.php?f=6&t=1064 -- download FASMW-ZX)
REQUIRES 4K OR MORE MEMORY AS IT USES A FULL SCREEN DISPLAY. Something similar can work for 1K but needs different code to handle a smaller display file.
Basically works like this.
Code: Select all
MOVEDOT: LD HL,(D_FILE) ;HL=DFILE (DISPLAY AREA OF MEMORY)
INC HL ;HL=1ST CHARACTER OF FIRST LINE OF DFILE
LD (D_CURSOR),HL
LD A,(HL)
LD (OLDSPACE),A ;SAVE WHAT IS THERE ALREADY
LD (HL),DOT ;PUT THE DOT THERE
MDLOOP: CALL GETKEY
OR A ;A=0 (SPACE/BREAK)
RET Z ;' ' SPACE (BREAK), EXIT PROGRAM
CP ZX_R_ARROW
CALL Z,RIGHT
CP ZX_L_ARROW
CALL Z,LEFT
CP ZX_U_ARROW
CALL Z,UPDOWN
CP ZX_D_ARROW
CALL Z,UPDOWN
JR MDLOOP
Code: Select all
//ROM SUBROUTINES
DECODE EQU $07BD
//KEYCODES
ZX_U_ARROW EQU 70H ;UP ARROW
ZX_D_ARROW EQU 71H ;DOWN ARROW
ZX_L_ARROW EQU 72H ;LEFT ARROW
ZX_R_ARROW EQU 73H ;RIGHT ARROW
ZX_INV_SP EQU 80H ;'±' INVERSE SPACE
DOT EQU ZX_INV_SP
//VARIABLES FOR THE PROGRAM
OLDSPACE: db 00
D_CURSOR: dw 0000
MOVEDOT: LD HL,(D_FILE) ;HL=DFILE (DISPLAY AREA OF MEMORY)
INC HL ;HL=1ST CHARACTER OF FIRST LINE OF DFILE
LD (D_CURSOR),HL
LD A,(HL)
LD (OLDSPACE),A ;SAVE WHAT IS THERE ALREADY
LD (HL),DOT ;PUT THE DOT THERE
MDLOOP: CALL GETKEY
OR A ;A=0 (SPACE/BREAK)
RET Z ;' ' SPACE (BREAK), EXIT PROGRAM
CP ZX_R_ARROW
CALL Z,RIGHT
CP ZX_L_ARROW
CALL Z,LEFT
CP ZX_U_ARROW
CALL Z,UPDOWN
CP ZX_D_ARROW
CALL Z,UPDOWN
JR MDLOOP
RIGHT: PUSH AF ;SAVE THE A REGISTER
LD HL,(D_CURSOR)
INC HL
LD A,(HL)
CP 76H ; EOL MARKER
JR Z,R_FIN ; DONT GO PAST EOL
DEC HL
LD A,(OLDSPACE)
LD (HL),A
INC HL
LD (D_CURSOR),HL
LD A,(HL)
LD (OLDSPACE),A
LD (HL),DOT
R_FIN:POP AF ;RESTORE THE A REGISTER
RET
LEFT: PUSH AF
LD HL,(D_CURSOR)
DEC HL
LD A,(HL)
CP 76H ; EOL MARKER
JR Z,L_FIN ; DONT GO PAST EOL
INC HL
LD A,(OLDSPACE)
LD (HL),A
DEC HL
LD (D_CURSOR),HL
LD A,(HL)
LD (OLDSPACE),A
LD (HL),DOT
L_FIN:POP AF
RET
UPDOWN:LD DE,0021H ;ONE ZX81 DISPLAY LINE = 32 CHAR + EOL (33d OR 21h)
LD HL,(D_CURSOR)
CP ZX_U_ARROW
JR Z,UP
DOWN:ADD HL,DE ;BOUNDS CHECK , ADD ONE LINE
EX DE,HL ;DE=ONE LINE DOWN
LD HL,VARS_ADDR ;ADDRESS AFTER THE DFILE (DISPLAY AREA)
DEC HL
OR A
SBC HL,DE
RET C ;DO NOT GO BELOW DISPLAY AREA
JR UD_FIN
UP: OR A ;BOUNDS CHECK
SBC HL,DE
EX DE,HL
LD HL,(D_FILE)
OR A
SBC HL,DE
RET NC ;DO NOT GO UP
UD_FIN: PUSH AF ;SAVE THE A REGISTER (WHICH CONTAINS THE KEYCODE)
LD A,(OLDSPACE)
LD HL,(D_CURSOR)
LD (HL),A
LD (D_CURSOR),DE
LD A,(DE)
LD (OLDSPACE),A
LD A,DOT
LD (DE),A
POP AF ;RETURN WITH A SAME AS BEFORE
RET
GETKEY: ;RETURN WITH A=KEYPRESS
SCANKEY:LD A,(4025H);LAST_K
INC A
JR NZ,SCANKEY
GOTKEY: LD BC,(LAST_K)
LD A,C
INC A
JR Z,GOTKEY
CALL DECODE
JR NC,GOTKEY
LD A,(HL)
RET