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