|
|
|
@ -26,6 +26,7 @@ |
|
|
|
; 20191012 - Add PLAY command for SBC-V2-004 Sound support. |
|
|
|
; 20191013 - Add option for long error messages. |
|
|
|
; - Add option to use VT100 escape codes for screen controls. |
|
|
|
; 20200308 - Add ECB-VDU Graphics support for set, reset and point |
|
|
|
; |
|
|
|
#INCLUDE "std.asm" |
|
|
|
; |
|
|
|
@ -33,6 +34,29 @@ |
|
|
|
; |
|
|
|
ABBRERR .EQU FALSE ; Choose between long error message and abbreviated error messages. |
|
|
|
VT100 .EQU TRUE ; Use VT100 escape codes for CLS |
|
|
|
VDUGFX .EQU FALSE ; Option to enable ECB-VDU graphics support using SET, RESET and POINT. |
|
|
|
; |
|
|
|
;================================================================================== |
|
|
|
; SBC V2 + ECB-VDU GRAPHICS CUSTOMIZATION 160X75 BLOCK GRAPHICS ON AN 80X25 DISPLAY |
|
|
|
; REQUIRES ECB-VDU WITH 256 CHARACTER MOD AND 12X8GFX1 FONT INSTALLED, VDU MODE SET TO 80X25B/24B. |
|
|
|
; SWITCHES LONG ERROR MESSAGES OFF FOR SPACE |
|
|
|
; |
|
|
|
#IF VDUGFX |
|
|
|
#IF (VDUSIZ=V80X25B) |
|
|
|
VDUROWS .EQU 25 |
|
|
|
VDUCOLS .EQU 80 |
|
|
|
#ENDIF |
|
|
|
#IF (VDUSIZ=V80X24B) |
|
|
|
VDUROWS .EQU 24 |
|
|
|
VDUCOLS .EQU 80 |
|
|
|
#ENDIF |
|
|
|
ABBRERR .SET TRUE |
|
|
|
VDUREG .EQU 0F2H ; ECB-VDU |
|
|
|
VDUSTS .EQU 0F2H ; |
|
|
|
VDUDTA .EQU 0F3H ; PORT |
|
|
|
VDURWR .EQU 0F1H ; REGISTER |
|
|
|
VDURRD .EQU 0F0H ; ADDRESSES |
|
|
|
#ENDIF |
|
|
|
; |
|
|
|
; GENERAL EQUATES |
|
|
|
; |
|
|
|
@ -49,7 +73,6 @@ CTRLS .EQU 13H ; Control "S" |
|
|
|
CTRLU .EQU 15H ; Control "U" |
|
|
|
ESC .EQU 1BH ; Escape |
|
|
|
DEL .EQU 7FH ; Delete |
|
|
|
|
|
|
|
; |
|
|
|
; BASIC WORK SPACE LOCATIONS |
|
|
|
; |
|
|
|
@ -58,7 +81,7 @@ DEL .EQU 7FH ; Delete |
|
|
|
; 2090H - 20F8H BASIC EXECUTABLE VARAIABLES / WORKSPACE |
|
|
|
; 20F9H - BASIC PROGRAM START |
|
|
|
|
|
|
|
WRKSPC .EQU BAS_END+90H ; WAS 4090H ; BASIC Work space |
|
|
|
WRKSPC .EQU BAS_END+90H ; BASIC Work space |
|
|
|
USR .EQU WRKSPC+3H ; "USR (x)" jump |
|
|
|
OUTSUB .EQU WRKSPC+6H ; "OUT p,n" |
|
|
|
OTPORT .EQU WRKSPC+7H ; Port (p) |
|
|
|
@ -82,7 +105,7 @@ CHKSUM .EQU WRKSPC+4AH ; Array load/save check sum |
|
|
|
NMIFLG .EQU WRKSPC+4CH ; Flag for NMI break routine |
|
|
|
BRKFLG .EQU WRKSPC+4DH ; Break flag |
|
|
|
RINPUT .EQU WRKSPC+4EH ; Input reflection |
|
|
|
POINT .EQU WRKSPC+51H ; "POINT" reflection (unused) |
|
|
|
POINT .EQU WRKSPC+51H ; "POINT" reflection |
|
|
|
PSET .EQU WRKSPC+54H ; "SET" reflection |
|
|
|
RESET .EQU WRKSPC+57H ; "RESET" reflection |
|
|
|
STRSPC .EQU WRKSPC+5AH ; Bottom of string space |
|
|
|
@ -122,10 +145,9 @@ PBUFF .EQU WRKSPC+0E9H ; Number print buffer |
|
|
|
MULVAL .EQU WRKSPC+0F6H ; Multiplier |
|
|
|
PROGST .EQU WRKSPC+0F9H ; Start of program text area |
|
|
|
STLOOK .EQU WRKSPC+15DH ; Start of memory test |
|
|
|
|
|
|
|
|
|
|
|
; |
|
|
|
; BASIC ERROR CODE VALUES |
|
|
|
|
|
|
|
; |
|
|
|
NF .EQU 00H ; NEXT without FOR |
|
|
|
SN .EQU 02H ; Syntax error |
|
|
|
RG .EQU 04H ; RETURN without GOSUB |
|
|
|
@ -147,23 +169,22 @@ UF .EQU 22H ; UnDEFined FN function |
|
|
|
MO .EQU 24H ; Missing operand |
|
|
|
HX .EQU 26H ; HEX error |
|
|
|
BN .EQU 28H ; BIN error |
|
|
|
|
|
|
|
; |
|
|
|
.ORG BAS_LOC ; WAS 02000H |
|
|
|
|
|
|
|
; |
|
|
|
COLD: JP STARTB ; Jump for cold start |
|
|
|
WARM: JP WARMST ; Jump for warm start |
|
|
|
STARTB: |
|
|
|
LD IX,0 ; Flag cold start |
|
|
|
JP CSTART ; Jump to initialise |
|
|
|
|
|
|
|
; |
|
|
|
.WORD DEINT ; Get integer -32768 to 32767 |
|
|
|
.WORD ABPASS ; Return integer in AB |
|
|
|
|
|
|
|
|
|
|
|
; |
|
|
|
CSTART: LD HL,WRKSPC ; Start of workspace RAM |
|
|
|
LD SP,HL ; Set up a temporary stack |
|
|
|
JP INITST ; Go to initialise |
|
|
|
|
|
|
|
; |
|
|
|
INIT: LD DE,INITAB ; Initialise workspace |
|
|
|
LD B,INITBE-INITAB+3; Bytes to copy |
|
|
|
LD HL,WRKSPC ; Into workspace RAM |
|
|
|
@ -174,7 +195,7 @@ COPY: LD A,(DE) ; Get source |
|
|
|
DEC B ; Count bytes |
|
|
|
JP NZ,COPY ; More to move |
|
|
|
LD SP,HL ; Temporary stack |
|
|
|
|
|
|
|
; |
|
|
|
CALL CLREG ; Clear registers and stack |
|
|
|
CALL PRNTCRLF ; Output CRLF |
|
|
|
LD (BUFFER+72+1),A ; Mark end of buffer |
|
|
|
@ -200,7 +221,7 @@ MLOOP: INC HL ; Next byte |
|
|
|
LD (HL),B ; Restore old contents |
|
|
|
JP Z,MLOOP ; If RAM - test next byte |
|
|
|
JP SETTOP ; Top of RAM found |
|
|
|
|
|
|
|
; |
|
|
|
TSTMEM: CALL ATOH ; Get high memory into DE |
|
|
|
OR A ; Set flags on last byte |
|
|
|
JP NZ,SNERR ; ?SN Error if bad character |
|
|
|
@ -243,17 +264,21 @@ SETTOP: DEC HL ; Back one byte |
|
|
|
WARMST: LD SP,STACK ; Temporary stack |
|
|
|
BRKRET: CALL CLREG ; Clear registers and stack |
|
|
|
JP PRNTOK ; Go to get command line |
|
|
|
|
|
|
|
; |
|
|
|
BFREE: .BYTE " Bytes free",CR,LF,0,0 |
|
|
|
|
|
|
|
SIGNON: .BYTE "Z80 BASIC Ver 4.7b",CR,LF |
|
|
|
; |
|
|
|
SIGNON: .BYTE "Z80 BASIC Ver 4.7b" |
|
|
|
#IF VDUGFX |
|
|
|
.BYTE "/vdu" |
|
|
|
#ENDIF |
|
|
|
.BYTE CR,LF |
|
|
|
.BYTE "Copyright ",40,"C",41 |
|
|
|
.BYTE " 1978 by Microsoft",CR,LF,0,0 |
|
|
|
|
|
|
|
; |
|
|
|
MEMMSG: .BYTE "Memory top",0 |
|
|
|
|
|
|
|
; |
|
|
|
; FUNCTION ADDRESS TABLE |
|
|
|
|
|
|
|
; |
|
|
|
FNCTAB: .WORD SGN |
|
|
|
.WORD INT |
|
|
|
.WORD ABS |
|
|
|
@ -323,57 +348,57 @@ WORDS: .BYTE 'E'+80H,"ND" ; PEND: |
|
|
|
.BYTE 'C'+80H,"SAVE" ; REM: NOT IMPLEMENTED |
|
|
|
.BYTE 'N'+80H,"EW" ; NEW |
|
|
|
|
|
|
|
.BYTE 'T'+80H,"AB(" |
|
|
|
.BYTE 'T'+80H,"O" |
|
|
|
.BYTE 'F'+80H,"N" |
|
|
|
.BYTE 'S'+80H,"PC(" |
|
|
|
.BYTE 'T'+80H,"HEN" |
|
|
|
.BYTE 'N'+80H,"OT" |
|
|
|
.BYTE 'S'+80H,"TEP" |
|
|
|
.BYTE 'T'+80H,"AB(" ; TAB( |
|
|
|
.BYTE 'T'+80H,"O" ; TO |
|
|
|
.BYTE 'F'+80H,"N" ; FN( |
|
|
|
.BYTE 'S'+80H,"PC(" ; SPC( |
|
|
|
.BYTE 'T'+80H,"HEN" ; THEN |
|
|
|
.BYTE 'N'+80H,"OT" ; NOT |
|
|
|
.BYTE 'S'+80H,"TEP" ; STEP |
|
|
|
|
|
|
|
.BYTE '+'+80H |
|
|
|
.BYTE '-'+80H |
|
|
|
.BYTE '*'+80H |
|
|
|
.BYTE '/'+80H |
|
|
|
.BYTE '^'+80H |
|
|
|
.BYTE 'A'+80H,"ND" |
|
|
|
.BYTE 'O'+80H,"R" |
|
|
|
.BYTE 'A'+80H,"ND" ; AND |
|
|
|
.BYTE 'O'+80H,"R" ; OR |
|
|
|
.BYTE '>'+80H |
|
|
|
.BYTE '='+80H |
|
|
|
.BYTE '<'+80H |
|
|
|
|
|
|
|
.BYTE 'S'+80H,"GN" |
|
|
|
.BYTE 'I'+80H,"NT" |
|
|
|
.BYTE 'A'+80H,"BS" |
|
|
|
.BYTE 'U'+80H,"SR" |
|
|
|
.BYTE 'F'+80H,"RE" |
|
|
|
.BYTE 'I'+80H,"NP" |
|
|
|
.BYTE 'P'+80H,"OS" |
|
|
|
.BYTE 'S'+80H,"QR" |
|
|
|
.BYTE 'R'+80H,"ND" |
|
|
|
.BYTE 'L'+80H,"OG" |
|
|
|
.BYTE 'E'+80H,"XP" |
|
|
|
.BYTE 'C'+80H,"OS" |
|
|
|
.BYTE 'S'+80H,"IN" |
|
|
|
.BYTE 'T'+80H,"AN" |
|
|
|
.BYTE 'A'+80H,"TN" |
|
|
|
.BYTE 'P'+80H,"EEK" |
|
|
|
.BYTE 'D'+80H,"EEK" |
|
|
|
.BYTE 'P'+80H,"OINT" |
|
|
|
.BYTE 'L'+80H,"EN" |
|
|
|
.BYTE 'S'+80H,"TR$" |
|
|
|
.BYTE 'V'+80H,"AL" |
|
|
|
.BYTE 'A'+80H,"SC" |
|
|
|
.BYTE 'C'+80H,"HR$" |
|
|
|
.BYTE 'H'+80H,"EX$" |
|
|
|
.BYTE 'B'+80H,"IN$" |
|
|
|
.BYTE 'L'+80H,"EFT$" |
|
|
|
.BYTE 'R'+80H,"IGHT$" |
|
|
|
.BYTE 'M'+80H,"ID$" |
|
|
|
.BYTE 'S'+80H,"GN" ; SGN |
|
|
|
.BYTE 'I'+80H,"NT" ; INT |
|
|
|
.BYTE 'A'+80H,"BS" ; ABS |
|
|
|
.BYTE 'U'+80H,"SR" ; USR |
|
|
|
.BYTE 'F'+80H,"RE" ; FRE |
|
|
|
.BYTE 'I'+80H,"NP" ; INP |
|
|
|
.BYTE 'P'+80H,"OS" ; POS |
|
|
|
.BYTE 'S'+80H,"QR" ; SQR |
|
|
|
.BYTE 'R'+80H,"ND" ; RND |
|
|
|
.BYTE 'L'+80H,"OG" ; LOG |
|
|
|
.BYTE 'E'+80H,"XP" ; EXP |
|
|
|
.BYTE 'C'+80H,"OS" ; COS |
|
|
|
.BYTE 'S'+80H,"IN" ; SIN |
|
|
|
.BYTE 'T'+80H,"AN" ; TAN |
|
|
|
.BYTE 'A'+80H,"TN" ; ATN |
|
|
|
.BYTE 'P'+80H,"EEK" ; PEEK |
|
|
|
.BYTE 'D'+80H,"EEK" ; DEEK |
|
|
|
.BYTE 'P'+80H,"OINT" ; POINT |
|
|
|
.BYTE 'L'+80H,"EN" ; LEN |
|
|
|
.BYTE 'S'+80H,"TR$" ; STR$ |
|
|
|
.BYTE 'V'+80H,"AL" ; VAL |
|
|
|
.BYTE 'A'+80H,"SC" ; ASC |
|
|
|
.BYTE 'C'+80H,"HR$" ; CHR$ |
|
|
|
.BYTE 'H'+80H,"EX$" ; HEX$ |
|
|
|
.BYTE 'B'+80H,"IN$" ; BIN$ |
|
|
|
.BYTE 'L'+80H,"EFT$" ; LEFT$ |
|
|
|
.BYTE 'R'+80H,"IGHT$" ; RIGHT$ |
|
|
|
.BYTE 'M'+80H,"ID$" ; MID$ |
|
|
|
.BYTE 80H ; End of list marker |
|
|
|
|
|
|
|
; |
|
|
|
; KEYWORD ADDRESS TABLE |
|
|
|
|
|
|
|
; |
|
|
|
WORDTB: .WORD PEND |
|
|
|
.WORD FOR |
|
|
|
.WORD NEXT |
|
|
|
@ -411,9 +436,9 @@ WORDTB: .WORD PEND |
|
|
|
.WORD PLAY |
|
|
|
.WORD REM |
|
|
|
.WORD NEW |
|
|
|
|
|
|
|
; |
|
|
|
; RESERVED WORD TOKEN VALUES |
|
|
|
|
|
|
|
; |
|
|
|
ZEND .EQU 080H ; END |
|
|
|
ZFOR .EQU 081H ; FOR |
|
|
|
ZDATA .EQU 083H ; DATA |
|
|
|
@ -422,7 +447,7 @@ ZGOSUB .EQU 08CH ; GOSUB |
|
|
|
ZREM .EQU 08EH ; REM |
|
|
|
ZPRINT .EQU 09EH ; PRINT |
|
|
|
ZNEW .EQU 0A4H ; NEW |
|
|
|
|
|
|
|
; |
|
|
|
ZTAB .EQU 0A5H ; TAB |
|
|
|
ZTO .EQU 0A6H ; TO |
|
|
|
ZFN .EQU 0A7H ; FN |
|
|
|
@ -430,7 +455,7 @@ ZSPC .EQU 0A8H ; SPC |
|
|
|
ZTHEN .EQU 0A9H ; THEN |
|
|
|
ZNOT .EQU 0AAH ; NOT |
|
|
|
ZSTEP .EQU 0ABH ; STEP |
|
|
|
|
|
|
|
; |
|
|
|
ZPLUS .EQU 0ACH ; + |
|
|
|
ZMINUS .EQU 0ADH ; - |
|
|
|
ZTIMES .EQU 0AEH ; * |
|
|
|
@ -442,32 +467,32 @@ ZLTH .EQU 0B5H ; < |
|
|
|
ZSGN .EQU 0B6H ; SGN |
|
|
|
ZPOINT .EQU 0C7H ; POINT |
|
|
|
ZLEFT .EQU 0CDH +2 ; LEFT$ |
|
|
|
|
|
|
|
; |
|
|
|
; ARITHMETIC PRECEDENCE TABLE |
|
|
|
|
|
|
|
; |
|
|
|
PRITAB: .BYTE 79H ; Precedence value |
|
|
|
.WORD PADD ; FPREG = <last> + FPREG |
|
|
|
|
|
|
|
; |
|
|
|
.BYTE 79H ; Precedence value |
|
|
|
.WORD PSUB ; FPREG = <last> - FPREG |
|
|
|
|
|
|
|
; |
|
|
|
.BYTE 7CH ; Precedence value |
|
|
|
.WORD MULT ; PPREG = <last> * FPREG |
|
|
|
|
|
|
|
; |
|
|
|
.BYTE 7CH ; Precedence value |
|
|
|
.WORD DIV ; FPREG = <last> / FPREG |
|
|
|
|
|
|
|
; |
|
|
|
.BYTE 7FH ; Precedence value |
|
|
|
.WORD POWER ; FPREG = <last> ^ FPREG |
|
|
|
|
|
|
|
; |
|
|
|
.BYTE 50H ; Precedence value |
|
|
|
.WORD PAND ; FPREG = <last> AND FPREG |
|
|
|
|
|
|
|
; |
|
|
|
.BYTE 46H ; Precedence value |
|
|
|
.WORD POR ; FPREG = <last> OR FPREG |
|
|
|
|
|
|
|
; |
|
|
|
; BASIC ERROR CODE LIST |
|
|
|
|
|
|
|
; |
|
|
|
#IF ABBRERR |
|
|
|
ERRORS: .BYTE "NF" ; NEXT without FOR |
|
|
|
.BYTE "SN" ; Syntax error |
|
|
|
@ -513,9 +538,9 @@ ERRORS: .BYTE "NEXT without FOR",0 |
|
|
|
.BYTE "HEX",0 |
|
|
|
.BYTE "BIN",0 |
|
|
|
#ENDIF |
|
|
|
|
|
|
|
; |
|
|
|
; INITIALISATION TABLE ------------------------------------------------------- |
|
|
|
|
|
|
|
; |
|
|
|
INITAB: JP WARMST ; Warm start jump |
|
|
|
JP FCERR ; "USR (X)" jump (Set to Error) |
|
|
|
OUT (0),A ; "OUT p,n" skeleton |
|
|
|
@ -553,16 +578,22 @@ INITAB: JP WARMST ; Warm start jump |
|
|
|
.BYTE 0 ; Break not by NMI |
|
|
|
.BYTE 0 ; Break flag |
|
|
|
JP TTYLIN ; Input reflection (set to TTY) |
|
|
|
JP $0000 ; POINT reflection unused |
|
|
|
JP $0000 ; SET reflection |
|
|
|
JP $0000 ; RESET reflection |
|
|
|
#IF VDUGFX |
|
|
|
JP POINTB ; POINT reflection unused |
|
|
|
JP SETB ; SET reflection |
|
|
|
JP RESETB ; RESET reflection |
|
|
|
#ELSE |
|
|
|
JP REM |
|
|
|
JP REM |
|
|
|
JP REM |
|
|
|
#ENDIF |
|
|
|
.WORD STLOOK ; Temp string space |
|
|
|
.WORD -2 ; Current line number (cold) |
|
|
|
.WORD PROGST+1 ; Start of program text |
|
|
|
INITBE: |
|
|
|
|
|
|
|
; |
|
|
|
; END OF INITIALISATION TABLE --------------------------------------------------- |
|
|
|
|
|
|
|
; |
|
|
|
ERRMSG: .BYTE " Error",0 |
|
|
|
INMSG: .BYTE " in ",0 |
|
|
|
ZERBYT .EQU $-1 ; A zero byte |
|
|
|
@ -2075,6 +2106,10 @@ FNOFST: LD B,0 ; Get address of function |
|
|
|
PUSH BC ; Save adjusted token value |
|
|
|
CALL GETCHR ; Get next character |
|
|
|
LD A,C ; Get adjusted token value |
|
|
|
#IF VDUGFX |
|
|
|
CP 2*(ZPOINT-ZSGN) ; Adjusted "POINT" token? |
|
|
|
JP Z,POINT ; Yes - Do "POINT" (not POINTB) |
|
|
|
#ENDIF |
|
|
|
CP 2*(ZLEFT-ZSGN)-1; Adj' LEFT$,RIGHT$ or MID$ ? |
|
|
|
JP C,FNVAL ; No - Do function |
|
|
|
CALL OPNPAR ; Evaluate expression (X,... |
|
|
|
@ -2098,7 +2133,7 @@ FNVAL: CALL EVLPAR ; Evaluate expression |
|
|
|
GOFUNC: LD BC,FNCTAB ; Function routine addresses |
|
|
|
ADD HL,BC ; Point to right address |
|
|
|
LD C,(HL) ; Get LSB of address |
|
|
|
INC HL ; |
|
|
|
INC HL |
|
|
|
LD H,(HL) ; Get MSB of address |
|
|
|
LD L,C ; Address to HL |
|
|
|
JP (HL) ; Jump to function |
|
|
|
@ -2840,7 +2875,7 @@ SCNEND: POP DE ; Addresses of strings |
|
|
|
JP GARBLP ; Look for more strings |
|
|
|
|
|
|
|
CONCAT: PUSH BC ; Save prec' opr & code string |
|
|
|
PUSH HL ; |
|
|
|
PUSH HL |
|
|
|
LD HL,(FPREG) ; Get first string |
|
|
|
EX (SP),HL ; Save first string |
|
|
|
CALL OPRND ; Get second string |
|
|
|
@ -3350,7 +3385,7 @@ FPMULT: CALL TSTSGN ; Test sign of FPREG |
|
|
|
PUSH HL ; Save for return |
|
|
|
LD HL,MULT8 ; Address of 8 bit multiply |
|
|
|
PUSH HL ; Save for NMSB,MSB |
|
|
|
PUSH HL ; |
|
|
|
PUSH HL |
|
|
|
LD HL,FPREG ; Point to number |
|
|
|
MULT8: LD A,(HL) ; Get LSB of number |
|
|
|
INC HL ; Point to NMSB |
|
|
|
@ -4069,7 +4104,7 @@ RND: CALL TSTSGN ; Test sign of FPREG |
|
|
|
LD C,A ; BC = Offset into table |
|
|
|
ADD HL,BC ; Point to coefficient |
|
|
|
CALL LOADFP ; Coefficient to BCDE |
|
|
|
CALL FPMULT ; ; Multiply FPREG by coefficient |
|
|
|
CALL FPMULT ; Multiply FPREG by coefficient |
|
|
|
LD A,(SEED+1) ; Get (SEED+1) |
|
|
|
INC A ; Add 1 |
|
|
|
AND 00000011B ; 0 to 3 |
|
|
|
@ -4197,31 +4232,258 @@ ATNTAB: .BYTE 9 ; Table used by ATN |
|
|
|
.BYTE 000H,000H,000H,081H ; 1/1 |
|
|
|
|
|
|
|
ARET: RET ; A RETurn instruction |
|
|
|
; |
|
|
|
#IF VDUGFX |
|
|
|
; |
|
|
|
; GETXYA |
|
|
|
; Decode the x,y pixel coordinate from BASIC |
|
|
|
; Convert pixel coordinate to character coordinate and create the graphic character mask. |
|
|
|
; Convert character coordinate to screen address |
|
|
|
; |
|
|
|
; On exit, A = Graphic character byte mask. HL= screen address. |
|
|
|
; Calling routine set, reset, point uses these to update screen. |
|
|
|
; |
|
|
|
GETXYA: CALL CHKSYN ; Make sure "(" follows |
|
|
|
.DB "(" |
|
|
|
CALL GETNUM ; Get a number |
|
|
|
CALL DEINT ; Get integer -32768 to 32767 |
|
|
|
PUSH DE ; Save "X" |
|
|
|
CALL CHKSYN ; Make sure "," follows |
|
|
|
.DB "," |
|
|
|
CALL GETNUM ; Get a number |
|
|
|
CALL CHKSYN ; Make sure ")" follows |
|
|
|
.DB ")" |
|
|
|
CALL DEINT ; Get integer -32768 to 32767 |
|
|
|
PUSH HL ; Save code string address |
|
|
|
POP IY ; In IY |
|
|
|
; |
|
|
|
; Pixel column (0-159) is on the stack. DE contains the pixel row (0-74) |
|
|
|
; Convert X,Y Pixels co-ord. to X,Y character co-ord. Create Byte mask |
|
|
|
; |
|
|
|
POP HL ; Get the pixel column |
|
|
|
LD A,L ; Change HL from a pixel |
|
|
|
SRL A ; column to a character column |
|
|
|
LD L,A ; by dividing by two. |
|
|
|
SBC A,A ; If the pixel column is even |
|
|
|
INC A ; then set the byte mask to 00000010 |
|
|
|
ADC A,A ; if it is odd set mask to 00000001 |
|
|
|
PUSH HL ; Save the character column |
|
|
|
|
|
|
|
LD HL,(VDUROWS*3)-1; Get row to HL |
|
|
|
SBC HL,DE ; C=0 from above |
|
|
|
LD DE,-1 ; Zero line count |
|
|
|
LD BC,3 ; 3 blocks per line |
|
|
|
DIV3LP: SBC HL,BC ; Subtract 3 |
|
|
|
INC DE ; Count the subtractions |
|
|
|
JP P,DIV3LP ; More to do |
|
|
|
|
|
|
|
OR A ; HL is the remainder which defines |
|
|
|
DEC BC ; which pixel row the mask should be on |
|
|
|
ADC HL,BC ; HL = -1, 0, 1 and flags are set |
|
|
|
|
|
|
|
JR Z,BY4 ; Byte mask is in A and |
|
|
|
JP P,ROW0SKP ; set for pixel row 0 |
|
|
|
RLCA ; Move the mask to |
|
|
|
RLCA ; pixel row 1 or 2 |
|
|
|
BY4: RLCA ; based on the remainder |
|
|
|
RLCA ; calculate above in HL |
|
|
|
ROW0SKP:OR 10000000B ; Convert Byte mask (0-63) to a font character (128-192) |
|
|
|
; |
|
|
|
; A=Byte mask, stack = character column (0-79). DE contains character row (0-24) |
|
|
|
; Check for valid character co-ord and calculate screen address |
|
|
|
; |
|
|
|
POP HL ; Character column |
|
|
|
PUSH AF ; Save byte mask |
|
|
|
|
|
|
|
LD A,H ; Column high byte to A |
|
|
|
OR A ; Error if negative |
|
|
|
JP NZ,FCERR ; or >255 |
|
|
|
LD A,L ; Column low byte to A |
|
|
|
CP VDUCOLS ; Error if out of |
|
|
|
JP P,FCERR ; Range |
|
|
|
|
|
|
|
LD B,E ; Rows to B |
|
|
|
INC B |
|
|
|
LD E,L ; Columns to E |
|
|
|
|
|
|
|
LD HL,-(VDUCOLS) ; Base VDU address |
|
|
|
ADD HL,DE ; Add column to address |
|
|
|
LD DE,VDUCOLS ; Line to DE |
|
|
|
ADD80X: ADD HL,DE ; Multiply by lines |
|
|
|
DJNZ ADD80X |
|
|
|
; |
|
|
|
POP AF ; Restore byte mask |
|
|
|
RET |
|
|
|
; |
|
|
|
SETB: CALL GETXYA ; Get co-ords and VDU address |
|
|
|
PUSH AF ; Save bit mask |
|
|
|
CALL VDU_RDHL ; Get character from screen |
|
|
|
CP 192 ; Is it a block graphic? |
|
|
|
JR NC,NOTBLK1 |
|
|
|
CP 128 |
|
|
|
JR NC,SETOR ; Yes - OR new bit |
|
|
|
NOTBLK1:POP AF ; Restore bit mask |
|
|
|
PUTBIT: CALL VDU_WRHL ; Put character on screen |
|
|
|
RESCSA: PUSH IY ; Restore code string address |
|
|
|
POP HL ; From IY |
|
|
|
RET |
|
|
|
|
|
|
|
SETOR: POP BC ; Restore bit mask |
|
|
|
OR B ; Merge the bits |
|
|
|
JR PUTBIT ; Save on screen |
|
|
|
|
|
|
|
RESETB: CALL GETXYA ; Get co-ords and VDU address |
|
|
|
LD D,A ; Save byte mask |
|
|
|
CALL VDU_RDHL ; Get character from screen |
|
|
|
LD E,A ; Save current character |
|
|
|
PUSH DE |
|
|
|
CP 192 ; If it is not a block |
|
|
|
JR C,NOTBLK2 ; change it to a blank |
|
|
|
CP 128 |
|
|
|
JR C,NOTBLK2 |
|
|
|
XOR A |
|
|
|
NOTBLK2:LD B,00111111B ; Six bits per block |
|
|
|
AND B ; Clear bits 7 & 6 |
|
|
|
POP BC ; Get bit mask |
|
|
|
AND B ; Test for common bit |
|
|
|
JR Z,RESCSA ; None - Leave it |
|
|
|
LD A,E ; Recall byte from screen |
|
|
|
AND 00111111B ; Isolate bit |
|
|
|
XOR B ; Clear that bit |
|
|
|
JR PUTBIT ; Save the space |
|
|
|
|
|
|
|
NORES: POP BC ; Drop bit mask |
|
|
|
JR RESCSA ; Restore code string address |
|
|
|
|
|
|
|
POINTB: CALL GETXYA ; Get co-ords and VDU address |
|
|
|
PUSH AF |
|
|
|
CALL VDU_RDHL ; Get character from screen |
|
|
|
LD B,A |
|
|
|
POP AF |
|
|
|
CALL TSTBIT ; Test if bit is set |
|
|
|
JP NZ,POINT0 ; Different - Return zero |
|
|
|
LD A,0 |
|
|
|
LD B,1 ; Integer AB = 1 |
|
|
|
POINTX: POP HL ; Drop return |
|
|
|
PUSH IY ; PUSH code string address |
|
|
|
LD DE,RETNUM ; To return a number |
|
|
|
PUSH DE ; Save for return |
|
|
|
JP ABPASS ; Return integer AB |
|
|
|
|
|
|
|
POINT0: LD B,0 ; Set zero |
|
|
|
JP POINTX ; Return value |
|
|
|
; |
|
|
|
;---------------------------------------------------------------------- |
|
|
|
; INITIALIZE VDU |
|
|
|
;---------------------------------------------------------------------- |
|
|
|
; |
|
|
|
VDU_INIT: |
|
|
|
PUSH BC |
|
|
|
PUSH HL |
|
|
|
LD C,10 ; SET CURSOR OFF |
|
|
|
LD A,00100000B |
|
|
|
CALL VDU_WRREG |
|
|
|
; LD HL,0 ; SET SCREEN START ADDRESS |
|
|
|
; LD C,12 |
|
|
|
; CALL VDU_WRREGX |
|
|
|
; LD C,14 ; SET CURSOR START ADDRESS |
|
|
|
; CALL VDU_WRREGX |
|
|
|
; |
|
|
|
LD HL,(VDUROWS*VDUCOLS) ; CLEAR SCREEN |
|
|
|
VDU_FILL: |
|
|
|
LD C,18 |
|
|
|
CALL VDU_WRREGX |
|
|
|
LD A,31 |
|
|
|
OUT (VDUREG),A |
|
|
|
CALL VDU_WAITRDY ; WAIT FOR VDU TO BE READY |
|
|
|
LD A,' ' |
|
|
|
OUT (VDURWR),A |
|
|
|
LD A,H |
|
|
|
OR L |
|
|
|
DEC HL |
|
|
|
JR NZ,VDU_FILL |
|
|
|
POP HL |
|
|
|
POP BC |
|
|
|
RET |
|
|
|
; |
|
|
|
;---------------------------------------------------------------------- |
|
|
|
; WAIT FOR VDU TO BE READY FOR A DATA READ/WRITE |
|
|
|
;---------------------------------------------------------------------- |
|
|
|
; |
|
|
|
VDU_WAITRDY: |
|
|
|
IN A,(VDUSTS) ; READ STATUS |
|
|
|
OR A ; SET FLAGS |
|
|
|
RET M ; IF BIT 7 SET, THEN READY! |
|
|
|
JR VDU_WAITRDY ; KEEP CHECKING |
|
|
|
; |
|
|
|
;---------------------------------------------------------------------- |
|
|
|
; UPDATE SY6845 REGISTERS |
|
|
|
; VDU_WRREG WRITES VALUE IN A TO VDU REGISTER SPECIFIED IN C |
|
|
|
; VDU_WRREGX WRITES VALUE IN HL TO VDU REGISTER PAIR IN C, C+1 |
|
|
|
;---------------------------------------------------------------------- |
|
|
|
; |
|
|
|
VDU_WRREG: |
|
|
|
PUSH AF ; SAVE VALUE TO WRITE |
|
|
|
LD A,C ; SET A TO VDU REGISTER TO SELECT |
|
|
|
OUT (VDUREG),A ; WRITE IT TO SELECT THE REGISTER |
|
|
|
POP AF ; RECOVER VALUE TO WRITE |
|
|
|
OUT (VDUDTA),A ; WRITE IT |
|
|
|
RET |
|
|
|
; |
|
|
|
VDU_WRREGX: |
|
|
|
LD A,H ; SETUP MSB TO WRITE |
|
|
|
CALL VDU_WRREG ; DO IT |
|
|
|
INC C ; NEXT VDU REGISTER |
|
|
|
LD A,L ; SETUP LSB TO WRITE |
|
|
|
JR VDU_WRREG ; DO IT & RETURN |
|
|
|
; |
|
|
|
VDU_RDHL: |
|
|
|
LD C,18 ; READ A BYTE |
|
|
|
CALL VDU_WRREGX ; FROM VIDEO MEMORY |
|
|
|
LD A,31 ; POINTED TO BY HL |
|
|
|
OUT (VDUREG),A ; AND RETURN IT IN A |
|
|
|
CALL VDU_WAITRDY |
|
|
|
IN A,(VDURRD) |
|
|
|
RET |
|
|
|
; |
|
|
|
VDU_WRHL: |
|
|
|
PUSH AF ; WRITE A BYTE IN A |
|
|
|
LD C,18 ; TO VIDEO MEMORY |
|
|
|
CALL VDU_WRREGX ; POINTED TO BY HL |
|
|
|
LD A,31 |
|
|
|
OUT (VDUREG),A |
|
|
|
CALL VDU_WAITRDY |
|
|
|
POP AF |
|
|
|
OUT (VDURWR),A |
|
|
|
RET |
|
|
|
#ENDIF |
|
|
|
; INPUT CHARACTER FROM CONSOLE VIA HBIOS |
|
|
|
|
|
|
|
GETINP: |
|
|
|
PUSH BC |
|
|
|
PUSH DE |
|
|
|
PUSH HL |
|
|
|
|
|
|
|
LD C,CIODEV_CONSOLE; CONSOLE UNIT TO C |
|
|
|
LD B,BF_CIOIN ; HBIOS FUNC: INPUT CHAR |
|
|
|
RST 08 ; HBIOS READS CHARACTDR |
|
|
|
LD A,E ; MOVE CHARACTER TO A FOR RETURN |
|
|
|
|
|
|
|
POP HL ; RESTORE REGISTERS (AF IS OUTPUT) |
|
|
|
POP DE |
|
|
|
POP BC |
|
|
|
RET |
|
|
|
CLS: |
|
|
|
#IF VDUGFX |
|
|
|
CALL VDU_INIT ; Clear VDU screen |
|
|
|
#ENDIF |
|
|
|
#IF VT100 |
|
|
|
PUSH HL |
|
|
|
LD HL,VT_CLS ; Output zero terminated |
|
|
|
VT0OUT: LD A,(HL) ; VT100 escape sequence |
|
|
|
INC HL ; directly to console. |
|
|
|
OR A |
|
|
|
CALL NZ,MONOUT ; clear screen |
|
|
|
JR NZ,VT0OUT ; and home cursor |
|
|
|
POP HL |
|
|
|
RET |
|
|
|
#ELSE |
|
|
|
LD A,CS ; ASCII Clear screen |
|
|
|
@ -4317,7 +4579,7 @@ ADD30 ADD A,$30 ; And make ASCII |
|
|
|
ADD301 ADD A,$30 ; And make it full ASCII |
|
|
|
LD B,A ; Store high order byte |
|
|
|
RET |
|
|
|
|
|
|
|
; |
|
|
|
; Convert "&Hnnnn" to FPREG |
|
|
|
; Gets a character from (HL) checks for Hexadecimal ASCII numbers "&Hnnnn" |
|
|
|
; Char is in A, NC if char is ;<=>?@ A-z, CY is set if 0-9 |
|
|
|
@ -4362,8 +4624,9 @@ HEXIT EX DE,HL ; Value into DE, Code string into HL |
|
|
|
|
|
|
|
HXERR: LD E,HX ; ?HEX Error |
|
|
|
JP ERROR |
|
|
|
|
|
|
|
; |
|
|
|
; BIN$(NN) Convert integer to a 1-16 char binary string |
|
|
|
; |
|
|
|
BIN: CALL TSTNUM ; Verify it's a number |
|
|
|
CALL DEINT ; Get integer -32768 to 32767 |
|
|
|
BIN2: PUSH BC ; Save contents of BC |
|
|
|
@ -4395,9 +4658,10 @@ BITOUT2: |
|
|
|
POP BC |
|
|
|
LD HL,PBUFF |
|
|
|
JP STR1 |
|
|
|
|
|
|
|
; |
|
|
|
; Convert "&Bnnnn" to FPREG |
|
|
|
; Gets a character from (HL) checks for Binary ASCII numbers "&Bnnnn" |
|
|
|
; |
|
|
|
BINTFP: EX DE,HL ; Move code string pointer to DE |
|
|
|
LD HL,$0000 ; Zero out the value |
|
|
|
CALL CHKBIN ; Check the number for valid bin |
|
|
|
@ -4429,24 +4693,22 @@ CHKBIN: INC DE |
|
|
|
|
|
|
|
BINERR: LD E,BN ; ?BIN Error |
|
|
|
JP ERROR |
|
|
|
|
|
|
|
; |
|
|
|
JJUMP1: |
|
|
|
LD IX,-1 ; Flag cold start |
|
|
|
JP CSTART ; Go and initialise |
|
|
|
|
|
|
|
; OUTPUT CHARACTER TO CONSOLE VIA HBIOS |
|
|
|
; OUTPUT CHARACTER A TO CONSOLE VIA HBIOS |
|
|
|
|
|
|
|
MONOUT: |
|
|
|
PUSH AF ; SAVE ALL INCOMING REGISTERS |
|
|
|
PUSH BC |
|
|
|
PUSH DE |
|
|
|
PUSH HL |
|
|
|
|
|
|
|
LD E,A ; OUTPUT CHAR TO E |
|
|
|
LD C,CIODEV_CONSOLE; CONSOLE UNIT TO C |
|
|
|
LD B,BF_CIOOUT ; HBIOS FUNC: OUTPUT CHAR |
|
|
|
RST 08 ; HBIOS OUTPUTS CHARACTDR |
|
|
|
|
|
|
|
POP HL ; RESTORE ALL REGISTERS |
|
|
|
POP DE |
|
|
|
POP BC |
|
|
|
@ -4460,6 +4722,9 @@ MONITR: LD A,BID_BOOT ; BOOT BANK |
|
|
|
INITST: LD A,0 ; Clear break flag |
|
|
|
LD (BRKFLG),A |
|
|
|
CALL SET_DUR_TBL ; SET UP SOUND TABLE |
|
|
|
#IF VDUGFX |
|
|
|
CALL VDU_INIT ; SET AND CLEAR VDU SCREEN 0 |
|
|
|
#ENDIF |
|
|
|
JP INIT |
|
|
|
|
|
|
|
ARETN: RETN ; Return from NMI |
|
|
|
|