; GENGRAF.ASM ; ----------- ; ; GSX-80 - GENGRAF.COM ; ; Disassembled by: ; ; ROCHE Emmanuel ; 8 rue HERLUISON ; 10000 TROYES ; FRANCE ; ------ ; ;-------------------------------- ; PAGE 0 ; Listing without page breaks ; ORG 0100H ; Standard CP/M-80 COMmand file ; ;-------------------------------- ; List of ASCII characters used ; lf equ 0AH ; Line Feed cr equ 0DH ; Carriage Return ctrlZ equ 1AH ; = End Of File ; ;-------------------------------- ; List of BDOS functions used ; BDOS equ 0005H ; Basic Disk Operating System ; sysres equ 0 ; System reset conout equ 2 ; Console output pstring equ 9 ; Print string openf equ 15 ; Open file closef equ 16 ; Close file deletef equ 19 ; Delete file readf equ 20 ; Read sequential writef equ 21 ; Write sequential makef equ 22 ; Make file renamef equ 23 ; Rename file setDMA equ 26 ; Set DMA address filsiz equ 35 ; Compute file size ; ;-------------------------------- ; List of page zero locations used ; reboot EQU 0000H ; Warm start dskuse EQU 0004H ; Current disk and user number topTPA EQU 0006H ; Address of top TPA I$0010 EQU 0010H ; ----I I$0020 EQU 0020H ; ----I FCB1 EQU 005CH ; Default File Control Block 1 ZERtyp EQU 0065H ; First char of filetype in page zero ZERcr EQU 007CH ; Current record position in page zero ZERrrn EQU 007DH ; Random record number in page zero DBUF EQU 0080H ; Default 128-byte disk buffer ; C$CD02 EQU 0CD02H ; -C--- I$CDF9 EQU 0CDF9H ; ----I I$FFF3 EQU 0FFF3H ; ----I ; ;-------------------------------- ; List of offset inside Default FCB 1 ; FCBtyp equ 0009H ; First char of filetype in FCB FCBex equ 000CH ; Current extent number in FCB ; ;====================================================================== ; Start of first program ; start1: DB 0C3H ; Jump opcode ; word1: DW start2 ; Point to start of program ; retone: DB 0C9H ; Return opcode ; word2: DW 0000H ; ? ; start3: LXI H,0001H ; HL = 1 (point to BIOS entry?) SPHL ; Stack = above CALL chkASG ; Check is ASSIGN.SYS is on disk CALL readA ; Read ASSIGN.SYS file MVI A,05H ; Number of drivers to try to load PUSH PSW ; LXI H,DMAbuf ; DMA buffer (source) LXI D,DDnumb ; DD number (destination) getbyt: MOV A,M ; Get a byte from ASSIGN.SYS CPI ctrlZ ; = EOF? JZ close3 ; Then Close ASSIGN.SYS CPI 31H ; Is it a number? JNC dozen ; XRA A ; If < 1 then set to 0 JMP digit ; ; ;-------------------------------- ; dozen: SUI 30H ; Convert to binary number ADD A ; (Multiplied by 10?) MOV B,A ; ADD A ; ADD A ; ADD B ; digit: MOV B,A ; INX H ; MOV A,M ; Get a byte from ASSIGN.SYS SUI 30H ; Convert to binary number ADD B ; STAX D ; Store it in DD number XRA A ; Reset Reg-A to zero INX D ; STAX D ; 2nd byte of DD number = zero INX D ; INX H ; (Space separator in ASSIGN.SYS) INX H ; (Point to drive letter) CALL upper ; Convert to upper case SUI 40H ; Convert to binary number STAX D ; Store in DD list INX D ; Point to next char in destination INX H ; Point to next char in source MVI C,08H ; 8 chars of device driver DDname: CALL upper ; Convert to upper case CPI ';' ; Start of comments? (end of DD name) JZ fill1 ; CPI cr ; End of line? JNZ fill2 ; fill1: MVI A,' ' ; Space for filling DD filename DCX H ; Decrement counter fill2: STAX D ; Put space in DD table INX D ; DCR C ; = 0? JNZ DDname ; No: loop MVI A,lf ; Yes: we must have reached the Line Feed fill3: CMP M ; Isn't it? INX H ; JNZ fill3 ; POP PSW ; DCR A ; Loop 5 times PUSH PSW ; JNZ getbyt ; Get another byte from ASSIGN.SYS close3: POP PSW ; CALL closeA ; Close ASSIGN.SYS LHLD topTPA ; Load address of top of TPA from page zero SHLD savtop ; Save address of top of TPA LXI D,DDlist ; Source: List of 5 DD filenames LXI H,ASSIGN ; Destin: ASSIGN.SYS file spec MVI C,09H ; 9 bytes (drive code + DD filename) CALL copyDH ; Copy one file specification MVI M,50H ; "P" (add PRL filetype) INX H ; MVI M,52H ; "R" INX H ; MVI M,4CH ; "L" CALL C0278 ; LHLD LOMEM ; New top of TPA after DD is loaded SHLD savtop ; Save address of top of TPA LXI D,GSXSYS ; Source: GDOS file specification LXI H,ASSIGN ; Destin: ASSIGN.SYS file spec MVI C,0CH ; 12 bytes (drive code + FILENAME.TYP) CALL copyDH ; Copy one file specification CALL C0278 ; LHLD LOMEM ; Destin: New top of TPA after DD is loaded PUSH H ; LXI B,dskuse ; Current disk and user number DAD B ; LXI D,topTPA ; Source: Load address of top TPA MVI C,02H ; 2 bytes CALL copyDH ; Copy it in LOMEM LXI D,DDnumb ; Source: MVI C,02H ; 2 bytes CALL copyDH ; Copy it in DDnumb DCX D ; DCX D ; Source: MVI C,37H ; 55 bytes (5 times 11 bytes) CALL copyDH ; Copy 5 file specifications XCHG ; INX D ; INX D ; MVI C,pstring ; Print string CALL BDOS ; LHLD word2 ; Load what? POP D ; DAD D ; JNC ninofm ; 'not enough memory$' XCHG ; SHLD topTPA ; Store address of top TPA MVI C,setDMA ; Set DMA address LXI D,DBUF ; Default 128-bytes disk buffer CALL BDOS ; LXI D,reloc ; Source: Put RELOC address in Reg-DE LHLD LOMEM ; Destin: New top of TPA after DD is loaded LXI B,I$FFF3 ; Length of GSX.SYS (GDOS) ? DAD B ; PUSH H ; SHLD GDOSb ; GDOS base MVI C,0DH ; 13 bytes CALL copyDH ; Copy a string in TPA LXI H,border ; Limit between 1st and 2nd program POP D ; PUSH D ; MOV A,E ; SUB L ; MOV C,A ; MOV A,D ; SBB H ; MOV B,A ; LXI D,start1 ; Start of first program JMP retone ; Return opcode ; ;-------------------------------- ; HL source ; DE destination ; BC count ; reloc: MOV A,M ; Get a byte STAX D ; Put it in destination INX H ; INX D ; DCX B ; Decrement 16 bit counter MOV A,B ; ORA C ; If finished, then jump to GDOS DB 0C2H ; JNZ opcode GDOSb: DW 0000H ; GDOS base JMP start1 ; Else: Start of first program ; ;-------------------------------- ; Test if lower cases. ; If so, convert to upper cases. ; upper: MOV A,M ; Get a byte INX H ; CPI 'a' ; Beginning of lower cases? RC ; CPI 'z'+1 ; End of lower cases? RNC ; SUI 20H ; Convert to upper cases RET ; ; ;-------------------------------- ; Copy a string in TPA from DE (source) to HL (destination) ; ; DE = source ; HL = destination ; C = number of bytes ; copyDH: LDAX D ; Get a byte from source MOV M,A ; Put it in TPA at destination HL INX D ; INX H ; DCR C ; Decrement counter JNZ copyDH ; RET ; ; ;-------------------------------- ; ninofm: LXI D,notmem ; 'Not enough memory$' JMP bak2CPM ; ; ;-------------------------------- ; notmem: DB 'Not enough memory$' ; GSXSYS: DB 00H ; Default drive DB 'GSX SYS' ; GDOS file specification ; ;-------------------------------- ; Table of DDs ; ; Format: ; DW 0FFFFH is replaced by DD number (HI = DD number, LO = 00H) ; DB 00H is replaced by the drive number ; DS 8 is replaced by the DD filename ; DDnumb: DW 0FFFFH DDlist: DB 00H DB ' ' ; First DD filename ; DW 0FFFFH DB 00H DB ' ' ; Second DD filename ; DW 0FFFFH DB 00H DB ' ' ; Third DD filename ; DW 0FFFFH DB 00H DB ' ' ; Fourth DD filename ; DW 0FFFFH DB 00H DB ' ' ; Fifth DD filename ; ;-------------------------------- ; C0278: CALL chkASG ; Check if ASSIGN.SYS is on disk CALL readA ; Read ASSIGN.SYS file LHLD DMA2nd ; DMA buffer 2nd byte (PRL program size) PUSH H ; XCHG ; LHLD savtop ; Load address of top of TPA MOV A,L ; SUB E ; MOV A,H ; Compute HIMEM - PRL program size SBB D ; MOV H,A ; MVI L,00H ; Page boundary SHLD LOMEM ; Store address of new top of TPA PUSH H ; PUSH H ; PUSH D ; CALL readA ; Read ASSIGN.SYS file POP B ; POP H ; J$0298: CALL C02C8 ; MOV M,A ; INX H ; DCX B ; MOV A,C ; ORA B ; JNZ J$0298 ; POP H ; MOV B,H ; DCR B ; POP D ; J$02A7: MVI C,08H ; 8 CALL C02C8 ; J$02AC: RLC ; PUSH PSW ; JNC J$02B4 ; MOV A,B ; ADD M ; MOV M,A ; J$02B4: INX H ; DCX D ; MOV A,D ; ORA E ; JZ close2 ; Close ASSIGN.SYS POP PSW ; DCR C ; JNZ J$02AC ; JMP J$02A7 ; ; ;-------------------------------- ; close2: POP PSW ; CALL closeA ; Close ASSIGN.SYS RET ; ; ;-------------------------------- ; C02C8: PUSH H ; PUSH D ; LHLD D03B6 ; INR L ; JP J$02D9 ; PUSH B ; CALL readA ; Read ASSIGN.SYS file POP B ; LXI H,0000H ; J$02D9: SHLD D03B6 ; LXI D,DMAbuf ; DMA buffer DAD D ; MOV A,M ; POP D ; POP H ; RET ; ; ;-------------------------------- ; Check if file is on disk ; chkASG: LXI D,ASSIGN ; ASSIGN.SYS file spec chkfil: PUSH D ; LXI H,FCBex ; Point to current extent number DAD D ; MVI M,00H ; INX H ; INX H ; MVI M,00H ; MVI A,80H ; STA D03B6 ; MVI C,openf ; Open file CALL BDOS ; POP D ; LXI H,I$0020 ; DAD D ; MVI M,00H ; badchk: ORA A ; Successful open/close? RP ; Yes: return CALL showFN ; No: Display filename on console LXI D,notfnd ; ' not found$' JMP bak2CPM ; ; ;-------------------------------- ; closeA: LXI D,ASSIGN ; ASSIGN.SYS file spec MVI C,closef ; Close file CALL BDOS ; JMP badchk ; Cf. above ; ;-------------------------------- ; Display filename on console ; showFN: XCHG ; MOV A,M ; Get drive code ORA A ; JZ nodriv ; ADI 40H ; Convert drive code in letter MOV E,A ; CALL showit ; MVI E,':' ; Drive separator CALL showit ; nodriv: INX H ; MVI A,8+1 ; Filename CALL loopri ; MVI E,'.' ; Filename separator CALL showit ; MVI A,3+1 ; Filetype CALL loopri ; RET ; ; ;-------------------------------- ; Display a char on console ; showit: PUSH H ; MVI C,conout ; Console output CALL BDOS ; POP H ; RET ; ; ;-------------------------------- ; Display n-1 chars on console ; loopri: DCR A ; Done? RZ ; MOV E,M ; Get char INX H ; Ready next char PUSH PSW ; CALL showit ; Display the char on console POP PSW ; JMP loopri ; Loop until done ; ;-------------------------------- ; Read ASSIGN.SYS file ; readA: LXI D,DMAbuf ; DMA buffer MVI C,setDMA ; Set DMA address CALL BDOS ; LXI D,ASSIGN ; ASSIGN.SYS file spec PUSH D ; MVI C,readf ; Read sequential CALL BDOS ; POP D ; ORA A ; Successful read? RZ ; Yes: return CALL showFN ; No: Display filename on console LXI D,whyEOF ; ': unexpected EOF$' bak2CPM:MVI C,pstring ; Print string CALL BDOS ; JMP reboot ; Warm start ; ;-------------------------------- ; whyEOF: DB ': unexpected EOF$' ; notfnd: DB ' not found$' ; ASSIGN: DB 00H ; Default drive DB 'ASSIGN SYS' ; File specification DS 24 ; Rest of FCB definition ; savtop: DW 0000H ; Save area for top of TPA ; LOMEM: DW 0000H ; Save area for new top of TPA, ; after a DD is loaded in TPA ; D03B6: DW 0000H ; ? ; DMAbuf: DB 00H ; DMA buffer first byte ; DMA2nd: DB 00H ; DMA buffer second byte (PRL program size) ; DS 126 ; Rest of 128-bytes buffer ; ; ;====================================================================== ; Start of second program ; start2: LXI D,copyr ; Copyright message MVI C,pstring ; Print string CALL BDOS ; LXI H,ZERtyp ; First char of filetype in page zero MVI M,43H ; "C" (add COM filetype) INX H ; MVI M,4FH ; "O" INX H ; MVI M,4DH ; "M" LXI D,FCB1 ; Default FCB in page zero MVI C,filsiz ; Compute file size CALL BDOS ; LHLD ZERrrn ; Random record number in page zero DAD H ; DAD H ; DAD H ; DAD H ; DAD H ; DAD H ; DAD H ; LXI D,I$048D ; DAD D ; MOV A,L ; CMA ; MOV L,A ; MOV A,H ; CMA ; MOV H,A ; INX H ; SHLD word2 ; Save what? XRA A ; STA ZERcr ; Current record position set to zero LXI H,FCB1 ; Source: Default FCB in page zero LXI D,FCBseq ; Destin: FCB for read/write seq PUSH D ; MVI C,24H ; 36 bytes CALL copyHD ; POP D ; PUSH D ; LXI H,FCBtyp ; Point to first char of filetype ; border: ; +++ Limit between 1st and 2nd program +++ ; DAD D ; MVI M,24H ; "$" (temporary file) INX H ; MVI M,24H ; "$" INX H ; MVI M,24H ; "$" MVI C,deletef ; Delete file CALL BDOS ; I$048D EQU $-1 ; ??? POP D ; MVI C,makef ; Make file CALL BDOS ; INR A ; JZ nodspc ; Display 'no dir space' on console LXI H,start3 ; Relocate start of program SHLD word1 ; Point to start of program LXI D,start1 ; Start of first program J$04A1: PUSH D ; MVI C,setDMA ; Set DMA address CALL BDOS ; LXI D,FCBseq ; FCB for read/write seq MVI C,writef ; Write sequential CALL BDOS ; POP D ; LXI H,DBUF ; Default 128-bytes disk buffer DAD D ; XCHG ; LXI H,start2 ; Start of second program MOV A,E ; SUB L ; MOV A,D ; SBB H ; JC J$04A1 ; LXI D,FCB1 ; Default FCB in page zero CALL chkfil ; Check if file is on disk J$04C5: MVI C,80H ; LXI D,copyr ; J$04CA: PUSH D ; PUSH B ; MVI C,setDMA ; Set DMA address CALL BDOS ; LXI D,FCB1 ; Default FCB in page zero MVI C,readf ; Read sequential CALL BDOS ; STA errcod ; Error code (Read sequential) ORA A ; POP B ; POP D ; JNZ J04EE ; DCR C ; JZ J04EE ; LXI H,DBUF ; Default 128-bytes disk buffer DAD D ; XCHG ; JMP J$04CA ; ; ;-------------------------------- ; J04EE: MVI A,80H ; SUB C ; MOV C,A ; LXI D,copyr ; J$04F5: PUSH B ; PUSH D ; MVI C,setDMA ; Set DMA address CALL BDOS ; LXI D,FCBseq ; FCB for read/write seq MVI C,writef ; Write sequential CALL BDOS ; ORA A ; POP D ; POP B ; JNZ werror ; Display 'write error$' on console DCR C ; JZ J$0516 ; LXI H,DBUF ; Default 128-bytes disk buffer DAD D ; XCHG ; JMP J$04F5 ; ; ;-------------------------------- ; J$0516: LDA errcod ; Error code (Read sequential) ORA A ; JZ J$04C5 ; LXI D,FCBseq ; FCB for read/write seq MVI C,closef ; Close file CALL BDOS ; LXI D,FCB1 ; MVI C,deletef ; Delete file CALL BDOS ; LXI D,FCBseq ; FCB for read/write seq LXI H,I$0010 ; DAD D ; MVI C,10H ; 16 bytes XCHG ; CALL copyHD ; LXI H,rentyp ; MVI M,43H ; "C" (add COM filetype) INX H ; MVI M,4FH ; "O" INX H ; MVI M,4DH ; "M" MVI C,renamef ; Rename file LXI D,FCBseq ; FCB for read/write seq CALL BDOS ; MVI C,sysres ; System reset JMP BDOS ; ; ;-------------------------------- ; HL = source ; DE = destination ; C = count ; copyHD: MOV A,M ; Get a byte STAX D ; Put it in destination DE INX H ; INX D ; DCR C ; Decrement count JNZ copyHD ; RET ; ; ;-------------------------------- ; werror: LXI D,wrierr ; 'Write Error.$' JMP bak2CPM ; ; ;-------------------------------- ; nodspc: LXI D,nodirs ; 'No Directory Space.$' JMP bak2CPM ; ; ;-------------------------------- ; errcod: DB 00H ; Error code (Read sequential) ; DB 00H ; (Byte added by linker?) ; FCBseq: DB 00H ; FCB for read/write seq DB 00H,00H,00H,00H,00H,00H,00H,00H DB 00H,00H,00H,00H,00H,00H,00H,00H DB 00H,00H,00H,00H,00H,00H,00H,00H ; rentyp: DB 00H,00H,00H ; Filetype for renaming filename.COM DB 00H,00H,00H,00H,00H,00H,00H,00H ; ;-------------------------------- ; wrierr: DB 'Write Error.$' ; nodirs: DB 'No Directory Space.$' ; copyr: DB '---------------------------------------------------', cr, lf DB 'GENGRAF 1.0 15 Nov 82 Serial No 5000-1232-654321', cr, lf DB 'Copyright (C) 1982 ', cr, lf DB 'Digital Research, Inc. All Rights Reserved', cr, lf DB '---------------------------------------------------', cr, lf, '$' ; ;-------------------------------- ; END 100H ; Standard CP/M-80 COMmand file