title CP/M 3.x ASCII DUMP Utility name ('DUMPASC') ; Original DASMed version of CP/M 3.x DUMP.COM ; A bit optimized and fixed for dump ASCII only FALSE equ 0 TRUE equ NOT FALSE OS equ 0000h BDOS equ 0005h FCB equ 005ch CCP equ 0080h _RRN equ 33 .conin equ 1 .conout equ 2 .condir equ 6 .string equ 9 .conbuf equ 10 .consta equ 11 .resdsk equ 13 .open equ 15 .rdseq equ 20 .setdma equ 26 .filsiz equ 35 .errmod equ 45 .SCB equ 49 .conmod equ 109 _get equ 0fdh .PWlen equ 8 RecLng equ 128 Recs equ 8 ; Get 8 records a time OSerr equ -1 _PWerr equ 7 _ExtErr equ -1 _CtrlC equ 00001b _PagLen equ 1ch _PagMod equ 2ch CtrlC equ 'C'-'@' CtrlX equ 'X'-'@' lf equ 0ah cr equ 0dh eot equ '$' LoMask equ 00001111b ClMask equ 00111111b ; ; Print byte as hex characters ; ENTRY Accu holds byte ; HexByte: push af rra ; Get HI bits rra rra rra call HexNibb ; .. and print pop af ; .. then LO ; ; Print nibble as hex character ; ENTRY Accu holds nibble ; HexNibb: and LoMask ; .. mask add a,90h daa adc a,40h daa jr Conout ; ; Print byte as ASCII character ; ENTRY Accu holds byte ; ASCIIbyte: cp '~'+1 ; Test range jr nc,ItsASC ; .. give dot if no ASCII cp ' ' jr nc,Conout ; .. it is ASCII ItsASC: ld a,'.' ; ; Print character on console ; ENTRY Accu holds character ; Conout: push hl push de push bc ld e,a ; Put into right place ld c,.conout call BDOS ; .. and print pop bc pop de pop hl ret ; ; Open file ; OpenFile: ld c,.open ld de,FCB call BDOS ; Open file ld (IOres),a ; .. save code ld a,h cp _PWerr ; Test password required jr z,GetPasswd ld a,(IOres) cp OSerr ; Test any error ret nz ; .. nope jp NoFile GetPasswd: ld a,(PwFlag) ; Get flag cp TRUE ; .. test tried before jp z,InvPW ; .. yeap, invalid call ClrPW ; Clear password ld de,$PASSWD call String ; Tell what we want ld a,.PWlen ld (CCP),a ; Set length ld c,.conbuf ld de,CCP call BDOS ; Read password ld a,(CCP+1) ; Get length ld (PW.Len),a or a jp z,Exit ; .. end if no input call UPPline ; Convert to UPPER case ld de,CCP+2 call SetDMA ; Set as buffer ld a,TRUE ld (PwFlag),a ; Force one try jr OpenFile ; ; Clear password entry ; ClrPW: ld b,.PWlen ; Get length ld hl,CCP+2 ClrLoop: ld (hl),' ' ; .. blank it inc hl djnz ClrLoop ret ; ; Convert password to UPPER case ; UPPline: ld b,.PWlen ; Init a bit ld hl,CCP+2 UPPloop: ld a,(hl) cp 'a' ; Test 'a'..'z' jr c,ItsLo cp 'z'+1 jr nc,ItsLo sub 'a'-'A' ; .. convert to UPPER case ld (hl),a ItsLo: inc hl djnz UPPloop ld a,(PW.Len) ; Get length of input add a,CCP+2 ; .. add buffer ld (EndPtr),a ld hl,(EndPtr) ld (hl),' ' ; .. clear last entry ret ; ; %%%%%%%%%%%%%%%% ; %% DUMP ENTRY %% ; %%%%%%%%%%%%%%%% ; DUMP: ld sp,LocStk ; Get my stack call PrHead ; Give header call SetMode ; Set error mode and break call GetScr ; Get console state call OpenFile ; Open file call GetSize ; Get valid size ; ; Read buffer from file ; ReadBuff: ld de,Heap ; Init data pointer RdLoop: push de call SetDMA ; Set disk buffer call ReadRec ; Read a record pop de ld a,(RecRead) inc a ; Bump record count ld (RecRead),a cp Recs ; Test buffer filled jr z,DUMPbuf ; .. yeap, so go dump ld hl,RecLng add hl,de ; .. next record address ex de,hl jr RdLoop ; ; Dump entire buffer ; DUMPbuf: ld l,0 ; Set limit ld a,(RecRead) ; Get records read rra call c,FixLimit ; Fix limit on even count ld h,a ; Get as page count dec hl ld (Pages),hl ; .. save call DUMPit ; .. do the job ld a,(EOF) ; Test end of file cp TRUE jp z,Exit ; .. exit if so xor a ld (RecRead),a ; .. clear record count jr ReadBuff ; .. read next buffer ; ; Read record from file ; ReadRec: ld c,.rdseq ld de,FCB call BDOS ; Read record or a ret z ; .. ok, there's more ld a,(RecRead) ; Test record read or a jp z,Exit ; .. end if none read ld a,TRUE ld (EOF),a ; Set end of file jr DUMPbuf ; .. dump remaining buffer ; ; Set disk buffer ; ENTRY Reg DE points to buffer ; SetDMA: ld c,.setdma call BDOS ; Set buffer ret ; ; Test break detected ; EXIT Zero set if no character found ; IsBreak: push bc push de push hl ld c,.consta call BDOS ; Get state or a push af ld c,.conin call nz,BDOS ; .. clean keyboard if pending pop af pop hl pop de pop bc ret ; ; Print hex address ; EXIT Reg HL holds start of buffer ; HexAdr: ld hl,(DMPadr) ld a,h call HexByte ; Dump HI ld a,l ld hl,(DMPstrt) ; Get start of buffer call HexByte ; .. dump LO ld a,':' jp Conout ; Give delimiter ; ; Test screen filled ; TestMORE: ld a,(PagMode) ; Test page mode or a call z,IsMORE? ; .. continous, so wait ret ; ; Give new line on console ; NL: ld a,cr ; .. simple control call Conout ld a,lf jp Conout ; ; Give blank on console ; PrBlank: ld a,' ' jp Conout ; .. give blank ; ; Check screen filled ; IsMORE?: ld a,(PagLen) ; Get page length ld e,a ld a,(CurLine) cp e ; Test screen filled jr z,IsFull ; .. yeap inc a ; .. bump ld (CurLine),a ret IsFull: xor a ld (CurLine),a ; Clear line ld de,$MORE call String ; .. tell full WtCR: ld c,.condir ld e,_get call BDOS ; Get character cp CtrlC ; Test break jp z,Exit ; .. end if so cp cr jr nz,WtCR ; .. wait for CR ld a,CtrlX jp Conout ; .. give cancel ; ; Compare current address to end address ; ENTRY Reg HL holds current address ; EXIT Carry set if end ; IsEnd?: ex de,hl ld hl,(DMPend) ; Get end or a sbc hl,de ; .. compare ex de,hl ret ; ; Do the dump job ; DUMPit: ld de,(Pages) ; Get page count ld hl,Heap ; Init data pointer ld (DMPstrt),hl ; .. for start add hl,de ld (DMPend),hl ; .. and end DMP.Loop: call TestMORE ; .. test full screen call NL ; Give new line call IsBreak ; Test key pressed jp nz,Exit ; .. end if so ld hl,(DMPstrt) ; Get start ld (DMPptr),hl ; .. as pointer call HexAdr ; Give hex address call PrBlank ; Give blank DMP.ASCLoop: ld a,(hl) ; Get character call ASCIIbyte ; .. type it inc hl push hl ld hl,(DMPadr) ; Get line address ld a,l and ClMask cp ClMask ; Test line boundary inc hl ; .. bump address ld (DMPadr),hl pop hl jr nz,DMP.ASCLoop ld (DMPstrt),hl ; .. set new start call IsEnd? ; Test job done jr nc,DMP.Loop ret ; .. yeap ; ; Give header message ; PrHead: ld de,$HEAD call String ; .. print it ret ; ; Set error mode and keyboard state ; SetMode: ld c,.errmod ld e,_ExtErr call BDOS ; Set extended error ld c,.conmod ld de,_CtrlC call BDOS ; Set console status at Ctrl-C ret ; ; Get console state ; GetScr: ld c,.SCB ld de,PB.PagMode call BDOS ; Get page mode or a ret nz ; .. exit if not ld (PagMode),a ; .. save ld c,.SCB ld de,PB.PagLen call BDOS ; Get length of page dec a ld (PagLen),a ret ; ; Get size of file ; GetSize: ld c,.filsiz ld de,FCB call BDOS ; Get size of file ld ix,FCB+_RRN ld a,(ix+0) or (ix+1) ; Test any record or (ix+2) ret nz ; .. yeap ld de,$NO.REC call String ; .. tell empty file jp Exit ; .. exit ; ; Set buffer count ; FixLimit: ld l,RecLng ; .. set length ret ; ; Print string on console ; ENTRY Reg DE points to string ; String: ld c,.string call BDOS ; .. print ret ; ; Tell file not found ; NoFile: ld c,.string ld de,$NO.FILE call BDOS ; Print message jr Exit ; .. and stop ; ; Tell invalid password ; InvPW: ld de,$PW.ERR call String ; Give message ; ; Stop DUMP ; Exit: ld c,.resdsk call BDOS ; Reset disk system jp OS ; .. and exit ; $HEAD: db cr,lf,lf,'CP/M 3 DUMP - Version 3.0',eot $NO.FILE: db cr,lf,'ERROR: File Not Found',cr,lf,eot $PASSWD: db cr,lf,'Enter Password: ',eot $PW.ERR: db cr,lf,'Password Error',eot $NO.REC: db cr,lf,'ERROR: No Records Exist',eot $MORE: db cr,lf,'Press RETURN to continue ',eot DMPend: dw 0 DMPptr: dw 0 DMPstrt: dw 0 DMPadr: dw 0 ; IOres: db 0 RecRead: db 0 EOF: db FALSE PwFlag: db FALSE Pages: dw 0 PB.PagMode: db _PagMod,0 PB.PagLen: db _PagLen,0 PagMode: db TRUE PagLen: db 0 CurLine: db 0 PW.Len: db 0 EndPtr: dw 0 ; ds 2*10 LocStk: Heap equ $ end DUMP