+++ /dev/null
- ; must begin on a page boundary (address % 256 == 0) to ensure
- ; the jump table is correctly aligned
- ;
- ; This varies by platform so we really want to make this relocatable
- ; not linked per platform somehow
- ;
- .area ASEG(ABS)
- .org 0xf000
-startaddr:
-
-fcb .EQU 0x005C ; Default CP/M FCB
-buff .EQU 0x0080 ; Default CP/M Buffer
-BS .EQU 0x08 ; ASCII BackSpace
-TAB .EQU 0x09 ; ASCII Horizontal Tab
-LF .EQU 0x0A ; ASCII Line Feed
-CR .EQU 0x0D ; ASCII Carriage Return
-ESC .EQU 0x1B ; ASCII ESCape Char
-
-TCGETS .EQU 1 ; Fuzix - get tty data
-TCSETS .EQU 2 ; Fuzix - set tty data
-TIOCINQ .EQU 5 ; Fuzix - characters pending
-
-STDIN .EQU 0 ; file descriptor value of keyboard
-STDOUT .EQU 1 ; file descriptor value of display
-
-; Initialize both FCB entries to blank values
-
-EStart: LD HL,#fcbDat ; Move initial FCB
- PUSH HL
- LD DE,#fcb ; into
- LD BC,#16 ; position
- LDIR
- POP HL
- LD C,#16 ; init 2nd entry
- LDIR
-
-; Catenate argv[] elements into default buffer
-
- POP IX ; Skip argc
- POP IX ; Get Ptr to argv[]
- LD DE,#buff+1 ; Pt to CP/M Dflt Buffer
- LD C,#0 ; Cnt to 0
- INC IX ; Skip Argv[0]
- INC IX
-Cold0: LD L, 0(IX) ; Get Ptr to Arg element
- INC IX
- LD H, 0(IX)
- INC IX
- LD A,H
- OR L ; End?
- JR Z,Cold2 ; ..exit if Yes
- LD A,#' ' ; Add space separator for args
- LD (DE),A
- INC DE
- INC C ; bump count
-Cold1: LD A,(HL)
- OR A ; End of string?
- JR Z,Cold0 ; ..try next if Yes
- CP #'a' ; ensure
- JR C,NoCap ; it
- CP #'z'+1 ; is
- JR NC,NoCap ; UCase
- AND #0x5F
-NoCap: LD (DE),A ; Move a byte
- INC HL
- INC C ; bump count
- INC E ; bump ptr
- JR NZ,Cold1 ; ..get next byte if no bfr ovfl
- ;..else 0FF->100H, terminate
- DEC E ; (back up for Null-termination)
-Cold2: XOR A
- LD (DE),A ; Null-terminate for safety
-
- LD HL,#buff ; Pt to count loc'n in buff
- LD (HL),C ; save total arg count
- INC HL ; advance to 1st char
- LD DE,#fcb+1
- CALL FilNm ; Get Name/Typ in 1st FCB
- OR A ; (set End flag)
- LD DE,#fcb+17 ; (prepare)
- CALL NZ,FilNm ; Get Tame/Typ in 2nd FCB if present
-
- LD DE,#dir
- LD B,#128
- CALL ZeroDE ; Clear Directory Buffer
-
- LD HL,#0
- LD (0x0003),HL ; Clear IOBYTE and Default Drive/User
-
- JP __bios ; Go to Cold Start setup
-
-; Fill FCB Name.Typ fields with any present data
-
-FilNm: LD A,(HL) ; Get char
- INC HL ; bump
- OR A ; End of String?
- RET Z
- CP #' ' ; "Whitespace"?
- JR Z,FilNm0 ; ..jump if Yes
- CP #TAB
- JR NZ,FilNm1 ; ..jump if No
-FilNm0: DEC C ; Count down total length
- LD A,C ; (prepare)
- JR NZ,FilNm ; ..loop if Not End
- RET ; ..else Exit showing EOL
-
-FilNm1: LD B,#8 ; Set length of Name field
- PUSH DE ; save Ptr to Name[0]
- CALL FilFl0 ; Get Name
- POP DE ; restore Ptr to Name
- OR A
- RET Z ; ..return if End-of-Line
- CP #' '
- RET Z ; ..return if separator
- CP #'.'
- JR Z,FilNm2 ; ..bypass char skip
-
-FilNm3: LD A,(HL)
- INC HL
- OR A
- RET Z ; Exit if End of Line
- CP #' '
- RET Z ; or End of Field
- CP #'.'
- JR NZ,FilNm3 ; ..loop til End or period
-
-FilNm2: LD A,E
- ADD A,#8 ; Adjust FCB ptr to type field
- LD E,A
- LD B,#3
- ;..fall thru to get next char..
-; Move bytes from (HL) to (DE) for Count in C, Count in B or Ch in {' ','.',0}
-
-FilFld: LD A,(HL) ; Get Char
- INC HL ; bump ptr
- OR A ; End of String?
- RET Z ; ..return if Yes
-FilFl0: CP #'.' ; Period?
- RET Z
- CP #' ' ; Space?
- RET Z
- LD (DE),A ; Else Store byte
- INC DE ; bump dest ptr
- DEC C ; End of Input String?
- LD A,C ; (prepare)
- RET Z ; .return End if Yes
- DJNZ FilFld ; ..loop til field counter ends
- OR #0x0FF ; Return flag
- RET
-
-fcbDat: .db 0
- .ascii ' '
- .db 0,0,0,0
-
-;==========================================================
-; Resident Portion of Basic Disk Operating System
-;==========================================================
-; bdos()
-; {
-__bdos: JP _bdos0
-; }
-
-;.....
-; BDOS Function Dispatch Table
-
-fcnTbl: .dw Fcn0 ; Warm Boot
- .dw Fcn1 ; ConIn
- .dw Fcn2 ; ConOut
- .dw Fcn3 ; Reader In
- .dw Fcn4 ; Punch Out
- .dw Fcn5 ; List Output
- .dw Fcn6 ; Direct Console IO
- .dw Fcn7 ; Get IOBYTE
- .dw Fcn8 ; Set IOBYTE
- .dw Fcn9 ; WrBuf
- .dw Fcn10 ; RdBuf
- .dw Fcn11 ; Get Console Status
- .dw Fcn12 ; Return Version #
- .dw Fcn13 ; Reset Disk Drive
- .dw Fcn14 ; Select Disk
- .dw Fcn15 ; Open File
- .dw Fcn16 ; Close File
- .dw Fcn17 ; Search First Occurance
- .dw Fcn18 ; Search Next Occurance
- .dw Fcn19 ; Delete File
- .dw Fcn20 ; Read File
- .dw Fcn21 ; Write File
- .dw Fcn22 ; Create File
- .dw Fcn23 ; Rename File
- .dw Fcn24 ; Return Disk Login Vector
- .dw Fcn25 ; Return Current Disk
- .dw Fcn26 ; Set DMA
- .dw Fcn27 ; Get Allocation Map
- .dw Fcn28 ; Write Protect Disk
- .dw Fcn29 ; Get R/O Vector Address
- .dw Fcn30 ; Set File Attributes
- .dw Fcn31 ; Get Disk Parameter Table Address
- .dw Fcn32 ; Set/Get User Code
- .dw Fcn33 ; Read Random
- .dw Fcn34 ; Write Random
- .dw Fcn35 ; Compute File Size
- .dw Fcn36 ; Set Random Record Field in FCB
-; .dw Fcn37 ; Reset Multiple Drives
-; .dw null ; (Fcn38 not implemented)
-; .dw Fcn39 ; Get Fixed Disk Vector
-; .dw Fcn40 ; Write Random
-TBLSZ .EQU .-fcnTbl
-MAXFCN .EQU TBLSZ/2
-
-;------------------------------------------------
-; bdos0()
-; {
-
-_bdos0: LD (_arg),DE
- LD A,C
- LD (_call),A
- CP #MAXFCN ; Legal Function?
- LD A,#0xFF ; Prepare Error code
- LD L,A
- RET NC ; ..return if Illegal
- LD (_userSP),SP
- LD SP,#_Bstack
- PUSH IX
- PUSH IY
- LD B,#0 ; Fcn # to Word
- LD HL,#_bdosX
- PUSH HL ; (ret Addr to Stack)
- LD HL,#fcnTbl
- ADD HL,BC
- ADD HL,BC ; Pt to Fcn entry in Table
- LD A,(HL)
- INC HL
- LD H,(HL)
- LD L,A
- JP (HL) ; "Call" Function #
-
-_bdosX: POP IY
- POP IX
- LD SP,(_userSP)
- LD DE,(_arg) ; Return Orig contents of DE
- LD A,(_call)
- LD C,A ; Return Orig contents of C
- LD A,L
- LD B,H ; Strict compatibility
- OR A
- RET
-; }
-
-;------------------------------------------------
-; case 0: _exit(); /* Warm Boot */
-
-Fcn0: JP WBoot
-
-;------------------------------------------------
-; case 6: if (arg < 0xfe) /* Direct Console I/O */
-; goto conout;
-; else if (arg == 0xfe)
-; return (ConSt);
-; else if (ConSt) /* 0xff */
-; goto conout;
-; else return (0);
-
-Fcn6: LD A,E ; _arg in DE
- CP #0x0FE ; < 0FE ?
- JR C,Fcn2 ; ..jump if Write if Yes
- PUSH AF
- CALL BConSt ; Else get Console Status
- POP AF
- INC A
- RET NZ ; ..exit with 0ffh if 0feh
- LD A,H
- OR L ; Any char ready?
- RET Z ; ..exit if Nothing available
- ;..else fall thru to Fcn1..
-;------------------------------------------------
-; case 1: /* Console Input */
-; conin: read (0, &c, 1);
-; if (c == '\n')
-; c = '\r';
-; return (c);
-
-Fcn1: CALL BConIn ; Get Char from Bios
-Fcn1A: LD H,#0
- CP #0x0A ; \n?
- LD L,A ; (prepare for return
- RET NZ ; ..return if Not
- LD L,#0x0D ; Else return CR
- RET
-
-;------------------------------------------------
-; case 3: /* Reader (Aux) Input */
-; conin: read (0, &c, 1);
-; if (c == '\n')
-; c = '\r';
-; return (c);
-
-Fcn3: CALL AuxIn ; Get Char from Bios
- JR Fcn1A ; ..exit via common code
-
-;------------------------------------------------
-; case 2: /* Console Output */
-; conout: if (arg == '\r')
-; return (0);
-; c = arg;
-; write (1, &c, 1);
-; break;
-
-Fcn2: LD C,E ; _arg in DE, need char in C
- JP BConOu
-
-;------------------------------------------------
-; case 4: /* Punch (Aux) Output */
-; conout: if (arg == '\r')
-; return (0);
-; c = arg;
-; write (1, &c, 1);
-; break;
-
-Fcn4: LD C,E ; _arg in DE, need char in C
- JP AuxOut
-
-;------------------------------------------------
-; case 5: if (arg == '\r') /* List (Prntr) Output */
-; return (0);
-; c = arg;
-; write (2, &c, 1);
-; break;
-
-Fcn5: LD A,E ; _arg in DE
- CP #13 ; \r?
- RET Z
- JP List ; ..go to Bios
-
-;------------------------------------------------
-; case 9: ptr = (char *)arg; /* Print '$'-term String */
-; while (*ptr != '$')
-; {
-; if (*ptr != '\r')
-; write (1, ptr, 1);
-; ++ptr;
-; }
-; break;
- ; Enter: DE -> String (arg)
-Fcn9: LD A,(DE) ; Get char
- INC DE ; pt to Next
- CP #'$' ; End?
- RET Z ; ..quit if Yes
- LD C,A
- PUSH DE
- CALL BConOu
- POP DE
- JR Fcn9 ; ..loop Til done
-
-;------------------------------------------------
-; case 10: rdbuf (arg);
-; break;
-; rdbuf (arg)
-; char *arg;
-; {
-; int nread;
-
-; nread = read (0, arg+2, *arg & 0xff);
-
-Fcn10:
- push de
- ex de,hl ; hl - buffer
- ld e,(hl) ; e - max chars
- inc hl
- inc hl
- ld d,#0 ; d - char cnt
-get: push hl
- push de
- call BConIn
- pop de
- pop hl
- cp #8
- jr z,del
- cp #0x7F
- jr z,del
- cp #3
- jp z,0
- push hl
- push de
- push af
- ld c,a
- call BConOu
- pop af
- pop de
- pop hl
- ld (hl),a
- cp #CR
- jr z,eol
- ld a,e
- cp d
- jr z,eol1
- inc hl
- inc d
- jr get
-del: ld a,d
- or a
- jr z,get
- push hl
- push de
- ld c,#8
- call BConOu
- ld c,#' '
- call BConOu
- ld c,#8
- call BConOu
- pop de
- pop hl
- dec hl
- dec d
- jr get
-eol: ld (hl),#0
-eol1: ld a,d
- pop de
- inc de
- ld (de),a
- ld hl,#0
- ret
-
-
-;------------------------------------------------
-; case 11: return (ConSt); /* Get Console Status */
-
-Fcn11: JP BConSt
-
-;------------------------------------------------
-; case 12: /* Return Version # */
-
-Fcn12: LD HL,#0x0022 ; Say this is CP/M 2.2
- RET
-
-;------------------------------------------------
-; case 13: /* Reset Disk Drive */
-; SDma(0x80);
-; break;
-Fcn13:
- LD BC,#0x80
- JP BSDma
-
-;------------------------------------------------
-; case 7: /* Get IO Byte */
-; case 8: break; /* Set IO Byte */
-; case 14: break; /* Select Disk
-; case 25: break; /* Return Current Disk */
-; case 28: break; /* Write Protect Disk */
-; case 30: break; /* Set File Attribytes */
-; case 32: break; /* Get/Set User Code */
-Fcn7:
-Fcn8:
-Fcn14:
-Fcn25: ; 0 = Drive A
-Fcn28:
-Fcn30:
-Fcn32: ; Return User 0
-; default: break;
-; }
-; return (0);
-
-Exit0: LD HL,#0
- RET
-
-;------------------------------------------------
-; case 15: return (openfile (arg)); /* Open File */
-; openfile (blk)
-; {
-; desc = open (getname (arg), 2);
- ; DE -> arg
-Fcn15: CALL Fcn17 ; Does this file exist?
- LD A,H
- AND L
- INC A ; File Not Found (-1)?
- RET Z ; ..return -1 if File doesn't exist
-
-Open1: CALL CkSrch ; (Close Search File)
-
-; arg.recno = 0;
-
- CALL ZeroCR
- LD 13(IY),#0x80 ; use S1 as file open flag
-
- JR Exit0 ; Return Dir Code for Entry
-
-;.....
-; Common File Open Routine. Used by Read, Write and Search First.
-; Enter: DE = File Mode
-; HL = Ptr to Null-terminated Path String
-; Exit : A = 0 if Error, HL = -1
-; File Descriptor, A <> 0 if Ok
-
-OpenF: PUSH DE ; Mode
- PUSH HL ; Path
- LD HL,#1 ; Fuzix Open Fcn #
- PUSH HL
- RST 0x30 ; _open (Path, Mode);
- POP BC ; Clean Stack
- POP BC
- POP BC
- LD A,H
- AND L
- INC A ; FF -> 0?
- RET ; ..return (HL=-1/A=0 if Err, HL=fd/A<>0 of Ok)
-
-;------------------------------------------------
-; case 16: return (closefile (arg)); /* Close File */
-
-; if (close (arg->desc) == -1)
-
-Fcn16: LD IY,(_arg)
- LD 13(IY),#0 ; clear file open flag
-
- LD HL,#11 ; Fuzix sync function #
- PUSH HL
- RST 0x30 ; Execute!
- POP BC ; Clean Stack
-
- JP Exit0 ; Return OK
-
-;....
-; Close file descriptor
-
-CloseV: PUSH DE
- LD HL,#2 ; Fuzix Close Fcn #
- PUSH HL
- RST 0x30 ; Execute!
- POP BC ; Clean Stack
- POP BC
- RET
-
-;------------------------------------------------
-; case 17: /* Search First */
-
-Fcn17: CALL CkSrch ; Ensure Search File closed
- LD HL,#'.' ; Open current directory
- LD (RName),HL ; store name in Secondary work string
- LD DE,#0 ; Open Read-Only
- LD HL,#RName
- CALL OpenF ; _open ('.', 0);
- RET Z ; HL = -1, A = 0 if Can't Open
-
- LD (srchFD),HL ; Else Ok, Save File Descriptor
- LD (curFil),HL ; Duplicate for Reading
- ;..fall thru to read one entry..
-;------------------------------------------------
-; case 18: return (255); /* Search Next */
-
-;
-; FIXME: dir entries need to be bigger ?
-;
-Fcn18: LD HL,(dmaadr)
- LD (dmaSav),HL ; Save "real" DMA
-Fcn18A: LD HL,#dir+16
- LD (dmaadr),HL ; Set DMA for Dir Op'n
- LD A,#16 ; Getdirent
- LD DE,#32 ; Len of Dir entries
- CALL RdWrt0 ; Read an Entry
- JR C,#Fcn18E ; Error if Carry Set
- OR A ; Read Ok?
- JR Z,Fcn18E ; ..Return HL=-1 if EOF
- CALL ChkDir ; Else Set Dir to CP/M, Check Match
- OR A
- JR NZ,Fcn18A ; ..loop if No Match
-
- LD A,(_call)
- CP #15 ; Is this a File Open internal Call?
- LD HL,#0 ; (set Success, Index 0)
- JR Z,Fcn18X ; ..exit now if Yes
-
- LD HL,#dir ; Else
- LD DE,(dmaSav) ; Move Dir Buffer to "real" DMA
- LD BC,#128
- LDIR
- LD L,B ; Use 0 in BC
- LD H,C ; to show Index 0 (success)
- JR Fcn18X ; ..exit
-
-Fcn18E: LD HL,#-1
-Fcn18X: LD DE,(dmaSav)
- LD (dmaadr),DE ; Restore "real" DMA Addr
- RET
-
-;------------------------------------------------
-; case 19: return (delete (arg)); /* Delete File */
-
-Fcn19: CALL CkSrch ; Ensure Search file closed
-
-; if (unlink (getname (arg)) == -1)
- ; DE -> arg
- CALL GetNam ; Parse to String
- PUSH HL ; String
- LD HL,#6 ; UZI Unlink Fcn #
- PUSH HL
- RST 0x30 ; Execute!
- POP BC ; Clean Stack
- POP BC
-
-; return (255);
-; return (0);
-
- LD A,H
- AND L
- INC A ; FF->0?
- JP NZ,Exit0 ; return Ok if No
-
-ExitM1: LD HL,#-1
- RET
-
-
-;------------------------------------------------
-; case 33: /* Read File Random */
-; readrandom (fcb)
-; {
-
-Fcn33: CALL RWprep ; Prepare File for access
- JP Z,Exit1
-
- LD IY,(_arg)
- LD A,33(IY) ; Set Record Count from
- LD 32(IY),A ; Random Record number
- LD A,34(IY) ;
- LD 12(IY),A ;
-
- CALL DoRead
- JR RWEx
-
-;....
-DoRead:
- CALL LSeek ; Seek to Offset (128-byte rec in Block)
-
- CALL BRead ; Read 1 Sector
-
- PUSH AF
- LD DE,(curFil)
-;;;; CALL CloseV ; Close the file
- LD DE,#0
- LD (curFil),DE
- POP AF
-
- RET
-
-
-;------------------------------------------------
-; case 20: return (readfile (arg)); /* Read File */
-; readfile (arg)
-; {
-; nread = read (blk->desc, dmaadr, 128);
- ; DE -> arg (FCB)
-Fcn20: CALL RWprep ; Prepare file for access
- JP Z,Exit1
-
- CALL DoRead ; Read 1 Sector
-
-; arg.recno++;
-
- PUSH AF
- CALL IncCR ; Bump Current Record #
- POP AF
-
-RWEx: JP C,Exit1 ; ..Error if Carry Set
-
-; if (nread == 0)
-; return (0);
-
- OR A ; Good Read?
- JP Z,Exit0 ; exit w/0 if Yes
-
-; else return (1)
-
- JP Exit1
-
-;------------------------------------------------
-; case 34: /* Write File Random */
-; writerandom (fcb)
-; {
-; /* CAUTION the seek calls MUST be in this order */
-; _seek (f, (int)(fcb+33) % 128, 0); /* byte seek */
-; _seek (f, (int)(fcb+33) / 128, 3); /* block seek */
-
-Fcn34: CALL RWprep ; Prepare file for access
- JP Z,Exit1
-
- LD IY,(_arg)
- LD A,33(IY) ; Set Record Count from
- LD 32(IY),A ; Random Record number
- LD A,34(IY) ;
- LD 12(IY),A ;
-
- CALL DoWrite
- JR RWEx
-
-;....
-DoWrite:
- CALL LSeek ; Seek to Offset (128-byte rec in Block)
-
- CALL BWrit ; Write 1 Sector
-
- PUSH AF
- LD DE,(curFil)
-;;;; CALL CloseV ; Close the file
- LD DE,#0
- LD (curFil),DE
- POP AF
-
- RET
-
-;------------------------------------------------
-; case 21: return (writefile (arg)); /* Write File */
-; writefile (arg)
-; {
-; if (write (blk->desc, dmaadr, 128) != 128)
-
- ; DE -> arg (FCB)
-Fcn21: CALL RWprep ; Prepare file for access
- JP Z,Exit1
-
-Fcn21A: CALL DoWrite ; Write
-
-; arg.recno++;
-
- PUSH AF
- CALL IncCR ; Bump Current Record #
- POP AF
-
-; return (255);
-; return (0);
-
- JR RWEx ; ..exit via Common R/W Code
-; }
-
-;------------------------------------------------
-; case 22: return (makefile (arg)); /* Create File */
-; makefile (arg)
-; {
-; desc = creat (getname (blk), 0666);
-
-Fcn22: CALL CkSrch ; Ensure Search file closed
- LD HL,#0q0666 ; Own/Grp/Oth are Read/Execute
- PUSH HL ; DE -> arg
- LD HL,#0x502 ; O_CREAT|O_RDWR|O_TRUNC
- CALL GetNam ; This name string
- PUSH HL
- LD HL,#1 ; Fuzix open Fcn #
- PUSH HL
- RST 0x30 ; Execute!
- POP BC ; Clean Stack
- POP BC
- POP BC
- POP BC
-
-; if (desc == -1)
-
- LD A,H
- AND L
- INC A ; FF -> 0?
-
-; return (255);
-
- RET Z ; ..return -1 if Yes
-
-; arg.recno = 0;
-
- EX DE,HL
- CALL CloseV
- JP Open1
-
-;------------------------------------------------
-; case 23: return (rename (arg)); /* Rename File */
-; rename (arg)
-; {
-; RName = getname (arg);
-;
-; FIXME: should use rename() syscall now
-;
-Fcn23: CALL CkSrch ; Ensure Search file closed
- PUSH DE ; Save FCB Ptr
- CALL GetNam ; parse to UZI String
-
- LD HL,#FName
- LD DE,#RName
- LD BC,#12
- LDIR ; Copy to Rename string
-
-; FName = getname (arg+16);
-
- POP DE ; DE -> _arg
- LD HL,#16
- ADD HL,DE ; Offset to New Name
- EX DE,HL
- CALL GetNam ; parse it returning HL -> FName
-
-; if (link (RName, FName) < 0) {
-
- PUSH HL ; New Name
- LD HL,#RName ; Old Name
- PUSH HL
- LD HL,#5 ; UZI link Fcn #
- PUSH HL
- RST 0x30 ; Execute!
- POP BC ; Clean Stack
- POP BC
- POP BC
-
-; return (-1);
-
- JP C,ExitM1 ; Exit w/Err if Bad
-; }
-; if (unlink (RName) < 0) {
-
- LD HL,#RName ; Old Name
- PUSH HL
- LD HL,#6 ; UZI unlink Fcn #
- PUSH HL
- RST 0x30 ; Execute!
- POP BC ; Clean Stack
- POP BC
- JP NC,Exit0 ; exit w/0 if Ok
-
-; unlink (FName);
- ; Else remove the new iNode
- LD HL,#FName ; New Name
- PUSH HL
- LD HL,#6 ; UZI unlink Fcn #
- PUSH HL
- RST 0x30 ; Execute!
- POP BC ; Clean Stack
- POP BC
-
-; return (-1);
-
- JP C,ExitM1 ; return -1 if Bad
-; }
-; return (0);
-
- JP Exit0 ; else return Ok
-; }
-
-;------------------------------------------------
-; case 24: return (1); /* Return Disk Login Vector */
-
-Fcn24:
-Exit1: LD HL,#1
- RET
-
-;------------------------------------------------
-; case 26: dmaadr = (char *)arg; /* Set DMA Address */
-; break;
- ; Enter DE = DMA Address
-Fcn26: LD C,E
- LD B,D ; Move to Bios Regs
- JP BSDma ; Set in Bios & return
-
-;------------------------------------------------
-; case 27: return (-1) /* Get Allocation Map */
-; case 29: return (-1) /* Get R/O Vector Address */
-Fcn27:
-Fcn29: LD HL,#-1
- RET
-
-;------------------------------------------------
-; case 31: return (&dpb); /* Get Disk Param Table Addr */
-
-Fcn31: LD HL,#dpb
- RET
-; }
-
-;------------------------------------------------
-; case 35: /* Return File Size in FCB */
-; /* Use stat fcn, rounding up to mod-128 */
-; if (_stat (dname, &statbuf) == 0) {
- ; DE -> fcb
-Fcn35: CALL CkSrch ; Ensure Search file closed
- CALL GetNam ; parse to UZI String
- LD DE,#stBuf
- PUSH DE ; &statbuf
- PUSH HL ; dname
- LD HL,#15 ; UZI stat Fcn #
- PUSH HL
- RST 0x30 ; Execute!
- POP BC ; Clean Stk
- POP BC
- POP BC
- LD IY,(_arg)
- LD A,H
- OR L ; 0?
- JR NZ,Fcn35X ; ..jump if Bad
-
-; (int)fcb+33 = ((512 * statbuf.st_size.o_blkno
-; + statbuf.st_size.o_offset)
-; + 127)
-; >> 7;
-; FIXME: offset is now a simple number so this is wrong
-;
- LD HL,(stBuf+14) ; Get Offset
- LD DE,#127
- ADD HL,DE ; round up to next 128-byte block
- ADD HL,HL ; Shift so H has 128-byte blk #
- LD E,H ; position in DE
- LD HL,(stBuf+16) ; Get Block
- ADD HL,HL ; * 2
- ADD HL,HL ; * 4 for 128-byte Block Count
- ADD HL,DE ; Now have CP/M Record Size
- LD 33(IY),L
- LD 34(IY),H ; Store in RR fields in FCB
- LD 35(IY),D ; (D = 0)
-
-; return (0);
-
- LD L,D
- LD H,D ; HL = 0
- RET
-
-; else {
-; (int)fcb+33 = 0;
-
-Fcn35X: LD 33(IY),#0
- LD 34(IY),#0
- LD 35(IY),#0
-
-; return (-1);
-
- LD HL,#-1
-; }
- RET
-
-;------------------------------------------------
-; case 36: /* Set Random Record Field in FCB */
-
-Fcn36: LD IY,(_arg)
- LD A,32(IY) ; Fetch RecNo
- LD 33(IY),A ; place in LSB of RR field (r0)
- LD A,12(IY)
- LD 34(IY),A ; set (r1)
- LD 35(IY),#0 ; Clear Hi byte of RR (r2)
-
- LD HL,#0 ; Return Ok
- RET
-
-;===========================================================
-; BDos Support Routines
-;===========================================================
-; char *
-; getname (struct fcb *blk)
-; {
-; int j;
-; static char name[16];
-; char *p;
-
-; p = name;
- ; Enter: DE -> FCB drive byte
-GetNam: LD IX,#FName ; Dest to string
- EX DE,HL
- PUSH HL ; (save)
- INC HL ; adv to 1st char of FN
-
-; for (j = 0; j < 8; ++j)
-; {
-; if (!blk->name[j] || blk->name[j] == ' ')
-; break;
-
- LD B,#8
-GetN0: LD A,(HL)
- INC HL
- OR A
- JR Z,GetN1
- CP #' '
- JR Z,GetN1
-
-; *p++ = chlower (blk->name[j]);
-
- CALL ChLower
- LD 0(IX),A
- INC IX
- DJNZ GetN0
-; }
-
-GetN1: POP HL
- LD DE,#9
- ADD HL,DE ; Pt to 1st char of FT
- LD A,(HL)
- CP #' ' ; Any Type?
- JR Z,GetNX ; ..quit if Not
-
-; *p++ = '.';
-
- LD 0(IX),#'.'
- INC IX
-
-; for (j = 0; j < 3; ++j)
-
- LD B,#3
-
-; {
-; if (!blk->ext[j] || blk->ext[j] == ' ')
-; break;
-
-GetN2: LD A,(HL)
- INC HL
- CP #' '
- JR Z,GetNX
-
-; *p++ = chlower (blk->ext[j]);
-
- CALL ChLower
- LD 0(IX),A
- INC IX
- DJNZ GetN2
-
-; }
-; *p = '\0';
-
-GetNX: LD 0(IX),#0
-
-; return (name);
-
- LD HL,#FName
- RET
-; }
-
-;
-; FIXME: we need to use lseek for Fuzix
-;
-LSeek: LD BC,#0 ; Push 0 for absolute
- PUSH BC
- LD IY, (_arg) ; FCB
- LD C, 32(IY) ; Pull the offset out of the FCB
- LD B, 12(IY) ; This is in records (128 bytes)
- ; And may overflow 2^16 bytes
- XOR A
- SLA C ; C x 2, into carry
- RL B ; B x 2 picking up carry from C
- RLA ; A x 2 picking up carry from B - now in 64's
- SLA C
- RL B
- RLA ; now in 32's
- SLA C
- RL B
- RLA ; now in 16's
- SLA C
- RL B
- RLA ; now in 8's
- SLA C
- RL B
- RLA ; now in 4's
- SLA C
- RL B
- RLA ; now in 2's
- SLA C
- RL B
- RLA ; now in bytes
- LD (LSeekData), BC ; low bits
- LD (LSeekData + 2), A ; high bit (top byte already clear)
- LD BC, #LSeekData ; push pointer
- PUSH BC
- LD HL, (curFil)
- PUSH HL
- LD HL,#9 ; _lseek()
- PUSH HL
- RST 0x30 ; Syscall
- POP BC ; Recover stack
- POP BC
- POP BC
- POP BC
- RET
-
-;.....
-; Perform File Access Preparatory actions:
-; Open file for R/W and Seek to current Record #
-; Enter: DE = Ptr to FCB
-; Exit : A = 0 and HL = -1 if Error, A <> 0 if Ok
-
-RWprep: CALL CkSrch ; Ensure Search file closed
- LD HL,#13 ; offset to S1 (file open flag)
- ADD HL,DE
- LD A,(HL)
- AND #0x80
- LD HL,#-1
- RET Z
-
- CALL GetNam ; Parse FCB Fn.Ft to String
-
- CALL COpen
- RET Z ; ..return -1 on error
-
- LD (curFil),HL ; store file descriptor for Bios
- RET
-
-COpen: PUSH HL
- LD DE,#CName
-chk: LD A,(DE)
- CP (HL) ; compare filename with cached name
- JR NZ,differ
- OR A
- JR Z,same
- INC HL
- INC DE
- JR chk
-same: POP DE ; if same, just return the cached file descr
- LD HL,(Cfd)
- LD A,H
- AND L
- INC A
- RET NZ
- EX DE,HL
- JR op1
-differ: LD HL,(Cfd)
- LD A,H
- AND L
- INC A
- EX DE,HL
- CALL NZ,CloseV ; close old file
- POP HL ; restore file name
- CALL Ccopy
-op1: LD DE,#2 ; open for R/W
- CALL OpenF
- LD (Cfd),HL
- RET
-
-Ccopy: PUSH HL
- LD DE,#CName
-cpy: LD A,(HL)
- LD (DE),A
- INC HL
- INC DE
- OR A
- JR NZ,cpy
- POP HL
- RET
-
-;.....
-; Convert UZI Directory Entry at dir+16 to CP/M FCB entry at dir, Zero rest.
-; Ambiguously compare FCB FN.FT at dir to that passed at arg, returning Zero
-; if Match, Non-Zero if mismatch.
-
-ChkDir: LD DE,#dir
- LD HL,#dir+16+2 ; Pt to 1st char of Name
- XOR A
- LD (DE),A ; Zero Drive field
- INC DE ; Pt to 1st char of FN
- LD B,#8
- CALL ChkD0 ; Fix Name
- LD B,#3
- CALL ChkD0 ; & Type
- LD B,#21
- CALL ZeroDE ; Clear rest of Dir entry
-
- LD DE,(_arg)
- INC DE ; Pt to 1st char of FN
- LD A,(DE)
- CP #' ' ; Any Name present?
- JR NZ,ChkFN0 ; ..jump if Yes
- LD HL,#8
- ADD HL,DE ; Else offset to 1st char of FT
- LD A,(HL)
- CP #' ' ; Type present?
- LD A,#0x0FF ; (Assume Error)
- RET Z ; Return w/Err Flag if no Type either
-
-ChkFN0: LD HL,#dir+1 ; Else Compare name/type fields
- LD B,#11
- ; Ambiguous FN.FT compare of (HL) to (DE)
-ChkL: LD A,(DE)
- CP #'?' ; Accept anything?
- JR Z,ChkL0 ; ..jump if ambiguous
- XOR (HL)
- AND #0x7F ; Match?
- RET NZ ; .Return Non-Zero if Not
-ChkL0: INC HL
- INC DE
- DJNZ ChkL ; ..loop til Done
- XOR A ; return Zero for Match
- RET
-
-;.....
-; Parse FileSpec addressed by HL into FN.FT Spec addressed by DE.
-
-ChkD0: LD A,(HL) ; Get Char
- CP #'a'
- JR C,ChkD1
- CP #'z'+1
- JR NC,ChkD1
- AND #0x5F ; Convert to Uppercase
-ChkD1: OR A ; End of String?
- JR Z,ChkDE ; ..jump if End
- INC HL ; (bump Inp Ptr if Not End)
- CP #'.'
- JR Z,ChkDE ; ..or Period field separator
- LD (DE),A ; Store char
- INC DE ; bump Dest
- DJNZ ChkD0 ; ..loop til field done
-ChkD2: LD A,(HL) ; Get Next
- OR A
- RET Z ; Exit at End of string
- INC HL ; (adv to next)
- CP #'.'
- RET Z ; or field separator
- JR ChkD2 ; ..loop til end found
-
-ChkDE: LD A,#' ' ; Fill rest w/Spaces
-ChkD3: INC B
- DEC B ; More in field?
- RET Z ; ..exit if Not
- JR ZeroL ; ..else stuff spaces til field ends
-
-;.....
-; Zero area addressed by DE for B Bytes. Uses A,B,DE.
-
-ZeroDE: XOR A
-ZeroL: LD (DE),A
- INC DE
- DJNZ ZeroL
- RET
-
-;.....
-; Close the Directory if we just exitted a SearchF/SearchN sequence
-
-CkSrch: PUSH DE ; Save Regs
- PUSH HL
- LD DE,(srchFD) ; Get File Desc
- LD A,D
- OR E ; Anything open?
- CALL NZ,CloseV ; Close file if Yes
- LD HL,#0
- LD (srchFD),HL ; Mark as closed
- POP HL ; (ignore Errors)
- POP DE
- RET
-
-;.....
-; Bump current Record # for sequential R/W operations
-
-IncCR: LD IY,(_arg)
- INC 32(IY) ; Bump Lo byte
- RET NZ
- INC 12(IY) ; Bump Hi byte
- RET
-
-;.....
-; Init Current Record #
-
-ZeroCR: LD IY,(_arg)
- LD 32(IY),#0 ; Clear Lo Byte
- LD 12(IY),#0 ; Clear Hi Byte
- RET
-
-;.....
-; Convert char in A to Lowercase Ascii
-
-ChLower:
- CP #'A'
- RET C
- CP #'Z'+1
- RET NC
- OR #0x20 ; Convert to Lcase
- RET
-
-;= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
-; Bdos data in Text Segment for treating as single module
-
-; struct fcb {
-; char drive;
-; char name[8];
-; char ext[3];
-; char junk1[4];
-; char desc; /* This byte & 1st byte of Name used for file desc */
-; char name2[8];
-; char ext2[3];
-; char junk2[4];
-; char junk3;
-; };
-
-_arg: .dw 00 ; Argument passed to Bdos (char *arg;)
-_call: .db 0 ; Bdos Function # (char call;)
-FName: .ascii ' ' ; Storage for FCB "name" String
-RName: .ascii ' ' ; 2nd Storage for FCB "name" String (rename)
-
-CName: .ascii ' ' ; cached filename
- .db 0
-Cfd: .dw -1 ; cached file descriptor
-
-curFil: .dw 00 ; Storage for File Descriptor of FCB
- ; (set by Bdos, Used by Bios)
-stBuf: .ds 30 ; Buffer for stat() results
-
-DOSSIZ .EQU .-EStart
-RESV .EQU 0x100-(DOSSIZ&0x0FF)
- .ds RESV ; Pad to make Bios start on even mult of 256
-
-;============================================================
-; The Bios Jump table MUST start on an even MOD 256 boundary
-;============================================================
-
-__bios: JP __cold ; 0 Cold Boot
-WBoot: JP Exit ; 1 Warm Boot
-BConSt: JP ConSt ; 2 Console Status
-BConIn: JP ConIn ; 3 Console Input
-BConOu: JP ConOut ; 4 Console Output
- JP List ; 5 Printer Output
- JP AuxOut ; 6 Auxiliary Output (Punch)
- JP AuxIn ; 7 Auxiliary Input (Reader)
- JP Home ; 8 Home drive head
- JP SelDsk ; 9 Select Drive
- JP SetTrk ; 10 Set Track
- JP SetSec ; 11 Set Sector
-BSDma: JP SetDMA ; 12 Set DMA Address
-BRead: JP Read ; 13 Read Sector
-BWrit: JP Write ; 14 Write Sector
- JP ListSt ; 15 Printer Status
- JP SecTrn ; 16 Translate Sector
-
-;------------------------------------------------
-; Cold Entry. Set up CP/M vectors and Stack, Get
-; Current TTY Parms, Save for Exit, and begin
-
-__cold: LD A,#0x0C3
- LD HL,#__bdos
- LD SP,HL ; Set CP/M Stack for execution
- LD (0x0005),A ; Set Bdos Vector
- LD (0x0006),HL
- LD HL,#WBoot
- LD (0x0000),A ; Set Bios Warm Boot Vector
- LD (0x0001),HL
-
- LD HL,#ttTermios0 ; & buf
- LD DE,#TCGETS ; ioctl fcn to Get Parms
- CALL IoCtl ; Execute ioctl fcn on STDIN
- LD HL,#ttTermios0
- LD DE,#ttTermios
- LD BC, #20
- LDIR ; Move to Work Area
- ; Now we need to Change Modes defined in DEVTTY as:
- ; RAW = 20H (0000040)
- ; CRMOD = 10H (0000020)
- ; ECHO = 08H (0000010)
- ; CBREAK = 02H (0000002)
- ; COOKED = 00H (0000000)
- LD HL, #0
- ; Turn all the input and output magic off
- LD (ttTermios), HL
- LD (ttTermios + 2), HL
- XOR A
- LD (ttTermios+6), A ; Echo etch off
- LD A, (ttTermios+7)
- AND #0xF0 ; canonical processing off
- LD (ttTermios+7), A
- LD HL, #1 ; VTIME 0
- LD (ttTermios+8), HL ; VMIN 1
- LD HL, #ttTermios
- LD DE, #TCSETS
- CALL IoCtl ; Set terminal bits
-
- CALL 0x0100 ; ..Execute!
-
-;.....
-; 1 - Warm Boot Vector (Exits back to UZI) {exit (0);}
-; TTY Port Settings are restored to original state.
-
-Exit: LD C,#0x0D
- CALL ConOut
- LD C,#0x0A
- CALL ConOut
- LD HL,#ttTermios0 ; & buf
- LD DE,#TCSETS ; ioctl fcn to Set Parms
- CALL IoCtl ; Execute ioctl Fcn on STDIN
-
- LD HL,#0 ; Exit Good Status
- PUSH HL
- PUSH HL ; UZI Fcn 0 (_exit)
- RST 0x30 ; Execute!
- DI
- HALT
-
-;.....
-; 2 - Return Console Input Status
-
-ConSt: LD HL,#cnt ; &buf
- LD DE,#TIOCINQ ; ioctl fcn to read queue count
- CALL IoCtl ; Execute ioctl on STDIN
- LD HL,(cnt)
- LD A,H
- OR L ; Anything There?
- RET Z ; ..return Zero if Not
- OR #0x0FF ; Else signify char waiting
- RET
-
-;.....
-; 3 - Read Console Input Char {read (stdin, &char, 1);}
-
-ConIn: call ConSt
- jr z,ConIn
- LD HL,#1 ; 1 char
- PUSH HL
- LD DE,#char ; Addr to put char
- PUSH DE
- LD L,#STDIN ; fd
- PUSH HL
- LD L,#7 ; UZI Read Fcn
-ChrV0: PUSH HL
- RST 0x30 ; Execute
- POP BC
- POP BC
- POP BC
- POP BC
- LD A,(char)
- RET
-
-;.....
-; 4 - Write Char in C to Console {write (stdout, &char, 1);}
-
-ConOut: LD A,C
- LD DE,#char
- LD (DE),A ; Stash char
- LD HL,#1 ; 1 char
- PUSH HL
- PUSH DE ; Addr to get char
- LD L,#STDOUT ; fd
- PUSH HL
- LD L,#8 ; UZI Write Fcn
- JR ChrV0 ; ..go to common code
-
-;.....
-
-List: ; Bios Fcn 5
-AuxOut: ; Bios Fcn 6
-AuxIn: ; Bios Fcn 7
-Home: ; Bios Fcn 8
-SetTrk: ; Bios Fcn 10
-SetSec: ; Bios Fcn 11
-ListSt: ; Bios Fcn 15
-SecTrn: XOR A ; Bios Fcn 16. These are No-Ops
- RET
-
-;.....
-; 9 - Select Disk. Simply return the DPH pointer
-
-SelDsk: LD HL,#dph ; Return DPH Pointer
- RET
-
-;.....
-; 12 - Set DMA Transfer Address
-
-SetDMA: LD (dmaadr),BC ; Save Address
- Ret
-
-;.....
-; 13 - Read a "Sector" to DMA Address {read (curFil, dmaadr, 128);}
-
-Read: LD A,#7 ; Set UZI Read Fcn
- CALL RdWrt ; Do the work
- RET C ; ..exit if Error
- OR A ; 0 bytes Read?
- JR Z,XErr1 ; ..Return Error if Yes (EOF)
- SUB #128 ; A full 128 bytes Read?
- RET Z ; return Ok if Yes
- LD DE,(dmaadr)
- ADD HL,DE ; Else offset to byte after end
-Feof: LD (HL),#0x1A ; stuff EOF in case of text
- INC HL
- INC A
- JR NZ,Feof
- RET ; exit with OK status
-
-;.....
-; 14 - Write a "Sector" from DMA Address {write (curFil, dmaadr, 128);}
-
-Write: LD A,#8 ; Set UZI Write Fcn
- CALL RdWrt ; Do the work
- RET C ; ..exit if Error
- SUB #128 ; Good Write?
- RET Z ; return Ok if Yes
-XErr1: SCF
- JR XErr ; Else Return Error
-
-; Common Read/Write Support Routine
-
-RdWrt: LD DE,#128 ; 1 "Sector" char
- ; Entry Point accessed by Search Next (BDos)
-RdWrt0: PUSH DE
- LD HL,(dmaadr) ; from here
- PUSH HL
- LD HL,(curFil) ; to this file
- PUSH HL
- LD E,A ; Position R/W Fcn #
- PUSH DE
- RST 0x30 ; Execute!
- POP BC ; Clear Stack
- POP BC
- POP BC
- POP BC
- LD A,L ; Shuffle possible byte quantity
- RET NC ; ..return if No Error
-XErr: LD A,#0x01 ; Else Signal Error (keeping Carry)
- RET
-
-;==========================================================
-; Bios Support Utilities
-;==========================================================
-; Execute ioctl Function on STDIN
-; Enter: HL = Addr of Parm Block
-; DE = ioctl Function to execute
-; Exit : None
-; Uses : AF,BC,DE,HL
-
-IoCtl: PUSH HL ; &buf
- PUSH DE ; ioctl fcn
- LD E,#STDIN ; fd
- PUSH DE
- LD E,#29 ; Fuzix ioctl Fcn #
- PUSH DE
- RST 0x30 ; Execute!
- POP BC ; Clean Stack
- POP BC
- POP BC
- POP BC
- RET
-
-;- - - - - - - - - - Data Structures - - - - - - - - -
-
-dph: .dw 0 ; Ptr to Skew Table
- .dw 0,0,0 ; Scratch Words for BDos use
- .dw dir ; Ptr to Directory Buffer
- .dw dpb ; Ptr to DPB
- .dw 0 ; Ptr to Disk Checksum Buffer
- .dw 0 ; Ptr to ALV Buffer
-
-
-dpb: .dw 64 ; Dummy Disk Parameter Block
- .db 4
- .db 15
- .dw 0x0FFFF
- .dw 1023
- .db 0x0FF,0
- .db 0,0,0,0
-
-;----------------------- Data -----------------------
-
-dmaadr: .dw 0x0080 ; Read/Write Transfer Addr (char *dmaadr;)
-dmaSav: .dw 0 ; Temp storage of current DMA Address
-srchFD: .dw 0 ; File Descriptor for Searches
-char: .db ' ' ; Byte storage for Conin/Conout
-cnt: .dw 0 ; Count of waiting keys
-LSeekData: .dw 0 ; Used for _lseek() syscalls
- .dw 0
-ttTermios:
- .ds 20 ; Working TTY Port Settings
-ttTermios0:
- .ds 20 ; Initial TTY Port Settings
-
-dir: .ds 128 ; Directory Buffer
-
- .ds 128
-_Bstack:
-_userSP:.dw 0 ; WRS: important that we write data all the way to the very last byte used
-
-BIOSIZ .EQU .-__bios
-CPMSIZ .EQU .-__bdos
-
-; .end
-