From: Jon Langseth Date: Wed, 8 Feb 2017 19:27:48 +0000 (+0100) Subject: An experiment in reading files on CP/M X-Git-Url: https://git.defcon.no/?a=commitdiff_plain;h=HEAD;p=z80cpm An experiment in reading files on CP/M --- diff --git a/rf1.asm b/rf1.asm new file mode 100644 index 0000000..f30699d --- /dev/null +++ b/rf1.asm @@ -0,0 +1,129 @@ +; rf1.asm - Read File experiment #1 +; ASM dialect is for crasm/z80, producing Intel HEX. +; +; Attempting to understand file read operations on CP/M2 +; Reference material: +; http://www.cpm.z80.de/manuals/archive/cpm22htm/ch5.htm +; The default FCB can be used, it's location is at 05CH +; The default DMA buffer can be used, it's located at 080H +; When CCP jumps to 0100H, it's already taken the two +; first parameters to the command, and placed them in +; the default FCB area. More on this later in the code +; CCP has also placed the parameter string in the default +; DMA buffer area (080H). Not used in this experiment. + +; crasm macros.. Z80 CPU type, iHEX output, readable listing pages, listing-toggles.. +CPU Z80 +OUTPUT HEX +PAGE 24,120 +LIST ON +CLIST ON +ILIST ON +MLIST ON + +; BDOS call constants.. +conout EQU 2 ; Console output, put 1 char from E to Console +strout EQU 9 ; String output, place string at (DE) terminated by $ to Console +openf EQU 15 ; Open file, using the FCB at address (DE) +reads EQU 20 ; Read sequential, get next DMABUF from file at FCB in (DE) +closef EQU 16 ; Close file, using hte FCB at (DE) +bdos EQU 5 ; Call jump-address for all BDOS calls. + +; Standard location constants.. +sfcb EQU 0x5c ; The Standard/default FCB +fcbcr EQU sfcb+32 ; The CR field of the FCB +sdma EQU 0x80 ; The Standard/default DMA Buffer + +; Other fun constants... +eof EQU 0x1a ; CP/M EOF character, 0x1Ah/26d + +; Origin at TPA Start, 0x100 +* = 0x100 + + ; Start by printing out the filename currently in the default FCB. + ; CCP will take 'command file.sfx file1.sfx" and fill the default + ; FCB appropriately for file.sfx, plus the needed content for a + ; second FCB started at 0x6c (default fcb + 10h) + ; The Drive index is the first byte, and the filename is 8+3 bytes + LD HL, sfcb + 1 ; Load HL with address of Standard FCB + 1 + LD D, 8+3 ; Prepare a counter for 8+3 characters for a full filename +START LD E, (HL) ; Load content of address in HL into E + LD C, conout ; Prepare a Console Character Out BDOS call + PUSH HL ; BDOS call clobbers HL, push to stack + CALL bdos ; Go to BDOS for conout call + POP HL ; Restore HL after BDOS call + INC HL ; Next byte + DEC D ; .. until all needed characters.. + JR NZ, START + + ; --- START OF FILE OPEN + ; To open file for sequential access, the 'cr' field of the FCB needs + ; to be zeroed + LD HL, fcbcr ; Set the HL register pair to the CR field address + LD (HL), 0 ; Set to zero + + LD DE, sfcb ; Prepare DE with address of FCB + LD C, openf ; Set up for Open File BDOS call + CALL bdos ; GO! + + CP 255 ; Compare A register to check for error + JR Z, ERROPF ; If Zero set, A == 255, and we have an error + ; --- END OF FILE OPEN + + LD DE, okmsg ; Compare did not set Zero flag, so we can + LD C, strout ; use String Output to say that the file is opened + CALL bdos + + ; --- ACTUAL DATA REA +RREC LD DE, sfcb ; Load DE with address of FCB + LD C, reads ; and perform a sequential file read + CALL bdos ; BDOS will look at the FCB and retrieve the appropriate block + + CP 0 ; Check for errors on read. If we see anything other than + JR NZ, ERRRDD ; a zero, we have something wonky on the read. + ; --- DMA buffer now contains 128 bytes from file + + ; --- Fluff of code to read through file + LD D, 128 ; Prepare for counting through 128 bytes record... + LD HL, sdma ; Using the HL as a pointer to positions on DMA buffer +PRTBYTE LD E, (HL) ; Load content of address in HL into E + + ; This bit works for text, will be wonky if the file is binary + ; But, it seems that if a record is not full, it's supposed to get + ; filled with EOF characters until end... + LD A, eof ; Check for EOF character + CP E ; If cound, we're at the end of file + JR Z, DONE ; .. so jump to done + + LD C, conout ; Prepare a Console Character Out BDOS call + PUSH HL ; BDOS call clobbers HL, push to stack + CALL bdos ; Go to BDOS for conout call + POP HL ; Restore HL after BDOS call + INC HL ; Next byte + DEC D ; .. until all needed characters.. + JR NZ, PRTBYTE + + ; If we've gotten here, we have completed one 128 byte set, and + ; haven't seen any EOF characters yet. So, try to get a new one. + JP RREC ; Jump to read next record from file. + + +DONE LD DE, donemsg ; Do a quick status at the end of completion... + LD C, strout + CALL bdos + JP 0 ; Do a jump to BOOT, causing a boot to CCP + +ERROPF LD DE, erropn + JP ERROR +ERRRDD LD DE, errrd + JP ERROR + +ERROR LD C, strout + CALL bdos + JP 0 ; Do a jump to BOOT, causing a boot to CCP + +erropn ASC "\r\n---> ERROR opening file\r\n$" +errrd ASC "\r\n---> ERROR reading file\r\n$" +okmsg ASC "\r\n---> Opened file\r\n$" +donemsg ASC "\r\n---> Completed reading file.\r\n$" +