Browse Source

Merge pull request #49 from b1ackmai1er/master

Add sound to Nascom BASIC for SBC-V2-003
pull/54/head
Wayne Warthen 6 years ago
committed by GitHub
parent
commit
d12ed64fd6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 489
      Source/HBIOS/nascom.asm

489
Source/HBIOS/nascom.asm

@ -33,7 +33,7 @@ LF .EQU 0AH ; Line feed
CS .EQU 0CH ; Clear screen
CR .EQU 0DH ; Carriage return
CTRLO .EQU 0FH ; Control "O"
CTRLQ .EQU 11H ; Control "Q"
CTRLQ .EQU 11H ; Control "Q"
CTRLR .EQU 12H ; Control "R"
CTRLS .EQU 13H ; Control "S"
CTRLU .EQU 15H ; Control "U"
@ -42,6 +42,11 @@ DEL .EQU 7FH ; Delete
; BASIC WORK SPACE LOCATIONS
; 0200H - 2000H BASIC EXECUTABLE
; 2000H - 2090H STACK
; 2090H - 20F8H BASIC EXECUTABLE VARAIABLES / WORKSPACE
; 20F9H - BASIC PROGRAM START
WRKSPC .EQU BAS_END+90H ; WAS 4090H ; BASIC Work space
USR .EQU WRKSPC+3H ; "USR (x)" jump
OUTSUB .EQU WRKSPC+6H ; "OUT p,n"
@ -132,7 +137,7 @@ MO .EQU 24H ; Missing operand
HX .EQU 26H ; HEX error
BN .EQU 28H ; BIN error
.ORG BAS_LOC ; WAS 02000H
.ORG BAS_LOC ; WAS 02000H
COLD: JP STARTB ; Jump for cold start
WARM: JP WARMST ; Jump for warm start
@ -173,8 +178,8 @@ MSIZE: LD HL,MEMMSG ; Point to message
MLOOP: INC HL ; Next byte
; LD A,H ; Above address FFFF ?
; OR L
LD A,H ; Memory top set below HBIOS Proxy @ FE00
CP $FD
LD A,H ; Memory top set below HBIOS Proxy @ FE00
CP $FD
JP Z,SETTOP ; Yes - 64K RAM
LD A,(HL) ; Get contents
LD B,A ; Save it
@ -303,7 +308,7 @@ WORDS: .BYTE 'E'+80H,"ND"
.BYTE 'C'+80H,"ONT"
.BYTE 'L'+80H,"IST"
.BYTE 'C'+80H,"LEAR"
.BYTE 'C'+80H,"LOAD"
.BYTE 'P'+80H,"LAY"
.BYTE 'C'+80H,"SAVE"
.BYTE 'N'+80H,"EW"
@ -392,7 +397,7 @@ WORDTB: .WORD PEND
.WORD CONT
.WORD LIST
.WORD CLEAR
.WORD REM
.WORD PLAY
.WORD REM
.WORD NEW
@ -573,10 +578,10 @@ CHKSTK: PUSH HL ; Save code string address
ADD HL,BC
.BYTE 3EH ; Skip "PUSH HL"
ENFMEM: PUSH HL ; Save code string address
LD A,0D0H ;LOW -48 ; 48 Bytes minimum RAM
LD A,0D0H ;LOW -48 ; 48 Bytes minimum RAM
SUB L
LD L,A
LD A,0FFH; HIGH (-48) ; 48 Bytes minimum RAM
LD A,0FFH ; HIGH (-48) ; 48 Bytes minimum RAM
SBC A,H
JP C,OMERR ; Not enough - ?OM Error
LD H,A
@ -1257,34 +1262,36 @@ UPDATA: LD (NXTDAT),HL ; Update DATA pointer
EX DE,HL ; Restore code string address
RET
; GET CONSOLE INPUT STATUS VIA HBIOS
TSTBRK:
; SAVE INCOMING REGISTERS (AF IS OUTPUT)
PUSH BC
PUSH DE
PUSH HL
; GET CONSOLE INPUT STATUS VIA HBIOS
LD C,CIODEV_CONSOLE; CONSOLE UNIT TO C
LD B,BF_CIOIST ; HBIOS FUNC: INPUT STATUS
RST 08 ; HBIOS RETURNS STATUS IN A
; RESTORE REGISTERS (AF IS OUTPUT)
POP HL
POP DE
POP BC
PUSH BC ; SAVE INCOMING REGISTERS (AF IS OUTPUT)
PUSH DE
PUSH HL
LD C,CIODEV_CONSOLE; CONSOLE UNIT TO C
LD B,BF_CIOIST ; HBIOS FUNC: INPUT STATUS
RST 08 ; HBIOS RETURNS STATUS IN A
POP HL ; RESTORE REGISTERS (AF IS OUTPUT)
POP DE
POP BC
RET Z ; No key, go back
PUSH BC
PUSH DE
PUSH HL
; INPUT CHARACTER FROM CONSOLE VIA HBIOS
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
PUSH BC
PUSH DE
PUSH HL
; INPUT CHARACTER FROM CONSOLE VIA HBIOS
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
;
; RESTORE REGISTERS (AF IS OUTPUT)
POP HL
POP DE
POP BC
POP HL ; RESTORE REGISTERS (AF IS OUTPUT)
POP DE
POP BC
CP ESC ; Escape key?
JR Z,BRK ; Yes, break
@ -1292,22 +1299,22 @@ TSTBRK:
JR Z,BRK ; Yes, break
CP CTRLS ; Stop scrolling?
RET NZ ; Other key, ignore
STALL: ; Wait for key
; SAVE INCOMING REGISTERS (AF IS OUTPUT)
PUSH BC
PUSH DE
PUSH HL
STALL: ; Wait for key
PUSH BC ; SAVE INCOMING REGISTERS (AF IS OUTPUT)
PUSH DE
PUSH HL
;
; INPUT CHARACTER FROM CONSOLE VIA HBIOS
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
; INPUT CHARACTER FROM CONSOLE VIA HBIOS
;
; RESTORE REGISTERS (AF IS OUTPUT)
POP HL
POP DE
POP BC
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
CP CTRLQ ; Resume scrolling?
RET Z ; Release the chokehold
CP CTRLC ; Second break?
@ -1357,7 +1364,6 @@ NULL: CALL GETINT ; Get integer 0-255
LD (NULLS),A ; Set nulls number
RET
ACCSUM: PUSH HL ; Save address in array
LD HL,(CHKSUM) ; Get check sum
LD B,0 ; BC - Value of byte
@ -1967,8 +1973,8 @@ OPRND: XOR A ; Get operand routine
JP C,ASCTFP ; Number - Get value
CALL CHKLTR ; See if a letter
JP NC,CONVAR ; Letter - Find variable
CP '&' ; &H = HEX, &B = BINARY
JR NZ, NOTAMP
CP '&' ; &H = HEX, &B = BINARY
JR NZ, NOTAMP
CALL GETCHR ; Get next character
CP 'H' ; Hex number indicated? [function added]
JP Z,HEXTFP ; Convert Hex to FPREG
@ -2981,14 +2987,14 @@ VAL: CALL GETLEN ; Get length of string
EX (SP),HL ; Save string end,get start
PUSH BC ; Save end+1 byte
LD A,(HL) ; Get starting byte
CP '$' ; Hex number indicated? [function added]
JP NZ,VAL1
CALL HEXTFP ; Convert Hex to FPREG
JR VAL3
CP '$' ; Hex number indicated? [function added]
JP NZ,VAL1
CALL HEXTFP ; Convert Hex to FPREG
JR VAL3
VAL1: CP '%' ; Binary number indicated? [function added]
JP NZ,VAL2
CALL BINTFP ; Convert Bin to FPREG
JR VAL3
JP NZ,VAL2
CALL BINTFP ; Convert Bin to FPREG
JR VAL3
VAL2: CALL ASCTFP ; Convert ASCII string to FP
VAL3: POP BC ; Restore end+1 byte
POP HL ; Restore end+1 address
@ -3054,7 +3060,7 @@ POKE: CALL GETNUM ; Get memory address
CALL DEINT ; Get integer -32768 to 3276
PUSH DE ; Save memory address
CALL CHKSYN ; Make sure ',' follows
.BYTE ','
.BYTE ','
CALL GETINT ; Get integer 0-255
POP DE ; Restore memory address
LD (DE),A ; Load it into memory
@ -4143,19 +4149,21 @@ ATNTAB: .BYTE 9 ; Table used by ATN
ARET: RET ; A RETurn instruction
; INPUT CHARACTER FROM CONSOLE VIA HBIOS
GETINP:
PUSH BC
PUSH DE
PUSH HL
; INPUT CHARACTER FROM CONSOLE VIA HBIOS
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
; RESTORE REGISTERS (AF IS OUTPUT)
POP HL
POP DE
POP BC
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:
LD A,CS ; ASCII Clear screen
@ -4199,26 +4207,26 @@ DOKE: CALL GETNUM ; Get a number
HEX: CALL TSTNUM ; Verify it's a number
CALL DEINT ; Get integer -32768 to 32767
PUSH BC ; Save contents of BC
LD HL,PBUFF
LD A,D ; Get high order into A
LD HL,PBUFF
LD A,D ; Get high order into A
CP $0
JR Z,HEX2 ; Skip output if both high digits are zero
JR Z,HEX2 ; Skip output if both high digits are zero
CALL BYT2ASC ; Convert D to ASCII
LD A,B
CP '0'
JR Z,HEX1 ; Don't store high digit if zero
LD (HL),B ; Store it to PBUFF
INC HL ; Next location
HEX1: LD (HL),C ; Store C to PBUFF+1
LD A,B
CP '0'
JR Z,HEX1 ; Don't store high digit if zero
LD (HL),B ; Store it to PBUFF
INC HL ; Next location
HEX1: LD (HL),C ; Store C to PBUFF+1
INC HL ; Next location
HEX2: LD A,E ; Get lower byte
HEX2: LD A,E ; Get lower byte
CALL BYT2ASC ; Convert E to ASCII
LD A,D
LD A,D
CP $0
JR NZ,HEX3 ; If upper byte was not zero then always print lower byte
LD A,B
CP '0' ; If high digit of lower byte is zero then don't print
JR Z,HEX4
JR NZ,HEX3 ; If upper byte was not zero then always print lower byte
LD A,B
CP '0' ; If high digit of lower byte is zero then don't print
JR Z,HEX4
HEX3: LD (HL),B ; to PBUFF+2
INC HL ; Next location
HEX4: LD (HL),C ; to PBUFF+3
@ -4254,6 +4262,7 @@ ADD301 ADD A,$30 ; And make it full ASCII
; 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
;
HEXTFP EX DE,HL ; Move code string pointer to DE
LD HL,$0000 ; Zero out the value
CALL GETHEX ; Check the number for valid hex
@ -4362,40 +4371,40 @@ 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
MONOUT:
; SAVE ALL INCOMING REGISTERS
PUSH AF
PUSH BC
PUSH DE
PUSH HL
; OUTPUT CHARACTER TO CONSOLE VIA HBIOS
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
; RESTORE ALL REGISTERS
POP HL
POP DE
POP BC
POP AF
RET
MONITR: LD A,BID_BOOT ; BOOT BANK
LD HL,0 ; ADDRESS ZERO
CALL HB_BNKCALL ; DOES NOT RETURN
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
POP AF
RET
MONITR: LD A,BID_BOOT ; BOOT BANK
LD HL,0 ; ADDRESS ZERO
CALL HB_BNKCALL ; DOES NOT RETURN
INITST: LD A,0 ; Clear break flag
LD (BRKFLG),A
CALL SET_DUR_TBL ; SET UP SOUND TABLE
JP INIT
ARETN: RETN ; Return from NMI
TSTBIT: PUSH AF ; Save bit mask
AND B ; Get common bits
POP BC ; Restore bit mask
@ -4406,19 +4415,265 @@ TSTBIT: PUSH AF ; Save bit mask
OUTNCR: CALL OUTC ; Output character in A
JP PRNTCRLF ; Output CRLF
TXT_READY:
.DB CR,LF
.TEXT "BASIC READY "
.DB CR,LF,0FFH
; ---------------------------------------------------------------------------------------
; PLAY O,N,D ; PLAY OCTAVE 0-8, NOTE N (0-11), DURATION (1-8) [1/8 - 8/8 SECONDS]
PLAY: CALL GETINT ; GET OCTAVE
PUSH AF ; AND SAVE
CALL CHKSYN ; Make sure ',' follows
.BYTE ','
CALL GETINT ; GET NOTE
PUSH HL ; SAVE SYNTAX POINTER
LD L,A
LD H,0
ADD HL,HL ; X2
ADD HL,HL ; X4
LD DE,FRQDURTBL ; POINT TO NOTE ENTRY
ADD HL,DE ; ITS IN HL
EX (SP),HL ; RESTORE SYNTAX POINTER
; IN HL. NOTE PTR ON STACK
CALL CHKSYN ; Make sure ',' follows
.BYTE ','
CALL GETINT ; GET DURATION
POP DE ; GET NOTE PTR IN DE
EX (SP),HL ; GET OCTAVE IN HL. SYNTAX POINTER ON STACK
EX DE,HL ; PUT NOTE PTR IN HL, OCTAVE IN DE
PUSH BC ; SAVE SYNTAX POINTER
LD B,D ; SAVE OCTAVE
PUSH AF ; SAVE DURATION
LD A,(HL) ; LOAD 1ST ARG
INC HL ; IN DE
LD E,A ; WHICH IS THE
LD A,(HL) ; FREQUENCY FOR
INC HL ; THE EIGHTH
LD D,A ; OCTAVE
PUSH DE
LD A,(HL) ; LOAD 2ND ARG
INC HL ; IN DE
LD E,A ; WHICH IS THE
LD A,(HL) ; PITCH
LD D,A
PUSH DE ; SETUP ARGS IN HL
POP HL ; AND DE
POP DE ; DE = FREQUENCY
; HL = PITCH
LD A,8 ; DIVIDE THE
SUB B ; FREQUENCY BASED
JR Z,SPK_OCTOK ; ON THE OCTAVE
LD B,A
SPK_OCTDIV:
SRL D ; 0>D>C ; MULTIPLY THE
RR E ; C>E>C ; DURATION EVERY
SLA L ; C<L<0 ; TIME WE DIVIDE
RL H ; C<H<C ; THE FREQUENCY
DJNZ SPK_OCTDIV
JR NC,SPK_OCTOK ; SET TO MAXIMUM
LD HL,$FFFF ; IF OVERFLOW
SPK_OCTOK:
POP BC ; MULTIPLY CHL X B
PUSH HL ; SAVE
LD C,0
LD H,C
LD L,C
CCF
MULSKP: ADD HL,DE
JR NC,MULDLP
INC C
MULDLP: DJNZ MULSKP ; DIVIDE BY 8
SRL C ; 0>C>C ; BCHL = BCHL / 2
RR H ; C>H>C ;
RR L ; C>L>C ;
SRL C ; 0>C>C ; BCHL = BCHL / 2
RR H ; C>H>C ;
RR L ; C>L>C ;
SRL C ; 0>C>C ; BCHL = BCHL / 2
RR H ; C>H>C ;
RR L ; C>L>C ;
POP DE
EX DE,HL
; The following SPK_BEEPER routine is a modification of code from
; "The Complete SPECTRUM ROM DISSASSEMBLY" by Dr Ian Logan & Dr Frank O’Hara
; https://www.esocop.org/docs/CompleteSpectrumROMDisassemblyThe.pdf
;
; DE Number of passes to make through the sound generation loop
; HL Loop delay parameter
PUSH IX
DI ; Disable the interrupt for the duration of a 'beep'.
LD A,L ; Save L temporarily.
SRL L ; Each '1' in the L register is to count 4 T states, but take INT (L/4) and count 16 T states instead.
SRL L
CPL ; Go back to the original value in L and find how many were lost by taking 3-(A mod 4).
AND $03
LD C,A
LD B,$00
LD IX,SPK_DLYADJ ; The base address of the timing loop.
ADD IX,BC ; Alter the length of the timing loop. Use an earlier starting point for each '1' lost by taking INT (L/4).
LD A,(RTCVAL) ; Fetch the present border colour from BORDCR and move it to bits 2, 1 and 0 of the A register.
;
; The HL register holds the 'length of the timing loop' with 16 T states being used for each '1' in the L register and 1024 T states for each '1' in the H register.
;
SPK_DLYADJ:
NOP ; Add 4 T states for each earlier entry point that is used.
NOP
NOP
INC B ; The values in the B and C registers will come from the H and L registers - see below.
INC C
BE_H_L_LP:
DEC C ; The 'timing loop', i.e. BC*4 T states. (But note that at the half-cycle point, C will be equal to L+1.)
JR NZ,BE_H_L_LP
LD C,$3F
DEC B
JP NZ,BE_H_L_LP
;
XOR %00000100 ; Flip bit 2. The loudspeaker is now alternately activated and deactivated.
OUT (RTCIO),A ; Perform the 'OUT' operation, leaving other bits unchanged.
LD B,H ; Reset the B register.
LD C,A ; Save the A register.
BIT 4,A ; Jump if at the half-cycle point.
JR NZ,BE_AGAIN
;
LD A,D ; After a full cycle the DE register pair is tested.
OR E
JR Z,BE_END ; Jump forward if the last complete pass has been made already.
LD A,C ; Fetch the saved value.
LD C,L ; Reset the C register.
DEC DE ; Decrease the pass counter.
JP (IX) ; Jump back to the required starting location of the loop.
;
BE_AGAIN: ; The parameters for the second half-cycle are set up.
LD C,L ; Reset the C register.
INC C ; Add 16 T states as this path is shorter.
JP (IX) ; Jump back.
BE_END: EI
POP IX
POP BC ; RECALL SYNTAX POINTER
POP HL
RET
;
RTCVAL .DB 0
;
; SETUP THE ONE SECOND TONE DURATION TABLE BASED ON PROCESSOR SPEED AND TONE FREQUENCY
;
; DURATION = (CPUMHZ / 8) / FREQUENCY
; DURATION = (CPUKHZ * 1000 / 8 ) / FREQUENCY
; DURATION = (CPUKHZ * 125 ) / FREQUENCY
; DURATION = (CPUKHZ * 256 / 2 - CPUKHZ - (2 * CPUKHZ) ) / FREQUENCY
SET_DUR_TBL:
LD B,BF_SYSGET ; GET CPU SPEED
LD C,BF_SYSGET_CPUINFO ; FROM HBIOS
RST 08 ; IN DE
PUSH DE ; SAVE FOR CALCULATION
POP BC ; - CPUKHZ - (2 * CPUKHZ)
LD H,E ; DEHL = DE * 256
LD E,D
LD D,0
LD L,D
SRL E ; 0>E>C ; DEHL = DEHL / 2
RR H ; C>H>C ;
RR L ; C>L>C ;
SBC HL,BC ; DEHL = DEHL - CPUKHZ
JR NC,FRQ_AJ1
DEC DE
FRQ_AJ1:SLA C ; C<C<0 ; DEHL = DEHL - (2 * CPUKHZ)
RL B ; C<B<C
SBC HL,BC
JR NC,FRQ_AJ2
DEC DE
FRQ_AJ2: ; AT THIS POINT DEHL = CPUKHZ * 125 E.G. 9982 KHZ * 125 = 0012:DE14
PUSH HL ; DEHL = CPUKHZ / 8) / FREQUENCY
POP IX ; HLIX = DENOMINATOR
EX DE,HL
LD IY,FRQDURTBL ; POINT TO THE TABLE WE
LD B,FDTBSIZ ; WANT TO READ AND UPDATE
TBL_LP: PUSH BC
LD C,(IY+0) ; READ THE FREQUENCY
LD B,(IY+1) ; FROM THE TABLE IN BC
PUSH IX ; STORE DENOMINATOR FOR NEXT LOOP
PUSH HL
SLACK .EQU (BAS_END - $)
.FILL SLACK,00H
LD DE,0 ; HLIX = HLIX / BC, DE = REMAINDER
LD A,32
DIV_LP: ADD IX,IX
ADC HL,HL
EX DE,HL
ADC HL,HL
OR A
SBC HL,BC
INC IX
JR NC,DIV_CANSUB
ADD HL,BC
DEC IX
DIV_CANSUB:
EX DE,HL
DEC A
JR NZ, DIV_LP ; IX = RESULT
PUSH IX ; SAVE RESULT IN TABLE
POP DE
DUROVF: LD (IY+2),E
LD (IY+3),D
LD DE,4 ; POINT TO NEXT TABLE
ADD IY,DE ; ENTRY TO UPDATE
POP HL ; RETREIVE THE DENOMINATOR
POP IX ; FOR THE NEXT LOOP
POP BC ; RETREIVE THE
DJNZ TBL_LP ; LOOP COUNTER
RET
;
BAS_STACK .EQU $
; ONE OCTAVE TONE TABLE IN FREQUENCY, DURATION FORMAT. TO COMPENSATE FOR DIFFERENT
; CPU FREQUENCIES THE DURATION IS CALCULATED AND POPULATED AT STARTUP. DIFFERENT OCTAVE
; AND DURATIONS ARE CALCULATE BY MODIFYING THE VALUES READ FROM THIS TABLE.
;
.ECHO "BASIC space remaining: "
.ECHO SLACK
.ECHO " bytes.\n"
FRQDURTBL:
.DW $105A, $0, $1152, $0 ; C, C#
.DW $125A, $0, $1372, $0 ; D, D#
.DW $149A, $0 ; E
.DW $15D3, $0, $171F, $0 ; F, F#
.DW $1875, $0, $19F4, $0 ; G, G#
.DW $1B80, $0, $1D22, $0 ; A, A#
.DW $1EDE, $0 ; B
;
FDTBSIZ .EQU ($-FRQDURTBL)/4
.end
SLACK .EQU (BAS_END - $)
.FILL SLACK,00H
;
.ECHO "BASIC space remaining: "
.ECHO SLACK
.ECHO " bytes.\n"
.END

Loading…
Cancel
Save