+; 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$"
+