From efc55d3fd771c6dc7214562b9f3337c1f678ae45 Mon Sep 17 00:00:00 2001 From: Richard Russell Date: Mon, 17 Jun 2024 10:26:16 +0100 Subject: [PATCH] v5beta6: Added Acorn Z80 edition --- README.md | 4 +- WHATSNEW.TXT | 13 +- bin/acorn/BBCBASIC.COM | Bin 0 -> 18944 bytes bin/acorn/MAKE.SUB | 13 + bin/cpm/BBCBASIC.COM | Bin 18944 -> 18944 bytes src/ACORN.Z80 | 737 ++++++++++++++++++++++++++ src/AMOS.Z80 | 1119 ++++++++++++++++++++++++++++++++++++++++ src/CMOS.Z80 | 42 +- src/EXEC.Z80 | 19 +- src/MAIN.Z80 | 2 +- src/MATH.Z80 | 49 +- tests/EXITTEST.BBC | Bin 1261 -> 1408 bytes 12 files changed, 1931 insertions(+), 67 deletions(-) create mode 100644 bin/acorn/BBCBASIC.COM create mode 100644 bin/acorn/MAKE.SUB create mode 100644 src/ACORN.Z80 create mode 100644 src/AMOS.Z80 diff --git a/README.md b/README.md index 5d821cd..97b4663 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ More details of the features added in version 5.00 can be found in the file WHAT The files in green constitute the generic BBC BASIC interpreter which is shared by all the editions, it (just!) fits in 16 Kbytes so could be held in a ROM of this size. The files in -the blue box are used to build the CP/M edition. The files in the red box are used to build -the Acorn Z80 Second Processor edition (in principle: the source files are on an 8" floppy!) +the blue box are used to build the generic CP/M edition. The files in the red box are used +to build the Acorn Z80 Second Processor edition. Note that the name 'BBC BASIC' is used by permission of the British Broadcasting Corporation and is not transferrable to a derived or forked work. diff --git a/WHATSNEW.TXT b/WHATSNEW.TXT index 2f96ea4..e435ae1 100644 --- a/WHATSNEW.TXT +++ b/WHATSNEW.TXT @@ -50,17 +50,18 @@ New features in BBC BASIC (Z80) version 5.00, June 2024: 4.1 Bit-shifts <<, >>, >>> 4.2 Floating-point indirection (|) -4.3 RETURNed parameters from FN/PROC -4.4 Compound assignment (+=, -=, *=, /= etc.) -4.5 Assigning to a sub-string: LEFT$()=, MID$()= , RIGHT$()= -4.6 Hooks for CIRCLE,ELLIPSE,FILL,LINE,MOUSE,ORIGIN,RECTANGLE,TINT,SYS,WAIT -4.7 Hooks for WIDTH function, TINT function, MODE function +4.3 Additional VDU delimiter '|' +4.4 RETURNed parameters from FN/PROC +4.5 Compound assignment (+=, -=, *=, /= etc.) +4.6 Assigning to a sub-string: LEFT$()=, MID$()= , RIGHT$()= +4.7 Hooks for CIRCLE,ELLIPSE,FILL,LINE,MOUSE,ORIGIN,RECTANGLE,SYS,TINT,WAIT +4.8 Hooks for MODE function, TINT function, WIDTH function 5. Extensions to Acorn's BASIC V, compatible with BB4W, BBCSDL and BBCTTY 5.1 EXIT REPEAT / WHILE / FOR [var] 5.2 Address-of operator (^) -5.3 Byte variables and arrays (& suffix) +5.3 Byte (unsigned 8-bit) variables and arrays (& suffix) 5.4 'BY len' and 'TO term' qualifiers to GET$#file 5.5 ELSE IF THEN; (trailing semicolon) 5.6 == synonymous with = in comparisons diff --git a/bin/acorn/BBCBASIC.COM b/bin/acorn/BBCBASIC.COM new file mode 100644 index 0000000000000000000000000000000000000000..db61258bd368fe2e5d9fc4bf54ddb539fe1a8827 GIT binary patch literal 18944 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 delta 9801 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 diff --git a/src/ACORN.Z80 b/src/ACORN.Z80 new file mode 100644 index 0000000..404b8ea --- /dev/null +++ b/src/ACORN.Z80 @@ -0,0 +1,737 @@ + TITLE COPYRIGHT (C) R.T.RUSSELL 1983-2024 +; +;PATCH FOR BBC BASIC TO CP/M 2.2 & 3.0 +;* ACORN COMPUTERS Z80 TUBE VERSION * +;(C) COPYRIGHT R.T.RUSSELL, 02-01-1984 +;VERSION 5.0, 16-06-2024 +; +OSWRCH EQU 0FFEEH +OSWORD EQU 0FFF1H +OSBYTE EQU 0FFF4H +; +ESC EQU 1BH +TBY EQU 0FH +TTO EQU 0B8H +TFILL EQU 03H +; + EXTRN ITEMI + EXTRN EXPRI + EXTRN COMMA + EXTRN TERMQ + EXTRN BRAKET + EXTRN EXTERR + EXTRN STOREN + EXTRN TRAP + EXTRN VAR + EXTRN NXT + EXTRN XEQ +; + EXTRN ACCS + EXTRN COUNT + EXTRN WIDTH + EXTRN SCRAP +; + GLOBAL OSCALL + GLOBAL CLRSCN + GLOBAL PUTCSR + GLOBAL GETCSR + GLOBAL PUTIME + GLOBAL GETIME + GLOBAL OSKEY +; + GLOBAL CLG + GLOBAL MOVE + GLOBAL DRAW + GLOBAL PLOT + GLOBAL MODE + GLOBAL COLOUR + GLOBAL GCOL + GLOBAL ADVAL + GLOBAL SOUND + GLOBAL ENVEL + GLOBAL POINT +; + GLOBAL CIRCLE + GLOBAL ELLIPS + GLOBAL FILL + GLOBAL MOUSE + GLOBAL ORIGIN + GLOBAL RECTAN + GLOBAL LINE + GLOBAL TINT + GLOBAL WAIT + GLOBAL SYS +; + GLOBAL PUTIMS + GLOBAL GETIMS + GLOBAL TINTFN + GLOBAL MODEFN + GLOBAL WIDFN +; +;GETIME - Read elapsed-time clock. +; Outputs: DEHL = elapsed time (centiseconds) +; Destroys: A,D,E,H,L,F +; +GETIME: LD A,1 + LD HL,SCRAP + CALL OSWORD + LD HL,SCRAP + LD E,(HL) + INC HL + LD D,(HL) + INC HL + LD A,(HL) + INC HL + LD H,(HL) + LD L,A + EX DE,HL + RET +; +;GETIMS - Read real-time clock as string. +; Outputs: TIME$ in string accumulator +; E = string length (25) +; Destroys: A,B,C,D,E,H,L,F +; +GETIMS: LD A,14 + LD HL,SCRAP + LD (HL),0 + CALL OSWORD + LD HL,SCRAP + LD DE,ACCS + LD A,(HL) + CP E + RET Z + LD BC,25 + LDIR + RET +; +; +;PUTIME - Load elapsed-time clock. +; Inputs: DEHL = time to load (centiseconds) +; Destroys: A,D,E,H,L,F +; +PUTIME: PUSH IX + LD IX,SCRAP + LD (IX+0),L + LD (IX+1),H + LD (IX+2),E + LD (IX+3),D + LD A,2 + LD HL,SCRAP + CALL OSWORD + POP IX + RET +; +;PUTIMS - Wtite real-time clock as string. +; Inputs: string in string accumulator +; E = string length +; Destroys: A,B,C,D,E,H,L,F +; +PUTIMS: LD A,E ;Length + CP 26 + RET NC + LD B,0 + LD C,A + LD DE,SCRAP+1 + LD HL,ACCS + LDIR + LD HL,SCRAP + LD (HL),A + LD A,15 + JP OSWORD +; +; +;CLRSCN - Clear screen. +; Destroys: A,D,E,H,L,F +; +CLRSCN: LD A,0CH + JP OSWRCH +; +; +;OSKEY - Sample keyboard with specified wait. +; Inputs: HL = Time to wait (centiseconds) +; Outputs: Carry reset indicates time-out. +; If carry set, A = character typed. +; Destroys: A,D,E,H,L,F +; +OSKEY: LD A,129 + CALL OSBYTE + LD A,H + OR A + RET NZ ;TIME-OUT, CARRY RESET + LD A,L + SCF + RET ;NORMAL, CARRY SET +; +;PUTCSR - Move cursor to specified position. +; Inputs: DE = horizontal position (LHS=0) +; HL = vertical position (TOP=0) +; Destroys: A,D,E,H,L,F +; +PUTCSR: LD A,1FH + CALL OSWRCH + LD A,E + CALL OSWRCH + LD A,L + JP OSWRCH +; +;GETCSR - Return cursor coordinates. +; Outputs: DE = X coordinate (POS) +; HL = Y coordinate (VPOS) +; Destroys: A,D,E,H,L,F +; +GETCSR: LD A,134 + CALL OSBYTE + LD E,L + LD L,H + LD D,0 + LD H,D + RET +; +;POINT - var=POINT(x,y) +; +POINT: CALL EXPRI + EXX + PUSH HL + CALL CEXPRI + EXX + POP DE + CALL BRAKET + LD IX,SCRAP + LD (IX+0),E + LD (IX+1),D + LD (IX+2),L + LD (IX+3),H + LD HL,SCRAP + LD A,9 + CALL OSWORD + LD A,(IX+4) + LD L,A + ADD A,1 + SBC A,A + LD H,A +RETEXX: EXX + LD H,A + LD L,A + XOR A + LD C,A + RET +; +;ADVAL - var=ADVAL(n) +; +ADVAL: CALL ITEMI + EXX + LD A,128 + CALL OSBYTE + XOR A + JR RETEXX +; +;MODEFN - var=MODE +; +MODEFN: LD A,135 + CALL OSBYTE + LD L,H +RETU8: XOR A + LD H,A + JR RETEXX +; +;WIDFN - var=WIDTH +; +WIDFN: LD A,(WIDTH) + LD L,A + JR RETU8 +; +;ENVEL - ENVELOPE var,var,var,var,var,var,var, +; var,var,var,var,var,var,var +; +ENVEL: LD B,0 + LD IX,SCRAP + PUSH BC + PUSH IX +ENVEL1: CALL EXPRI + EXX + POP IX + POP BC + LD (IX),L + LD A,B + CP 13 + JR Z,ENVEL2 + INC B + INC IX + PUSH BC + PUSH IX + CALL COMMA + JR ENVEL1 +ENVEL2: LD HL,SCRAP + LD A,8 + CALL OSWORD + JP XEQ +; +;SOUND - SOUND var,var,var,var +; +SOUND: LD B,0 + LD IX,SCRAP + PUSH BC + PUSH IX +SOUND1: CALL EXPRI + EXX + POP IX + POP BC + LD (IX+0),L + LD (IX+1),H + INC IX + INC IX + INC B + INC B + LD A,B + CP 8 + JR Z,SOUND2 + PUSH BC + PUSH IX + CALL COMMA + JR SOUND1 +SOUND2: LD HL,SCRAP + LD A,7 + CALL OSWORD + JP XEQ +; +;MODE - MODE n +; +MODE: CALL EXPRI + XOR A + LD (COUNT),A + EXX + LD H,L + LD L,22 + CALL WRCH2 + JR XEQGO1 +; +;CLG +; +CLG: LD A,16 + CALL OSWRCH + JR XEQGO1 +; +;ORIGIN x,y +; +ORIGIN: CALL EXPRI + EXX + PUSH HL + CALL CEXPRI + EXX + POP DE + LD C,29 + CALL WRCH5 + JR XEQGO1 +; +;COLOUR n +;COLOUR n,p +;COLOUR n,r,g,b +; +COLOUR: CALL EXPRI ;n + EXX + LD A,(IY) + CP ',' + JR Z,PALCOL + LD H,L + LD L,17 + CALL WRCH2 + JR XEQGO1 +; +PALCOL: PUSH HL + CALL CEXPRI ;p or r + EXX + EX DE,HL + LD HL,0 + LD A,(IY) + CP ',' + JR NZ,PALET1 + PUSH DE + CALL CEXPRI ;g + EXX + PUSH HL + CALL CEXPRI ;b + EXX + POP DE + POP BC + LD A,L + POP HL + LD D,C ;r + LD C,L ;n + LD L,E ;g + LD H,A ;b + LD E,16 + PUSH BC +PALET1: POP BC + LD B,19 + CALL WRCH6 + JR XEQGO1 +; +;GCOL [a,]b +; +GCOL: CALL EXPRI + EXX + LD E,0 + LD A,(IY) + CP ',' + JR NZ,GCOL0 + PUSH HL + CALL CEXPRI + EXX + POP DE +GCOL0: LD H,L + LD L,E + LD D,18 + CALL WRCH3 ;DLH +XEQGO1: JP XEQ +; +;LINE x1,y1,x2,y2 +; +LINE: CALL EXPRI + EXX + PUSH HL + CALL EXPR3 + EX (SP),HL ;HL <- x1, (SP) <- y2 + PUSH BC + EX DE,HL + LD C,4 + CALL VDU25 + POP DE + POP HL + LD C,5 + JR PLOT4A +; +;CIRCLE [FILL] x,y,r +; +CIRCLE: CP TFILL + PUSH AF + JR NZ,CIRCL0 + INC IY +CIRCL0: CALL EXPRI + EXX + PUSH HL + CALL CEXPRI + EXX + PUSH HL + CALL CEXPRI + EXX + POP BC ;y + POP DE ;x + PUSH HL + LD L,C + LD H,B + LD C,4 ; PLOT 4 = MOVE + CALL VDU25 + POP DE ;r + LD HL,0 + POP AF + LD C,145 ; PLOT 145 = outline circle + JR NZ,PLOT4A + LD C,153 ; PLOT 153 = filled circle +PLOT4A: JR PLOT4 +; +;ELLIPSE [FILL] x,y,a,b +; +ELLIPS: CP TFILL + PUSH AF + JR NZ,ELLIP0 + INC IY +ELLIP0: CALL EXPRI + EXX + PUSH HL + CALL EXPR3 + EX (SP),HL ;HL <- x, (SP) <- b + PUSH BC + EX DE,HL + LD C,4 ; PLOT 4 = Move absolute + CALL VDU25 + POP DE ;a + PUSH DE + LD HL,0 + LD C,L ; PLOT 0 - Move relative + CALL VDU25 + POP DE ;a + XOR A + LD L,A + LD H,A + SBC HL,DE + EX DE,HL + POP HL ;b + POP AF + LD C,193 ; PLOT 193 = outline ellipse + JR NZ,PLOT4 + LD C,201 ; PLOT 201 = filled ellipse + JR PLOT4 +; +;MOVE [BY} x,y +;DRAW [BY] x,y +;PLOT [BY] [n,]x,y +;FILL [BY] x,y +; +MOVE: LD C,4 + JR PLOT1 +; +DRAW: LD C,5 + JR PLOT1 +; +FILL: LD C,133 + JR PLOT1 +; +PLOT: LD C,69 + CP TBY + JR Z,PLOT1 + CALL EXPRI + EXX + PUSH HL + CALL CEXPRI + EXX + LD A,(IY) + CP ',' + JR Z,PLOT3 + POP DE + LD C,69 + JR PLOT4 +; +PLOT1: CP TBY + JR NZ,PLOT2 + INC IY + RES 2,C ;Change absolute to relative +PLOT2: PUSH BC + CALL EXPRI + EXX +PLOT3: PUSH HL + CALL CEXPRI + EXX + POP DE + POP BC +PLOT4: CALL VDU25 + JP XEQ +; +;RECTANGLE [FILL] x,y,w[,h] [TO xnew,ynew] +; +RECTAN: CP TFILL + PUSH AF + JR NZ,RECT0 + INC IY +RECT0: CALL EXPRI + EXX + PUSH HL + CALL CEXPRI + EXX + PUSH HL + CALL CEXPRI + EXX + PUSH HL + LD A,(IY) + CP ',' + JR NZ,RECT1 + CALL CEXPRI + EXX +RECT1: POP BC ;w + POP DE ;y + EX (SP),HL ;HL <- x, (SP) <- h + PUSH BC + EX DE,HL + LD C,4 + CALL VDU25 + LD A,(IY) + CP TTO + JR Z,RECTTO + POP DE ;w + POP HL ;h + POP AF + JR NZ,OUTLIN + LD C,97 + JR PLOT4 +; +;Block copy / move: +; +RECTTO: INC IY ; Bump over TO + CALL EXPRI + EXX + PUSH HL + CALL CEXPRI + EXX + POP BC ;newx + POP DE ;w + EX (SP),HL ;HL <- h, (SP) <- newy + PUSH BC + EX DE,HL + LD C,0 + CALL VDU25 + POP DE ;newx + POP HL ;newy + POP AF + LD C,190 ; PLOT 190 - Block copy + JR NZ,PLOT4B + DEC C ; PLOT 189 - Block move +PLOT4B: JR PLOT4 +; +;Outline rectangle: +; +OUTLIN: LD C,9 ; PLOT 9 - draw relative + PUSH HL + LD HL,0 + CALL VDU25 ; side 1 + POP HL + PUSH DE + LD DE,0 + CALL VDU25 ; side 2 + POP DE + PUSH HL + XOR A + LD L,A + LD H,A + SBC HL,DE + EX DE,HL + LD L,A + LD H,A + CALL VDU25 ; side 3 + POP DE + XOR A + LD L,A + LD H,A + SBC HL,DE + LD E,A + LD D,A + JR PLOT4B +; +;MOUSE x, y, b +; +MOUSE: LD A,128 + LD HL,9 + CALL OSBYTE + PUSH HL + LD A,128 + LD HL,8 + CALL OSBYTE + PUSH HL + LD A,128 + LD HL,7 + CALL OSBYTE + PUSH HL + CALL VAR + POP HL + CALL STOREI + CALL COMMA + CALL NXT + CALL VAR + POP HL + CALL STOREI + CALL COMMA + CALL NXT + CALL VAR + POP HL + CALL STOREI +XEQGO2: JP XEQ +; +;WAIT [n] +; +WAIT: CALL TERMQ + JR Z,XEQGO2 + CALL EXPRI + EXX + LD B,H + LD C,L + CALL GETIME + ADD HL,BC + LD BC,0 + EX DE,HL + ADC HL,BC + EX DE,HL +WAIT1: CALL TRAP + PUSH DE + PUSH HL + CALL GETIME + POP BC + OR A + SBC HL,BC + LD H,B + LD L,C + EX DE,HL + POP BC + SBC HL,BC + JR NC,XEQGO2 + EX DE,HL + LD D,B + LD E,C + JR WAIT1 +; +;OSCALL - Trap call to FFxx +; +OSCALL: POP HL ;DITCH RETURN ADDRESS + LD HL,OSRET + PUSH HL ;NEW RETURN ADDRESS + LD A,(IX+4) ;A% + LD E,(IX+20) ;E% + LD H,(IX+100) ;Y% + LD L,(IX+96) ;X% + JP (IY) +OSRET: PUSH AF + LD A,L ;F H L A + LD L,H ;| | | | + EXX ;| | | | + POP BC ;| | | | + LD H,A ;| | | | + LD L,B ;H L H' L' + LD A,C + EXX + LD H,A + RET +; +VDU25: LD B,25 +WRCH6: LD A,B + CALL OSWRCH +WRCH5: LD A,C + CALL OSWRCH +WRCH4: LD A,E + CALL OSWRCH +WRCH3: LD A,D + CALL OSWRCH +WRCH2: LD A,L + CALL OSWRCH + LD A,H + JP OSWRCH +; +EXPR3: CALL CEXPRI + EXX + PUSH HL + CALL CEXPRI + EXX + PUSH HL + CALL CEXPRI + EXX + POP BC ;x2 + POP DE ;y1 + RET +; +CEXPRI: CALL COMMA + JP EXPRI +; +STOREI: BIT 7,A + JR NZ,EEK + BIT 6,A + JR NZ,EEK + EXX + LD HL,0 + LD C,L + JP STOREN +; +EEK: LD A,50 + CALL EXTERR + DEFB 13H ;'Bad ' + DEFB 04H ;'MOUSE' + DEFB 20H + DEFB 15H ;'variable' + DEFB 0 +; +TINT: +TINTFN: +SYS: + XOR A + CALL EXTERR + DEFM 'Sorry' + DEFB 0 +; + END + \ No newline at end of file diff --git a/src/AMOS.Z80 b/src/AMOS.Z80 new file mode 100644 index 0000000..711db2f --- /dev/null +++ b/src/AMOS.Z80 @@ -0,0 +1,1119 @@ + TITLE BBC BASIC (C) R.T.RUSSELL 1984-2024 +; +;PATCH FOR BBC BASIC TO CP/M 2.2 & 3.0 +;* ACORN COMPUTERS Z80 TUBE VERSION * +;(C) COPYRIGHT R.T.RUSSELL, 08-05-1984 +;VERSION 5.0, 14-06-2024 +; + GLOBAL OSINIT + GLOBAL OSRDCH + GLOBAL OSWRCH + GLOBAL OSLINE + GLOBAL OSSAVE + GLOBAL OSLOAD + GLOBAL OSOPEN + GLOBAL OSSHUT + GLOBAL OSBGET + GLOBAL OSBPUT + GLOBAL OSSTAT + GLOBAL GETEXT + GLOBAL GETPTR + GLOBAL PUTPTR + GLOBAL PROMPT + GLOBAL RESET + GLOBAL LTRAP + GLOBAL OSCLI + GLOBAL TRAP + GLOBAL BYE + GLOBAL SCRAP +; + EXTRN ESCAPE + EXTRN EXTERR + EXTRN CHECK + EXTRN CRLF +; + EXTRN ACCS + EXTRN FREE + EXTRN CURLIN + EXTRN USER + EXTRN VERMSG +; +;OSSAVE - Save an area of memory to a file. +; Inputs: HL addresses filename (term CR) +; DE = start address of data to save +; BC = length of data to save (bytes) +; Destroys: A,B,C,D,E,H,L,F +; +STSAVE: CALL SAVLOD ;*SAVE + JP C,HUH ;"Bad command" + PUSH HL + JR OSS1 +; +OSSAVE: PUSH BC ;SAVE + CALL SETUP0 +OSS1: EX DE,HL + CALL CREATE + JR NZ,SAVE + LD A,190 + CALL EXTERR + DEFM 'Directory full' + DEFB 0 +SAVE: CALL WRITE + ADD HL,BC + EX (SP),HL + SBC HL,BC + EX (SP),HL + JR Z,SAVE1 + JR NC,SAVE +SAVE1: POP BC +CLOSE: LD A,16 + CALL BDOS1 + INC A + RET NZ + LD A,200 + CALL EXTERR + DEFM 'Close error' + DEFB 0 +; +;OSSHUT - Close disk file(s). +; Inputs: E = file channel +; If E=0 all files are closed +; Destroys: A,B,C,D,E,H,L,F +; +OSSHUT: LD A,E + OR A + JR NZ,SHUTIT +SHUT0: INC E + BIT 3,E + RET NZ + PUSH DE + CALL SHUT1 + POP DE + JR SHUT0 +; +SHUTIT: CALL FIND1 + JR NZ,SHUT2 + JP CHANER +; +SHUT1: CALL FIND1 + RET Z +SHUT2: XOR A + LD (HL),A + DEC HL + LD (HL),A + LD HL,37 + ADD HL,DE + BIT 7,(HL) + INC HL + CALL NZ,WRITE + LD HL,FCBSIZ + ADD HL,DE + LD BC,(FREE) + SBC HL,BC + JR NZ,CLOSE + LD (FREE),DE ;RELEASE SPACE + JR CLOSE +; +;TYPE - *TYPE command. +;Types file to console output. +; +TYPE: SCF ;*TYPE + CALL OSOPEN + OR A + JR Z,NOTFND + LD E,A +TYPE1: CALL TRAP ;IMPORTANT (ACORN) + CALL OSBGET + CALL OSWRCH + JR NC,TYPE1 + JR OSSHUT +; +;OSLOAD - Load an area of memory from a file. +; Inputs: HL addresses filename (term CR) +; DE = address at which to load +; BC = maximum allowed size (bytes) +; Outputs: Carry reset indicates no room for file. +; Destroys: A,B,C,D,E,H,L,F +; +STLOAD: CALL SAVLOD ;*LOAD + PUSH HL + JR OSL1 +; +OSLOAD: PUSH BC ;LOAD + CALL SETUP0 +OSL1: EX DE,HL + CALL OPEN + JR NZ,LOAD0 +NOTFND: LD A,214 + CALL EXTERR + DEFM 'File not found' + DEFB 0 +LOAD: CALL READ + JR NZ,LOAD1 + CALL INCSEC + ADD HL,BC +LOAD0: EX (SP),HL + SBC HL,BC + EX (SP),HL + JR NC,LOAD +LOAD1: POP BC + PUSH AF + CALL CLOSE + POP AF + CCF +RESET: RET +; +;OSOPEN - Open a file for reading or writing. +; Inputs: HL addresses filename (term CR) +; Carry set for OPENIN, cleared for OPENOUT. +; Outputs: A = file channel (=0 if cannot open) +; Destroys: A,B,C,D,E,H,L,F +; +OSOPEN: PUSH AF ;SAVE CARRY + CALL SETUP0 + POP AF + CALL NC,CREATE + CALL C,OPEN + RET Z ;ERROR + LD B,7 ;MAX. NUMBER OF FILES + LD HL,TABLE+13 +OPEN1: LD A,(HL) + DEC HL + OR (HL) + JR Z,OPEN2 + DEC HL + DJNZ OPEN1 + LD A,192 + CALL EXTERR + DEFM 'Too many open files' + DEFB 0 +; +OPEN2: LD DE,(FREE) ;FREE SPACE POINTER + LD (HL),E + INC HL + LD (HL),D + LD A,B ;CHANNEL (1-7) + LD HL,FCBSIZ + ADD HL,DE ;RESERVE SPACE + LD (FREE),HL + LD HL,FCB + PUSH DE + LD BC,36 + LDIR ;COPY FCB + EX DE,HL + INC HL + LD (HL),C ;CLEAR PTR + INC HL + POP DE + LD B,A + CALL RDF ;READ OR FILL + LD A,B + JP CHECK +; +;OSBPUT - Write a byte to a random disk file. +; Inputs: E = file channel +; A = byte to write +; Destroys: A,B,C,F +; +OSBPUT: PUSH DE + PUSH HL + LD B,A + CALL FIND + LD A,B + LD B,0 + DEC HL + LD (HL),B ;CLEAR EOF + INC HL + LD C,(HL) + RES 7,C + SET 7,(HL) + INC (HL) + INC HL + PUSH HL + ADD HL,BC + LD (HL),A + POP HL + CALL Z,WRRDF ;WRITE THEN READ/FILL + POP HL + POP DE + RET +; +;OSBGET - Read a byte from a random disk file. +; Inputs: E = file channel +; Outputs: A = byte read +; Carry set if LAST BYTE of file +; Destroys: A,B,C,F +; +OSBGET: PUSH DE + PUSH HL + CALL FIND + LD C,(HL) + RES 7,C + INC (HL) + INC HL + PUSH HL + LD B,0 + ADD HL,BC + LD B,(HL) + POP HL + CALL PE,INCRDF ;INC SECTOR THEN READ + CALL Z,WRRDF ;WRITE THEN READ/FILL + LD A,B + POP HL + POP DE + RET +; +;OSSTAT - Read file status. +; Inputs: E = file channel +; Outputs: Z flag set - EOF +; (If Z then A=0) +; DE = address of file block. +; Destroys: A,D,E,H,L,F +; +OSSTAT: CALL FIND + DEC HL + LD A,(HL) + INC A + RET +; +;GETEXT - Find file size. +; Inputs: E = file channel +; Outputs: DEHL = file size (0-&800000) +; Destroys: A,B,C,D,E,H,L,F +; +GETEXT: CALL FIND + EX DE,HL + LD DE,FCB + LD BC,36 + PUSH DE + LDIR ;COPY FCB + EX DE,HL + EX (SP),HL + EX DE,HL + LD A,35 + CALL BDOS1 ;COMPUTE SIZE + POP HL + XOR A + JR GETPT1 +; +;GETPTR - Return file pointer. +; Inputs: E = file channel +; Outputs: DEHL = pointer (0-&7FFFFF) +; Destroys: A,B,C,D,E,H,L,F +; +GETPTR: CALL FIND + LD A,(HL) + ADD A,A + DEC HL +GETPT1: DEC HL + LD D,(HL) + DEC HL + LD E,(HL) + DEC HL + LD H,(HL) + LD L,A + SRL D + RR E + RR H + RR L + RET +; +;PUTPTR - Update file pointer. +; Inputs: A = file channel +; DEHL = new pointer (0-&7FFFFF) +; Destroys: A,B,C,D,E,H,L,F +; +PUTPTR: LD D,L + ADD HL,HL + RL E + LD B,E + LD C,H + LD E,A ;CHANNEL + PUSH DE + CALL FIND + POP AF + AND 7FH + BIT 7,(HL) ;PENDING WRITE? + JR Z,PUTPT1 + OR 80H +PUTPT1: LD (HL),A + PUSH DE + PUSH HL + DEC HL + DEC HL + DEC HL + LD D,(HL) + DEC HL + LD E,(HL) + EX DE,HL + OR A + SBC HL,BC + POP HL + POP DE + RET Z + INC HL + OR A + CALL M,WRITE + PUSH HL + DEC HL + DEC HL + DEC HL + LD (HL),0 + DEC HL + LD (HL),B + DEC HL + LD (HL),C ;NEW RECORD NO. + POP HL + JR RDF +; +;WRRDF - Write, read; if EOF fill with zeroes. +;RDF - Read; if EOF fill with zeroes. +; Inputs: DE address FCB. +; HL addresses data buffer. +; Outputs: A=0, Z-flag set. +; Carry set if fill done (EOF) +; Destroys: A,H,L,F +; +WRRDF: CALL WRITE +RDF: CALL READ + DEC HL + RES 7,(HL) + DEC HL + LD (HL),A ;CLEAR EOF FLAG + RET Z + LD (HL),-1 ;SET EOF FLAG + INC HL + INC HL + PUSH BC + XOR A + LD B,128 +FILL: LD (HL),A + INC HL + DJNZ FILL + POP BC + SCF + RET +; +;INCRDF - Increment record, read; if EOF fill. +; Inputs: DE addresses FCB. +; HL addresses data buffer. +; Outputs: A=1, Z-flag reset. +; Carry set if fill done (EOF) +; Destroys: A,H,L,F +; +INCRDF: CALL INCSEC + CALL RDF + INC A + RET +; +;READ - Read a record from a disk file. +; Inputs: DE addresses FCB. +; HL = address to store data. +; Outputs: A<>0 & Z-flag reset indicates EOF. +; Carry = 0 +; Destroys: A,F +; +;BDOS1 - CP/M BDOS call. +; Inputs: A = function number +; DE = parameter +; Outputs: AF = result (carry=0) +; Destroys: A,F +; +READ: CALL SETDMA + LD A,33 +BDOS1: CALL BDOS0 + JR NZ,CPMERR + OR A + RET +CPMERR: LD A,255 + CALL EXTERR + DEFM 'CP/M Error' + DEFB 0 +; +BDOS0: PUSH BC + PUSH DE + PUSH HL + PUSH IX + PUSH IY + LD C,A + CALL BDOS + INC H + DEC H + POP IY + POP IX + POP HL + POP DE + POP BC + RET +; +;WRITE - Write a record to a disk file. +; Inputs: DE addresses FCB. +; HL = address to get data. +; Destroys: A,F +; +WRITE: CALL SETDMA + LD A,40 + CALL BDOS1 + JR Z,INCSEC + LD A,198 + CALL EXTERR + DEFM 'Disk full' + DEFB 0 +; +;INCSEC - Increment random record number. +; Inputs: DE addresses FCB. +; Destroys: F +; +INCSEC: PUSH HL + LD HL,33 + ADD HL,DE +INCS1: INC (HL) + INC HL + JR Z,INCS1 + POP HL + RET +; +;OPEN - Open a file for access. +; Inputs: FCB set up. +; Outputs: DE = FCB +; A=0 & Z-flag set indicates Not Found. +; Carry = 0 +; Destroys: A,D,E,F +; +OPEN: LD DE,FCB + LD A,15 + CALL BDOS1 + INC A + RET +; +;CREATE - Create a disk file for writing. +; Inputs: FCB set up. +; Outputs: DE = FCB +; A=0 & Z-flag set indicates directory full. +; Carry = 0 +; Destroys: A,D,E,F +; +CREATE: CALL CHKAMB + LD DE,FCB + LD A,19 + CALL BDOS1 ;DELETE + LD A,22 + CALL BDOS1 ;MAKE + INC A + RET +; +;CHKAMB - Check for ambiguous filename. +; Destroys: A,D,E,F +; +CHKAMB: PUSH BC + LD DE,FCB + LD B,12 +CHKAM1: LD A,(DE) + CP '?' + JR Z,AMBIG ;AMBIGUOUS + INC DE + DJNZ CHKAM1 + POP BC + RET +AMBIG: LD A,204 + CALL EXTERR + DEFM 'Bad name' + DEFB 0 +; +;SETDMA - Set "DMA" address. +; Inputs: HL = address +; Destroys: A,F +; +SETDMA: LD A,26 + EX DE,HL + CALL BDOS0 + EX DE,HL + RET +; +;FIND - Find file parameters from channel. +; Inputs: E = channel +; Outputs: DE addresses FCB +; HL addresses pointer byte (FCB+37) +; Destroys: A,D,E,H,L,F +; +FIND: INC E + DEC E + JR Z,CHANER + CALL FIND1 + LD HL,37 + ADD HL,DE + RET NZ +CHANER: LD A,222 + CALL EXTERR + DEFM 'Invalid channel' + DEFB 0 +; +;FIND1 - Look up file table. +; Inputs: E = channel +; Outputs: Z-flag set = file not opened +; If NZ, DE addresses FCB +; HL points into table +; Destroys: A,D,E,H,L,F +; +FIND1: LD A,E + AND 7 + ADD A,A + LD E,A + LD D,0 + LD HL,TABLE-2 + ADD HL,DE + LD E,(HL) + INC HL + LD D,(HL) + LD A,D + OR E + RET +; +;SETUP - Set up File Control Block. +; Inputs: HL addresses filename +; Format [A:]FILENAME[.EXT] +; Device defaults to current drive +; Extension defaults to .BBC +; A = fill character +; Outputs: HL updated +; A = terminator +; BC = 128 +; Destroys: A,B,C,H,L,F +; +;FCB FORMAT (36 BYTES TOTAL): +; 0 0=SAME DISK, 1=DISK A, 2=DISK B (ETC.) +; 1-8 FILENAME, PADDED WITH SPACES +; 9-11 EXTENSION, PADDED WITH SPACES +; 12 CURRENT EXTENT, SET TO ZERO +; 32-35 CLEARED TO ZERO +; +SETUP0: LD A,' ' +SETUP: PUSH DE + PUSH HL + LD DE,FCB+9 + LD HL,BBC + LD BC,3 + LDIR + LD HL,FCB+32 + LD B,4 +SETUP1: LD (HL),C + INC HL + DJNZ SETUP1 + POP HL + LD C,A + XOR A + LD (DE),A + POP DE + CALL SKIPSP + CP '"' + JR NZ,SETUP2 + INC HL + CALL SKIPSP + CALL SETUP2 + CP '"' + INC HL + JR Z,SKIPSP +BADSTR: LD A,253 + CALL EXTERR + DEFM 'Bad string' + DEFB 0 +; +PARSE: LD A,(HL) + INC HL + CP '`' + RET NC + CP '?' + RET C + XOR 40H + RET +; +SETUP2: PUSH DE + INC HL + LD A,(HL) + CP ':' + DEC HL + LD A,B + JR NZ,DEVICE + LD A,(HL) ;DRIVE + AND 31 + INC HL + INC HL +DEVICE: LD DE,FCB + LD (DE),A + INC DE + LD B,8 +COPYF: LD A,(HL) + CP '.' + JR Z,COPYF1 + CP ' ' + JR Z,COPYF1 + CP CR + JR Z,COPYF1 + CP '=' + JR Z,COPYF1 + CP '"' + JR Z,COPYF1 + LD C,'?' + CP '*' + JR Z,COPYF1 + LD C,' ' + INC HL + CP '|' + JR NZ,COPYF2 + CALL PARSE + JR COPYF0 +COPYF1: LD A,C +COPYF2: CALL UPPRC +COPYF0: LD (DE),A + INC DE + DJNZ COPYF +COPYF3: LD A,(HL) + INC HL + CP '*' + JR Z,COPYF3 + CP '.' + LD BC,3*256+' ' + LD DE,FCB+9 + JR Z,COPYF + DEC HL + POP DE + LD BC,128 +SKIPSP: LD A,(HL) + CP ' ' + RET NZ + INC HL + JR SKIPSP +; +BBC: DEFM 'BBC' +; +;HEX - Read a hex string and convert to binary. +; Inputs: HL = text pointer +; Outputs: HL = updated text pointer +; DE = value +; A = terminator (spaces skipped) +; Destroys: A,D,E,H,L,F +; +HEX: LD DE,0 ;INITIALISE + CALL SKIPSP +HEX1: LD A,(HL) + CALL UPPRC + CP '0' + JR C,SKIPSP + CP '9'+1 + JR C,HEX2 + CP 'A' + JR C,SKIPSP + CP 'F'+1 + JR NC,SKIPSP + SUB 7 +HEX2: AND 0FH + EX DE,HL + ADD HL,HL + ADD HL,HL + ADD HL,HL + ADD HL,HL + EX DE,HL + OR E + LD E,A + INC HL + JR HEX1 +; +;OSCLI - Process an "operating system" command +; +OSCLI: CALL SKIPSP + CP CR + RET Z + CP '|' + RET Z + CP '.' + JP Z,DOT ;*. + EX DE,HL + LD HL,COMDS +OSCLI0: LD A,(DE) + CALL UPPRC + CP (HL) + JR Z,OSCLI2 + JR C,UNK +OSCLI1: BIT 7,(HL) + INC HL + JR Z,OSCLI1 + INC HL + INC HL + JR OSCLI0 +; +OSCLI2: PUSH DE +OSCLI3: INC DE + INC HL + LD A,(DE) + CALL UPPRC + CP '.' ;ABBREVIATED? + JR Z,OSCLI4 + XOR (HL) + JR Z,OSCLI3 + CP 80H + JR Z,OSCLI4 + POP DE + JR OSCLI1 +; +OSCLI4: POP AF + INC DE +OSCLI5: BIT 7,(HL) + INC HL + JR Z,OSCLI5 + LD A,(HL) + INC HL + LD H,(HL) + LD L,A + PUSH HL + EX DE,HL + JP SKIPSP +; +UNK: EX DE,HL + JP ASCLI +; +; +BYE: RST 0 ;*BYE, *QUIT +; +ERA: CALL SETUP0 ;*ERA, *ERASE + LD C,19 + JR XEQ ;"DELETE" +; +RES: LD C,13 ;*RESET + JR XEQ ;"RESET" +; +DRV: CALL SETUP0 ;*DRIVE + LD A,(FCB) + DEC A + JP M,HUH + LD E,A + LD C,14 + JR XEQ0 +; +REN: CALL SETUP0 ;*REN, *RENAME + CP '=' + JR NZ,HUH + INC HL + PUSH HL + CALL EXISTS + LD HL,FCB + LD DE,FCB+16 + LD BC,12 + LDIR + POP HL + CALL SETUP0 + CALL CHKAMB + LD C,23 +XEQ: LD DE,FCB +XEQ0: LD A,(HL) + CP CR + JR NZ,HUH +BDC: LD A,C + CALL BDOS1 + RET P +HUH: LD A,254 + CALL EXTERR + DEFM 'Bad command' + DEFB 0 +; +EXISTS: LD HL,DSKBUF + CALL SETDMA + LD DE,FCB + LD A,17 + CALL BDOS1 ;SEARCH + INC A + RET Z + LD A,196 + CALL EXTERR + DEFM 'File exists' + DEFB 0 +; +SAVLOD: CALL SETUP0 ;PART OF *SAVE, *LOAD + CALL HEX + CP '+' + PUSH AF + PUSH DE + JR NZ,SAVLO1 + INC HL +SAVLO1: CALL HEX + CP CR + JR NZ,HUH + EX DE,HL + POP DE + POP AF + RET Z + OR A + SBC HL,DE + RET NZ + JR HUH +; +DOT: INC HL +DIR: LD A,'?' ;*DIR + CALL SETUP + CP CR + JR NZ,HUH + LD C,17 +DIR0: LD B,4 +DIR1: CALL LTRAP + LD DE,FCB + LD HL,DSKBUF + CALL SETDMA + LD A,C + CALL BDOS1 ;SEARCH DIRECTORY + JP M,CRLF + RRCA + RRCA + RRCA + AND 60H + LD E,A + LD D,0 + LD HL,DSKBUF+1 + ADD HL,DE + PUSH HL + LD DE,8 + ADD HL,DE + LD E,(HL) + INC HL + BIT 7,(HL) ;SYSTEM FILE? + POP HL + LD C,18 + JR NZ,DIR1 + PUSH BC + LD A,B + CP 4 + LD A,' ' + CALL Z,DRIVE + CALL OSWRCH + LD B,8 + LD A,' ' + BIT 7,E ;READ ONLY? + JR Z,DIR3 + LD A,'*' +DIR3: CALL CPTEXT + LD B,3 + LD A,' ' + CALL SPTEXT + POP BC + DJNZ DIR1 + CALL CRLF + JR DIR0 +; +DRIVE: LD A,(FCB) + DEC A + LD C,25 + CALL M,BDC + ADD A,'A' + RET +; +UPPRC: AND 7FH + CP '`' + RET C + AND 5FH ;CONVERT TO UPPER CASE + RET +; +HELP: LD B,32 ;*HELP + LD HL,VERMSG + JP PTEXT +; +; +COMDS: DEFM 'BY' + DEFB 'E'+80H + DEFW BYE + DEFM 'CP' + DEFB 'M'+80H + DEFW BYE + DEFM 'DI' + DEFB 'R'+80H + DEFW DIR + DEFM 'DRIV' + DEFB 'E'+80H + DEFW DRV + DEFM 'ERAS' + DEFB 'E'+80H + DEFW ERA + DEFM 'ER' + DEFB 'A'+80H + DEFW ERA + DEFM 'HEL' + DEFB 'P'+80H + DEFW HELP + DEFM 'LOA' + DEFB 'D'+80H + DEFW STLOAD + DEFM 'QUI' + DEFB 'T'+80H + DEFW BYE + DEFM 'RENAM' + DEFB 'E'+80H + DEFW REN + DEFM 'RE' + DEFB 'N'+80H + DEFW REN + DEFM 'RESE' + DEFB 'T'+80H + DEFW RES + DEFM 'SAV' + DEFB 'E'+80H + DEFW STSAVE + DEFM 'TYP' + DEFB 'E'+80H + DEFW TYPE + DEFB 0FFH +; +;PROCESS 6502's BRK INSTRUCTION +; +BRK: LD HL,(BRKPTR) + PUSH HL +BRKTRP: POP HL + LD A,(HL) + INC HL + PUSH HL + JP EXTERR +; +;TRAP - Test for "ESC" and abort if so. +; Destroys: A,H,L,F +; +TRAP: +LTRAP: LD A,(BRKFLG) + OR A + RET P +ESC: LD A,126 + CALL ASBYTE + JP ESCAPE +; +;PTEXT - Print text +; Inputs: HL = address of text +; B = number of characters to print +; Destroys: A,B,H,L,F +; +CPTEXT: PUSH AF + LD A,':' + CALL OSWRCH + POP AF +SPTEXT: CALL OSWRCH +PTEXT: LD A,(HL) + AND 7FH + INC HL + CALL OSWRCH + DJNZ PTEXT + RET +; +;OSINIT - Initialise RAM mapping etc. +;If BASIC is entered by BBCBASIC FILENAME then file +;FILENAME.BBC is automatically CHAINed. +; Outputs: DE = initial value of HIMEM (top of RAM) +; HL = initial value of PAGE (user program) +; Z-flag reset indicates AUTO-RUN. +; Destroys: A,B,C,D,E,H,L,F +; +OSINIT: LD A,0C3H + LD (38H),A + LD HL,BRKTRP + LD (39H),HL + LD HL,BRK + LD (BRKVEC),HL + LD A,229 + LD HL,0 + CALL ASBYTE ;ESC interrupts program + LD A,230 + LD HL,0 + CALL ASBYTE ;ESC flushes buffers + LD C,45 + LD E,254 + CALL BDOS ;TRAP ERRORS (CP/M 3) + XOR A + LD B,INILEN + LD HL,TABLE +CLRTAB: LD (HL),A ;CLEAR FILE TABLE + INC HL + DJNZ CLRTAB + LD DE,ACCS + LD HL,DSKBUF + LD C,(HL) + INC HL + CP C + JR Z,NOBOOT + LDIR ;COPY TO ACCS +NOBOOT: EX DE,HL + LD (HL),CR + LD DE,(6) ;DE = HIMEM + LD E,A ;PAGE BOUNDARY + LD HL,USER + RET +; +;OSRDCH - Read a character from console input. +; Outputs: A = character. +; Destroys: A,F +; +OSRDCH: PUSH BC + PUSH DE + PUSH HL + CALL ASRDCH + POP HL + POP DE + POP BC + RET +; +;OSWRCH - Write a character to console output. +; Inputs: A = character. +; Destroys: Nothing +; +PROMPT: LD A,'>' +OSWRCH: PUSH AF + PUSH BC + PUSH DE + PUSH HL + CALL ASWRCH + POP HL + POP DE + POP BC + POP AF + RET +; +;OSLINE - Read a complete line, terminated by +;carriage-return. +; Inputs: HL addresses destination buffer. +; (L=0) +; Outputs: Buffer filled, terminated by CR. +; A=0. +; Destroys: A,B,C,D,E,H,L,IX,F +; +OSLINE: LD IX,SCRAP + LD (IX+0),L + LD (IX+1),H + LD (IX+2),255 ;MAX. LINE LENGTH + LD (IX+3),' ' ;MIN. ASCII VALUE + LD (IX+4),255 ;MAX. ASCII VALUE + LD A,218 + LD HL,0 + CALL ASBYTE ;FLUSH VDU QUEUE + XOR A + LD HL,SCRAP + CALL ASWORD + JP C,ESC + XOR A + RET +; +CR EQU 0DH +FCBSIZ EQU 128+36+2 +; +BDOS EQU 5 +; +BRKFLG EQU 0FF80H +BRKPTR EQU 0FF82H +ASRDCH EQU 0FFE0H +ASWRCH EQU 0FFEEH +ASWORD EQU 0FFF1H +ASBYTE EQU 0FFF4H +ASCLI EQU 0FFF7H +BRKVEC EQU 0FFFAH +; +FCB EQU 5CH +DSKBUF EQU 80H +; +TABLE: DEFS 14 ;FILE BLOCK POINTERS +INILEN EQU $-TABLE +SCRAP: DEFS 31 + DEFB 0 +; +FIN: END + \ No newline at end of file diff --git a/src/CMOS.Z80 b/src/CMOS.Z80 index 539ee06..3bac740 100644 --- a/src/CMOS.Z80 +++ b/src/CMOS.Z80 @@ -440,14 +440,14 @@ INCRDF: CALL INCSEC ; READ: CALL SETDMA LD A,33 -BDOS1: CALL BDOS0 ;* - JR NZ,CPMERR ;* - OR A ;* - RET ;* -CPMERR: LD A,255 ;* CP/M 3 - CALL EXTERR ;* BDOS ERROR - DEFM 'CP/M Error' ;* - DEFB 0 ;* +BDOS1: CALL BDOS0 + JR NZ,CPMERR + OR A + RET +CPMERR: LD A,255 + CALL EXTERR + DEFM 'CP/M Error' + DEFB 0 ; BDOS0: PUSH BC PUSH DE @@ -456,8 +456,8 @@ BDOS0: PUSH BC PUSH IY LD C,A CALL BDOS - INC H ;* TEST H - DEC H ;* CP/M 3 ONLY + INC H + DEC H POP IY POP IX POP HL @@ -883,10 +883,10 @@ DIR1: CALL LTRAP LD HL,DSKBUF+1 ADD HL,DE PUSH HL - LD DE,8 ;** + LD DE,8 ADD HL,DE - LD E,(HL) ;** - INC HL ;** + LD E,(HL) + INC HL BIT 7,(HL) ;SYSTEM FILE? POP HL LD C,18 @@ -899,13 +899,13 @@ DIR1: CALL LTRAP ADD A,'A' CALL OSWRCH LD B,8 - LD A,' ' ;** - BIT 7,E ;** READ ONLY? - JR Z,DIR3 ;** - LD A,'*' ;** + LD A,' ' + BIT 7,E ;READ ONLY? + JR Z,DIR3 + LD A,'*' DIR3: CALL CPTEXT LD B,3 - LD A,' ' ;** + LD A,' ' CALL SPTEXT POP BC DJNZ DIR2 @@ -1046,11 +1046,11 @@ COMDS: DEFM 'BY' ; B = number of characters to print ; Destroys: A,B,H,L,F ; -CPTEXT: PUSH AF ;** +CPTEXT: PUSH AF LD A,':' CALL OSWRCH - POP AF ;** -SPTEXT: CALL OSWRCH ;** + POP AF +SPTEXT: CALL OSWRCH PTEXT: LD A,(HL) AND 7FH INC HL diff --git a/src/EXEC.Z80 b/src/EXEC.Z80 index da5ac69..7250bfa 100644 --- a/src/EXEC.Z80 +++ b/src/EXEC.Z80 @@ -10,7 +10,7 @@ ; ;VERSION 2.1, 22-01-1984 ;VERSION 3.1, 11-06-1987 -;VERSION 5.0, 10-06-2024 +;VERSION 5.0, 16-06-2024 ; GLOBAL XEQ GLOBAL RUN0 @@ -1557,14 +1557,14 @@ IF: CALL EXPRI JR Z,IFNOT ;FALSE LD A,(IY) CP TTHEN - JR NZ,XEQGO7 + JP NZ,XEQ IF0: INC IY ;SKIP "THEN" LD A,(IY) CP ';' JR Z,IF0 IF1: CALL NXT CP TLINO - JR NZ,XEQGO7 ;STATEMENT FOLLOWS + JP NZ,XEQ ;STATEMENT FOLLOWS JP GOTO ;LINE NO. FOLLOWS ; IFELSE: LD A,(IY) @@ -1968,13 +1968,17 @@ TRACE0: DEC HL TRACE1: LD (TRACEN),HL JR XEQGO1 ; -;VDU expr,expr;.... +;VDU expr,expr;....[|] ; VDU: CALL EXPRI EXX LD A,L - CALL OSWRCH + LD B,1 +VDU1: CALL OSWRCH + DJNZ VDU1 LD A,(IY) + CP '|' + JR Z,VDU4 CP ',' JR Z,VDU2 CP ';' @@ -1986,6 +1990,11 @@ VDU3: CALL TERMQ JR NZ,VDU JR XEQGO1 ; +VDU4: INC IY + XOR A + LD B,9 + JR VDU1 +; ;CLOSE channel number ; CLOSE: CALL CHANEL diff --git a/src/MAIN.Z80 b/src/MAIN.Z80 index 335449c..2b56132 100644 --- a/src/MAIN.Z80 +++ b/src/MAIN.Z80 @@ -174,7 +174,7 @@ PURGE: LD (HL),A ;CLEAR SCRATCHPAD CALL NEWIT JP NZ,CHAIN0 ;AUTO-RUN CALL TELL -VERMSG: DEFM 'BBC BASIC (Z80) Version 5beta5' +VERMSG: DEFM 'BBC BASIC (Z80) Version 5beta6' DEFB CR DEFB LF NOTICE: DEFM '(C) Copyright R.T.Russell 2024' diff --git a/src/MATH.Z80 b/src/MATH.Z80 index 1d4e864..bf886d9 100644 --- a/src/MATH.Z80 +++ b/src/MATH.Z80 @@ -4,7 +4,7 @@ ;(C) COPYRIGHT R.T.RUSSELL 1986-2024 ;VERSION 0.0, 26-10-1986 ;VERSION 0.1, 14-12-1988 (BUG FIX) -;VERSION 5.0, 21-05-2024 (SHIFTS ADDED) +;VERSION 5.0, 16-06-2024 (SHIFTS ADDED) ; ;BINARY FLOATING POINT REPRESENTATION: ; 32 BIT SIGN-MAGNITUDE NORMALIZED MANTISSA @@ -387,16 +387,7 @@ IMUL: LD A,H JP NEGATE ; IMUL1: DEC C - EXX - SLA E - RL D - EXX - RL E - RL D - EXX - ADC HL,HL - EXX - ADC HL,HL + CALL SLA8 JP P,IMUL1 ;NORMALISE EX AF,AF' RET M @@ -2177,30 +2168,12 @@ SQR2: INC A RET P SQRA: SLA C RL B + INC C EXX RL C RL B - EXX - INC C - SLA E - RL D - EXX - RL E - RL D - EXX - ADC HL,HL - EXX - ADC HL,HL - EXX - SLA E - RL D - EXX - RL E - RL D - EXX - ADC HL,HL - EXX - ADC HL,HL + CALL SLA8 + CALL SLA8 EXX JP NC,SQR1 SQR3: OR A @@ -2230,6 +2203,18 @@ SQRB: ADD HL,HL DEC C RET ; +SLA8: EXX + SLA E + RL D + EXX + RL E + RL D + EXX + ADC HL,HL + EXX + ADC HL,HL + RET +; DIGITQ: LD A,(IX) CP '9'+1 CCF diff --git a/tests/EXITTEST.BBC b/tests/EXITTEST.BBC index 95b72428290bf280b0b47527d8beeaf2c192a8df..e7abb45292c297481bcde3cd475a8ca92cc7c0b8 100644 GIT binary patch delta 716 zcmaFM*}y$Pww_mn;hsXUs=_M;T|-_$Iflmyo~jDA3Wf?h6bub`g*1QyULXM@1E7ep z0k6Cf!*hrdQ-ubol&M0Gf`9@@CoiiF!&_cfHy|Mv09I&YXR6QwRA*ynWUBCsmotjN z4`e(qPYT0v1wREl8;~`Ec?_=-d$p7#vlArYRw*QsU)00klFJ z9>Lfq{V)h(Uk}LNPFcXy0HJ25xSrV5F!4in2kKFhgmuQifFwTYzvM5S{?S MOF(!B2%iBV0OGF7J^%m! delta 568 zcmZqRe#<#QR#i}h;jx0Js)DV8p~4OYLjztRIiP?SNWjPdC}M2DE3YxpU#{MW;Vmz# z4UiCXV|WhKVPj{i&;nFwV`pTl@Qar-fWZ%B2ro|*!*K;a1sjlAf+-BI6z(WkDZEo? zRd@wbmB-)>R>fTbROJm+Wy;Im1X9Gy-NOJ=r92Jj1YekwfZCrccu#yIpuB+Li$Y0$ zc4}U+mBQP<=XeEIG2B5B5Zf|Yo>4S@AJ7tQkXu+!Fr4G%y99JE&?-9xBcKZ;?=XA? zng?>LsX~u}fWmQwZiT-JJ9)XD0X+cL#q$B`HlPpKe?c6_!U%U9-{i@RO7#+qFguhO zfp+LHLhUdI+QDiD6cTrU2^j&y2^b)DKnsC#UW`_}0wIjhFa`y>5wBnzkdGV*>=}&U zFe!ptD^LSe;th)@Q&C>_Hi(i5a3!*{CVMi;ST12i3#E08XrZ)&(NP8HeXw8uLd5CD#bg5QUP|;*w&8