; 1980-06-11 Started disassembling DMON-M V3.1 ; 1988-06-14 Last edits; ; 2018-10-14 OCR of scans in pdf document. ; 2023-05-17 DMON-M code edited to be ; conditional assembly for DMON-S ; 2023-05-21 Verifed producing M and S versions ; ; To do: conditionally assemble the H version ; ; This source file assembles at ; https://www.asm80.com/ ; but required some mods ; to get round stuff that asm80 could not handle. ; ; Note the OCR process often confuses characters. ; You will need to check the code before use. ; ; This source code has been checked against ; a known-good binary image of the monitor. ; ; These two lines work around an asm80 issue: ; ASCII_H equ 0x48 ASCII_M equ 0x4D ASCII_S equ 0x53 ; ; ; .cpu z80 ; ; There are several versions of the monitor, ; depending on the main I/O system ; ; DMON-M is a Disk-based monitor with VDU and KBD cards ; DMON-S is a Disk-based monitor with serial port ; ZYMONM is a Tape-based monitor ; ; Conditional assembly uses ; ; ; ; version_char equ 'S' ; Serial port user interface DOES NOT WORK! version_char equ ASCII_S ; Serial port user interface ; version_char equ ASCII_M ; VDU and KBD user interface ; version_char equ ASCII_H ; VDU and Serial port user interface ? ; ; I think the ZYMON monitors are significantly different, ; so conditional assembly is not practical for them and DMON. ; ; ; ; ; PAGE 1 ; ; TITLE DM.MAC ; DISASSEMBLY OF DMON-M V3.1 COMMENCED 11TH JUNE 1980 ; TITLE 'Z80 System Monitor' ; W.S, 1984 ; last Edit 14th June 1988 ;;; .Z80 ; DM.COM E000..E7FF ;;; ASEG FALSE EQU 0 ;; TRUE EQU NOT FALSE ; asm80 didn't like this TRUE EQU -1 ; so this used instead .if version_char = ASCII_S WIDESC .EQU TRUE .org 0xE000 ; .PHASE 0E000H .binfrom 0xE000 .binto 0xE800 .endif ; .if version_char = ASCII_M WIDESC .EQU FALSE .org 0x100 .PHASE 0E000H .binfrom 0x0100 .binto 0x0900 .endif CSTAT EQU 000H ; Console status CDATA EQU 001H ; Console data INNSK EQU 040H ; Input Mask (DAV) OMSK EQU 080H ; Output Mask (TBMT) LSTAT EQU 060H ; List Status LDATA EQU 070H ; List Data LOMSK EQU 080H ; Output Mask (TBMT) ;FLAG EQU 040H IBUFP EQU 0041H ; Pointer to next ; input buffer location IBUFF EQU 0080H ; console input buffer CTRL_C EQU 003H ; CTRL-C Abort BS EQU 008H ; CTRL-H Backspace HT EQU 009H ; CTRL-I Horizontal Tab LF EQU 00AH ; CTRL-J Line Feed VT EQU 00BH ; CRTL-K Vertical Tab FFEED EQU 00CH ; CTRL-L Form Feed CR EQU 00DH ; CTRL-M Carriage Return CTRL_P EQU 010H ; CTRL-P Print Toggle XOFF EQU 013H ; CTRL-Q TON XON EQU 011H ; CTRL-S TOFF CTRL_Z EQU 01AH ; CTRL-Z CTRL_Z ESC EQU 01BH ; CTRL-[ Escape RS EQU 01EH ; CTRL-^ RS DEL EQU 07FH ; Delete (Rubout) EOT equ 0x04 SOH equ 0x01 ;APOS EQU 0F7H ; APOS???? ; ; The source code relies on screen width ; (character columns) being a power of 2 ; for doing the hex dump. ; The constant LEND masks off the LS bits. ; ; This is not going to work for screen widths ; like 40 or 80. ; The width should be rounded down to ; a power of 2, then decremented to form LEND. ; ; ; ; .IF WIDESC = TRUE ; 64 Cols is not a wide screen XXFFF8 EQU 16 ; DUMP LINE LENGTH .ELSE XXFFF8 EQU 8 ; DUMP LINE LENGTH .ENDIF ; XXN02 EQU 002H N03 EQU 003H XXN82 EQU 082H XXXN17 EQU 017H XXXN18 EQU 018H XXN1C EQU 01CH XXXNF0 EQU 0F0H APOS EQU 0F7H LEND EQU XXFFF8-1 ; Line end ( 8 or 16 characters per line of dump) N88 EQU 088H XXN94 EQU 094H NA8 EQU 0A8H XXNC4 EQU 0C4H XXND0 EQU 0D0H XXNE0 EQU 0E0H XXNEC EQU 0ECH NF6 EQU 0F6H ; RAMST EQU 00000H ; RAM start ; FLAG EQU 00040H ; List device on/off flag ; .if version_char = ASCII_M UARTSP EQU 00044H ; UART status port .endif ; .if version_char = ASCII_S UARTSP_alt EQU 0e044H ; UART status port FLAG_alt EQU 08040H ; List device on/off flag UARTSP EQU 044H ; UART status port .endif ; T0001 EQU 00001H COLS EQU 64 ROWS EQU 24 FDCCMD EQU 00045H ; Save command DRIVE EQU 00046H ; Drive STATUS EQU 00047H ; Status DRVCMD EQU 00048H ; Drive command CURPOS EQU 00049H EFLAG EQU 0004BH IFLAG EQU 0004CH ; IBUFP 41 IBUFC EQU 00043H ; Counter for input buffer IBUFCX EQU 0004EH KSAVE EQU 0004DH ; Keyboard data CONFIG EQU 00050H ; Configuration ADDSPT EQU 00051H ; Addr of Sectors per track B0052 EQU 00052H T0052 EQU 00052H WPCTRK EQU 00053H ; Write precompensation track DRIVNO EQU 00054H ; Drive No ; ; PAGE 1-2 ; TRAKNO EQU 00055H ; Track No SECTNO EQU 00056H ; Sector No DMAADD EQU 00057H ; DMA addr COMMAND EQU 00059H B005A EQU 0005AH DPARM EQU 165 ; PARAMETER FDR DELAY LOOP DPARM3 EQU 750 ; PARAMETER FOR DELAY LOOP DPARM2 EQU 220 ; PARAMETER FOR DELAY LOOP T00F0 EQU 000F0H L09AD EQU 009ADH VDUST EQU 0F000H ; VDU RAM start TF5C0 EQU 0F5C0H TFFAF EQU 0FFAFH TFFC0 EQU 0FFC0H UART2S EQU 004H KBPORT EQU 040H DSTAT EQU 080H DTRACK EQU 081H DSECT EQU 082H DDATA EQU 083H DPOLL EQU 084H DCONF EQU 085H EPORT EQU 0FFH ; DMON: JP INIT ; Cold start JP CONST ; .if version_char = ASCII_M JP CONIN .endif ; .if version_char = ASCII_S JP CONIN_S .endif ; JP CONOUT ;-------------------------------------- ; ; List output routine ; LOUT: PUSH BC ; Save C PUSH AF ; Save char LOUT2: TTBMT: ; .if version_char = ASCII_M LD A,(UARTSP) ; List status port .endif ; .if version_char = ASCII_S LD A,(UARTSP_alt) ; List status port .endif ; LD C,A ; Load C with the UART Status Port IN A,(C) ; Input List Status AND 80H ; Test TBMT JR Z,TTBMT ; Loop if not ready (TB not MT) INC C ; Bump on to data port ; ; PAGE 1-3 ; POP AF ; Retrieve char AND 07FH ; Remove Parity (if any) CP BS ; Is it Backspace? JR NZ,OUTC ; Jump if not ;;; LD A,'\' ; If was BS replace with '\' ; asm80 has problems with backslash, so: LD A,5CH ; equivalent LOUT3: OUTC: OUT (C),A ; Send char POP BC ; restore C RET ; end of subroutine ; ; Console input routine ; INPUTT: CALL CONST ; Check status JR Z,INPUTT ; not ready INPUTS: CALL CONIN ; Get byte CP CTRL_C ; Abort? JP Z,WARM ; Yes ; ; .if version_char = ASCII_M CP CTRL_P ; CTRL-P? JR Z,PSET ; list .endif RET .if version_char = ASCII_S CP 0xfc ; ? xor b ; then return... ? inc hl .endif ; ; Console output routine ; OUTT: ; .if version_char = ASCII_M LD A,(FLAG) ; Print? Get value from FLAG .endif ; PUSH AF ; save AF ; .if version_char = ASCII_S LD A,(FLAG_alt) ; Print? Get value from FLAG .endif OR A ; Zero? test for zero JR Z,OUT2 ; Yes Jump if zero OUT2 POP AF ; Char into Acc PUSH AF ; save CALL LOUT ; To list device OUT2: CALL CONST ; Input? JP Z,OUT4 ; No CALL INPUTS ; Get input CP XOFF ; Freeze? JR NZ,OUT2 ; No ; ; Freeze output until CTRL-0 or CTRL-C ; OUT3: ; ; PAGE 1-4 ; CALL INPUTT ; Input? CP XON ; Resume? JR NZ,OUT3 ; No JR OUT2 ; ; Toggle list output with CTRL-P ; PSET: LD A,(FLAG) CPL LD (FLAG),A JP INPUTT ; ; Input a line from console and put it into the line buffer. ; Carriage return ends the line. ; Delete (Rubout) or CTRL-H (backspace) ; corrects last char entered. ; CTRL-X restart line. ; Other control characters are ignored. ; INPLN: LD A,'>' ; 3E ; Prompt CALL OUTT INPLN2: LD HL,IBUFF ; Butter address LD (IBUFP),HL ; Save pointer LD C, 00H ; count INPLI: CALL INPUTT ; console char CP 20H ; Control char? JR C,INPLC ; yes CP DEL ; delete? JR Z,INPLB ; yes CP 'Z'+1 ; upper case? JR C,INPL3 ; yes AND 05FH ; convert to upper case INPL3: LD (HL) ,A ; put into buffer LD A,32 ; 32 chars max butter size CP C ; buffer full? JR Z,INPLI ; yes, loop LD A,(HL) ; get char INC HL ; paint to next location INC C ; and count INPLE: CALL OUTT ; show char JR INPLI ; next char ; ; PAGE 1-5 ; ; Process control character ; INPLC: CP BS ; is is backspace? JR Z,INPLB ; yes CP CR ; is it return? JR NZ,INPLI ; no, ignore ; End of input line LD A,C ; count LD (IBUFC),A ; save ; Carriage-return, Line-feed routine CRLF: LD A,CR CALL OUTT ; Send CR LD A,LF JP OUTT ; Send LF ; Delete previous character if any INPLB: LD A,C ; char count OR A ; zero? JR Z, INPLI ; yes DEC HL ; move pointer back DEC C ; and count LD A,BS ; character CALL CONOUT LD A,' ' CALL CONOUT LD A,BS JR INPLE ; send ; ; Get a character from ; console buffer ; Set Carry if empty ; GETCH: PUSH HL ; save regs LD HL,(IBUFP) ; get pointer LD A,(IBUFC) ; and count SUB 01H ; clear with carry ; ; PAGE 1-6 ; JR C,GETC4 ; no more chars LD (IBUFC),A ; save new count LD A,(HL) ; get character INC HL ; increment pointer LD (IBUFP),HL ; and save GETC4: POP HL ; restore regs RET ; ; Send ASCII tessage until binary zero is ; found. Pointer is DE ; SENDM: LD A,(DE) ; get byte OR A ; Zero? RET Z ; Yes, done CALL OUTT ; Send it INC DE ; Pointer JR SENDM ; Next ; ; Get HL and DE from console ; Check that DE is larger than HL ; RDHLDE: CALL HHLDE RDHLD2: LD A, E ; E - L SUB L LD A,D ; D - H SBC A,H JR C,ERR ; HL bigger RET ; ;Input HL and DE ; HHLDE: CALL READHL ; HL JR C,ERR ; Only one address EX DE,HL CALL READHL EX DE,HL RET ; ;Input HL from console buffer ; READHL: PUSH DE PUSH BC ; save regs LD HL,0000 ; clear HL ; ; PAGE 1-7 ; RDHL1: CALL GETCH ; Get char JR C,RDHL5 ; No chars left CP ' ' ; Space? JR Z,RDHL1 ; Yes, get another char JR RDHL3 RDHL2: CALL GETCH ; Get char JR C,RDHL5 ; Line end RDHL3: CALL NIB ; Convert to binary JR C,RDHL4 ; not HEX ADD HL,HL ; Shift left ADD HL,HL ; four ADD HL,HL ; bytes ADD HL,HL OR L ; Add new char LD L, A JR RDHL2 ; Next ' ; ; Check for apostrophe or blank at end ; RDHL4: CP APOS ; Apostrophe? JR Z,RDHL5 ; 1 ;;; CP LOW(' '-'38) ; asm80 had problems CP 0F0H ; equivalent JR NZ,ERR ; Nat blank RDHL5: POP BC POP DE ; Restore RET ; Convert ASCII chars to binary NIB: SUB '0' ; ASCII bias RET C ;;; CP 'F'-'B'+1 ; asm80 had problems CP 17H ; equivalent CCF ; Invert RET C ; Error, >F CP 10 CCF ; Invert RET NC ; Number 0-9 ;;; SUB 'A'-'9'-1 ; asm80 had problems SUB 7 ; equivalent CP 10 ; Remove :- RET ; Letter A-F ; ; PAGE 1-8 ; ; Print on a proper input ERR: LD A,'?' CALL OUTT JP WARM ; Try again ; ; Start new line, give address ; CRHL: CALL CRLF ; New line ; ; Print HL as 4 hex digits ; OUTHL: LD C,H CALL OUTHX ; H OUTLL: LD C,L ; Output hex byte ; from C and a space OUTHEX: CALL OUTHX ; ; Output a space ; OUTSP: LD A,' ' JP OUTT ; ; Output a hex byte from C ; binary to ASCII conversion ; OUTHX: LD A,C ; Save original binary value RRA ; Move high RRA ; nibble RRA ; to RRA ; low nibble CALL HEX1 ; Upper char LD A,C ; Lower char HEX1: AND 0FH ; Take 4 bits ADD A,90H ; ; PAGE 1-9 ; DAA ; adjusts to packed BCD ADC A,40H ; > DAA ; adjusts to packed BCD JP OUTT ; ; Increment HL and ; check for end HL minus DE ; TSTOP: PUSH HL LD A,E SUB L ; E - L LD L,A LD A,D SUB H ; D - H OR L POP HL INC HL RET NZ ; Not done POP HL ; Raise stack RET ; ; Copy byte from B to memory ; and see that it got there ; CHEKM: LD (HL),B ; Put in mem LD A,(HL) CP B ; Same? RET Z ERRB: LD DE,MEMERR CALL SENDM CALL OUTHL ; Pointer JP WARM MEMERR: DEFB "Mem - ",00H HLDEBC: CALL HLDECK ; Range JP C, ERR ; No byte PUSH HL le180h: CALL READHL ; 3rd input LD B,H ; Move to BC LD C,L POP HL RET ; ; Get 2 addresses, check that ; additional data follows ; HLDECK: CALL HHLDE ; 2 addr JP C,ERR ; no more JP RDHLD2 ; check ; ; Print register in binary ; BITS: LD B,8 ; 8 bits BIT2: SLA L ; Shift L left ;; LD A,'0'/2 ; Half of 0 ASM80 fail LD A,18H ; Half of 0 ADC A,A ; Double carry CALL OUTT ; Print bit DJNZ BIT2 ; B times RET ; ; Uti1ity subroutines ; No comments ; DECIN: LD C,00H DBIN2: CALL GETCH JP C, ERR CP ' ' ; 20 JR Z,DBIN2 DBIN1: SUB '0' ; 30 JR C,DBIN4 CP LF JP NC,ERR LD D,A LD A,C ADD A,A LD C,A ADD A,A ADD A,A ADD A,C ADD A,D LD C,A CALL GETCH ; ; PAGE 1-11 ; JR C,DBIN5 JR DBIN1 DBIN4: ;;; CP LOW ('-'0') AND 0FFH ; asm80 has problems CP 0F0H ; equivalent JP NZ,ERR DBIN5: LD A,C RET DELAY: PUSH BC DEL1: LD BC,DPARM LOOP: DEC BC LD A,B OR C JP NZ,LOOP NOP NOP NOP NOP DEC HL LD A,H OR L JP NZ, DEL1 POP BC RET MSINON: .if version_char = ASCII_M DB CTRL_Z .endif ; DB CR,LF DB 'Z80 System Monitor ' DB '3.1/' ; .if version_char = ASCII_M DB version_char .endif ; .if version_char = ASCII_S DB version_char .endif ; DB CR,LF,LF DB ' RAM Top : ' DB 0 ; ; PAGE 1-12 ; ; Continuation of cold start ; INIT: IN A,(EPORT) ; Turn off Power on Jump XOR A ; Load A with zero OUT (UART2S),A ; Turn off tape motor relay LD (FLAG) ,A ; Turn off printer output LD A,20H ; Default disk configuration ; 3.5" drive A Double density ; deselect all drives OUT (DCONF),A ; Set up FDC-1 card ; .if version_char = ASCII_M LD DE,DMON ; Start of DMON LD HL,RAMST ; Start of RAM .endif ; .if version_char = ASCII_S LD DE, RDHL1-1 ; ; db 0xa1, 0xf5, 0x00 and c push af nop .endif ; FIND: LD A,(HL) ; Load first (next) byte of RAM CPL ; Complement it LD (HL),A ; Write to RAM (cospieiented) CP (HL) ; See if write was successful JR NZ,TOPT ; Jump to "Found Top" if not CPL ; Otherwise leave it as it was LD (HL),A ; Put it back as we found it INC HL ; Next location to test LD A,E ; See if we SUB L ; have reached LD A,D ; DMON SBC A,H ; EPROM yet JR NC,FIND ; Go back if not TOPT: ; Found Top (of RAM) LD SP,HL ; Set stack to very top of RAM LD DE,MSINON ; Sign on Message CALL SENDM ; Send it DEC HL ; Address of top byte of RAM CALL OUTHL CALL CON3 ; ; Warm-start entry ; WARM: LD SP,T00F0 LD HL,WARM ; Return here PUSH HL CALL CRLF ; New line CALL INPLN ; Get command line CALL GETCH ; First char RET C CP 'S' ; 53 JP Z,SET CP 'D' ; 44 JP Z, DISK CP 'M' ; 4D JP Z,MEM CP 'G' ; 47 JP Z,GO CP 'B' ; 42 JP Z,BOOT CP 'P' ; 50 JP Z,PORT ; .if version_char = ASCII_S cp 'K' ;e268 jp z,CMD_K ;e26a .endif ; JP ERR ; ; Set parameters ; SET: CALL GETCH RET C CP 'D' JP Z,SDISK CP 'P' JP NZ,ERR CALL READHL LD A,L LD (UARTSP),A CALL READHL LD A,L LD (CONFIG),A CALL DECIN LD (ADDSPT),A CALL DECIN LD (B0052),A CALL DECIN LD (WPCTRK),A RET ; ; SDISK: CALL DECIN CP 04H JP NC,ERR LD (DRIVNO),A CALL DECIN LD (TRAKNO),A CALL DECIN JP C,ERR LD HL,T0052 DEC A CP (HL) JP NC,ERR INC A LD (SECTNO),A CALL READHL LD (DMAADD),HL RET ; ; Routine to "Go" anywhere in memory ; All register are loaded beforehand ; GO: LD A,(IBUFC) OR A JP Z, ERR CALL READHL JP (HL) ; ; Input from any Port ; PORT: CALL READHL ; Port LD C,L ; Port No to C JP Z,OPORT IN L,(C) CALL OUTLL ; Hex value JP BITS ; ; Output byte to Port ; OPORT: CALL READHL ; Port OUT (C),L RET MEM: ; no comments CALL GETCH RET C CP 'D' JP Z,DISP CP 'L' JP Z,LOAD CP 'M' JP Z,MOVE CP 'F' JP Z,FILL CP 'S' JP Z,SEARCH JP ERR ; ; Load HEX or ASCII char into memory ; from console. Check: to see if ; the data actually got there ; Apostrophe precedes ASCII char ; Carriage return passes over location ; LOAD: CALL READHL ; Address LOAD2: CALL OUTHL ; Print it CALL PASCI ; ASCII CALL OUTSP LD C,(HL) ; Orig Byte CALL OUTHEX ; HEX PUSH HL ; Save pointer CALL INPLN2 ; Input CALL READHL ; Byte LD B,L ; to B POP HL CP APOS JR Z,LOAD6 ; ASCII input LD A,C ; How many? OR A ; None? JR Z,LOAD3 ; Yes LOAD4: CALL CHEKM ; Into memory LOAD3: INC HL JR LOAD2 ; ; Load ASCII character ; LOAD6: ; No comments CALL GETCH LD B, A JR LOAD4 ; ; Fill a portion of memory ; FILL: CALL HLDEBC ; Range, byte CP APOS JR Z,FILL4 ; ASCII LD B,C FILL2: CALL CHEKM ; Put, check CALL TSTOP ; Done? JR FILL2 ; Next FILL4: CALL GETCH ; ASCII char LD B,A JR FILL2 ; ; Move a block of memory HL - DE to BC ; MOVE: CALL HLDEBC ; 3 addr MOVDN: CALL MOVIN ; Move/check CALL TSTOP ; Done? INC BC ; No JR MOVDN MOVIN: LD A,(HL) ; Byte LD (BC),A ; New location LD A,(BC) ; Check CP (HL) ; its it there? RET Z LD H,B ; Error LD L,C ; Into HL JP ERRB ; Show bad ; Display memory in hexadecimal and ASCII DISP: CALL RDHLDE ; Range DISP2: CALL CRHL ; New line DISP3: LD C,(HL) ; Get byte CALL OUTHX ; Print CALL OUTSP INC HL ; Pointer LD A,L AND LEND ; Line end? JR Z,DISP4 ; Yes ASCII AND 03H ; Space CALL Z,OUTSP JR DISP3 ; Next hex DISP4: CALL OUTSP PUSH DE LD DE,-XXFFF8 ; Reset line ADD HL, DE POP DE DISP5: CALL PASCI ; ASCII dump CALL TSTOP ; Done? LD A,L ; No AND LEND ; Line End? JR NZ,DISP5 ; No JR DISP2 ; ; Display Memory byte in ASCII if ; possible, otherwise give decimal point ; PASCI: LD A,(HL) ; Get byte CP DEL ; High bit on? JR NC,PASC2 ; Yes CP ' ' ; Control char? JR NC,PASC3 ; No PASC2: LD A,'.' ; Change to dot PASC3: JP OUTT ; Send ; ; Search memory for one or two bytes ; SEARCH: CALL HLDEBC ; Range, 1st byte LD B,CR ; Set for 1 byte JR C,SEAR3 ; Only one PUSH HL CALL READHL ; 2nd byte LD B,L ; Into B POP HL SEAR3: LD A,(HL) ; Get byte CP C ; Match? JR NZ,SEAR4 ; No LD A,B ; Only one? CP CR JR Z,SEAR5 ; Yes ; ; Found first match, check for second ; INC HL LD A,(HL) ; Next byte DEC HL CP B ; Match? JR NZ,SEAR4 ; No SEAR5: PUSH BC ; A match CALL CRHL ; Show address POP BC SEAR4: CALL TSTOP ; Done? JR SEAR3 ; No ; .if version_char = ASCII_S CMD_K: ld de,MSINON2 ; Sign on Message 2 call SENDM jr past_MSINON2 ; MSINON2: .db "Connect to Remote Computer", CR, LF, 0 past_MSINON2: ; xor a ;e3eb ld (UARTSP),a ;e3ec ld hl,le180h ;e3ef le3f2h: in a,(XXN02) ;e3f2 and 040h ;e3f4 jp z,le40eh ;e3f6 ld a,(UARTSP) ;e3f9 or a ;e3fc jp z,le408h ;e3fd call sub_e438h ;e400 ld (hl),a ;e403 inc hl ;e404 jp le40bh ;e405 le408h: call sub_e438h ;e408 le40bh: call CONOUT ;e40b le40eh: call CONST ;e40e jp z,le3f2h ;e411 call CONIN ;e414 cp EOT jp z,handle_EOT cp SOH jp z,handle_SOH cp ESC jp z,handle_ESC ; push af ;e426 call sub_e430h ;e427 pop af ;e42a out (N03),a ;e42b jp le3f2h ;e42d ; sub_e430h: in a,(XXN02) ;e430 and 080h ;e432 jp z,sub_e430h ;e434 ret ;e437 ; sub_e438h: in a,(N03) ;e438 and 07fh ;e43a ret ;e43c ; handle_SOH: ld a,001h ;e43d ld (UARTSP),a ;e43f call 0e4deh ;e442 ld hl,00100h ;e445 jp le3f2h ;e448 ; handle_EOT: ld hl,00100h ;e44b call 0e4deh ;e44e le451h: call sub_e46fh ;e451 jr c,le451h ;e454 ld e,010h ;e456 le458h: call sub_e477h ;e458 jp c,le451h ;e45b ld (hl),a ;e45e inc hl ;e45f dec e ;e460 jp nz,le458h ;e461 le464h: call sub_e4aah ;e464 cp 00dh ;e467 jp nz,le464h ;e469 jp le451h ;e46c sub_e46fh: call sub_e477h ;e46f ret c ;e472 call sub_e477h ;e473 ret ;e476 sub_e477h: call sub_e488h ;e477 ret c ;e47a and 00fh ;e47b rlca ;e47d rlca ;e47e rlca ;e47f rlca ;e480 ld b,a ;e481 call sub_e488h ;e482 ret c ;e485 or b ;e486 ret ;e487 sub_e488h: call sub_e4aah ;e488 cp 020h ;e48b jp z,sub_e488h ;e48d cp 00dh ;e490 jp z,sub_e488h ;e492 cp 00ah ;e495 jp z,sub_e488h ;e497 sbc a,030h ;e49a ret c ;e49c cp 017h ;e49d ccf ;e49f ret c ;e4a0 cp 00ah ;e4a1 ccf ;e4a3 ret nc ;e4a4 sub 007h ;e4a5 cp 00ah ;e4a7 ret ;e4a9 sub_e4aah: call CONST ;e4aa call nz,CONIN ;e4ad cp 01bh ;e4b0 jp z,handle_ESC ;e4b2 in a,(XXN02) ;e4b5 and 040h ;e4b7 jp z,sub_e4aah ;e4b9 call sub_e438h ;e4bc call CONOUT ;e4bf ret ;e4c2 handle_ESC: ld de,0e4d6h ;e4c3 call SENDM ;e4c6 call OUTHL ;e4c9 call CRLF ;e4cc xor a ;e4cf or d ;e4d0 call nz,0c3fdh ;e4d1 ld sp,hl ;e4d4 jp po,0aa0dh ;e4d5 adc a,0ffh ;e4d8 ld e,b ;e4da ld d,h ;e4db ld a,(0cd00h) ;e4dc jr nc,$-26 ;e4df ld a,00dh ;e4e1 out (N03),a ;e4e3 ret ;e4e5 BOOT: ld a,060h ;e4e6 out (085h),a ;e4e8 ld hl,003e8h ;e4ea call DELAY ;e4ed ld c,000h ;e4f0 ld b,00ah ;e4f2 le4f4h: push bc ;e4f4 ld a,040h ;e4f5 or c ;e4f7 out (085h),a ;e4f8 ld a,05bh ;e4fa out (080h),a ;e4fc le4feh: in a,(084h) ;e4fe and 001h ;e500 jp z,le4feh ;e502 le505h: in a,(080h) ;e505 and 082h ;e507 xor 002h ;e509 jr nz,le505h ;e50b ld a,00fh ;e50d out (080h),a ;e50f le511h: in a,(084h) ;e511 and 001h ;e513 jr z,le511h ;e515 in a,(080h) ;e517 and 01ch ;e519 xor 004h ;e51b jp nz,le55fh ;e51d ld a,001h ;e520 out (082h),a ;e522 ld l,001h ;e524 ld e,001h ;e526 ld a,08ch ;e528 out (080h),a ;e52a ld c,084h ;e52c le52eh: in a,(c) ;e52e jr z,le52eh ;e530 in a,(083h) ;e532 jp p,le55fh ;e534 ld h,a ;e537 ld d,a ;e538 le539h: in a,(c) ;e539 jr z,le539h ;e53b in a,(083h) ;e53d jp p,le54dh ;e53f le542h: ld (hl),a ;e542 inc hl ;e543 in a,(c) ;e544 jr z,le539h ;e546 in a,(083h) ;e548 jp m,le542h ;e54a le54dh: in a,(080h) ;e54d and 09ch ;e54f jp nz,le55fh ;e551 pop bc ;e554 in a,(085h) ;e555 and 0c0h ;e557 or c ;e559 ld c,a ;e55a out (085h),a ;e55b ex de,hl ;e55d jp (hl) ;e55e le55fh: pop bc ;e55f ld a,004h ;e560 add a,c ;e562 and 00fh ;e563 ld c,a ;e565 jp nz,le4f4h ;e566 dec b ;e569 jp nz,le4f4h ;e56a ld a,020h ;e56d out (085h),a ;e56f jp DMON ;e571 ld hl,CDATA ;e574 jp DELAY ;e577 DISK: call GETCH ;e57a ret c ;e57d ld (COMMAND),a ;e57e call DECIN ;e581 ld (B005A),a ;e584 ld a,(COMMAND) ;e587 ld e,001h ;e58a cp 052h ;e58c jr z,le597h ;e58e ld e,000h ;e590 cp 057h ;e592 jp nz,ERR ;e594 le597h: ld a,(DRIVNO) ;e597 ld c,a ;e59a ld a,(CONFIG) ;e59b and 0ech ;e59e or c ;e5a0 ld c,a ;e5a1 ld a,(TRAKNO) ;e5a2 ld b,a ;e5a5 ld a,(SECTNO) ;e5a6 ld d,a ;e5a9 ld hl,ADDSPT ;e5aa dec a ;e5ad cp (hl) ;e5ae jr c,le5b8h ;e5af inc a ;e5b1 sub (hl) ;e5b2 ld d,a ;e5b3 ld a,c ;e5b4 or 010h ;e5b5 ld c,a ;e5b7 le5b8h: ld h,00ah ;e5b8 le5bah: push hl ;e5ba ld hl,(DMAADD) ;e5bb call sub_e62fh ;e5be ld (IBUFCX),hl ;e5c1 pop hl ;e5c4 or a ;e5c5 jp z,le5d2h ;e5c6 cp 003h ;e5c9 jr z,le5f8h ;e5cb dec h ;e5cd jr nz,le5bah ;e5ce jr le5f8h ;e5d0 le5d2h: ld hl,(IBUFCX) ;e5d2 ld (DMAADD),hl ;e5d5 ld a,(SECTNO) ;e5d8 ld hl,B0052 ;e5db cp (hl) ;e5de jp c,le5ebh ;e5df ld a,(TRAKNO) ;e5e2 inc a ;e5e5 ld (TRAKNO),a ;e5e6 ld a,000h ;e5e9 le5ebh: inc a ;e5eb ld (SECTNO),a ;e5ec ld a,(B005A) ;e5ef dec a ;e5f2 ld (B005A),a ;e5f3 jr nz,le597h ;e5f6 le5f8h: push af ;e5f8 ld de,le61ch ;e5f9 call SENDM ;e5fc pop af ;e5ff ld c,a ;e600 call OUTHEX ;e601 ld hl,DRIVNO ;e604 ld b,003h ;e607 le609h: ld c,(hl) ;e609 push hl ;e60a push bc ;e60b call OUTHEX ;e60c pop bc ;e60f pop hl ;e610 inc hl ;e611 dec b ;e612 jr nz,le609h ;e613 ld hl,(DMAADD) ;e615 call OUTHL ;e618 ret ;e61b le61ch: jr nz,$+71 ;e61c jr nz,$+34 ;e61e ld b,h ;e620 jr nz,le643h ;e621 ld d,h ;e623 jr nz,$+34 ;e624 ld d,e ;e626 jr nz,le66ah ;e627 ld h,h ;e629 ld h,h ;e62a ld (hl),d ;e62b dec c ;e62c ld a,(bc) ;e62d nop ;e62e sub_e62fh: push hl ;e62f ld a,010h ;e630 and c ;e632 jr z,le637h ;e633 ld a,002h ;e635 le637h: ld h,a ;e637 ld a,e ;e638 and 001h ;e639 jr z,le641h ;e63b ld a,088h ;e63d jr le643h ;e63f le641h: ld a,0a8h ;e641 le643h: or h ;e643 ld (FDCCMD),a ;e644 ld a,c ;e647 and 00fh ;e648 ld h,a ;e64a ld a,e ;e64b and 0c0h ;e64c or h ;e64e ld h,a ;e64f ld a,e ;e650 and 001h ;e651 ld a,h ;e653 jr nz,le664h ;e654 and 004h ;e656 ld a,h ;e658 jr nz,le664h ;e659 ld a,(WPCTRK) ;e65b cp b ;e65e ld a,h ;e65f jr nc,le664h ;e660 or 010h ;e662 le664h: ld (DRVCMD),a ;e664 push de ;e667 push bc ;e668 di ;e669 le66ah: in a,(085h) ;e66a and 010h ;e66c jr z,le684h ;e66e ld a,020h ;e670 out (085h),a ;e672 ld de,DPARM3 ;e674 le677h: call sub_e7c7h ;e677 dec de ;e67a ld a,d ;e67b or e ;e67c jr nz,le677h ;e67d le67fh: ld a,0ffh ;e67f ld (DRIVE),a ;e681 le684h: ld a,(DRIVE) ;e684 ld b,a ;e687 ld a,(DRVCMD) ;e688 out (085h),a ;e68b and 003h ;e68d ld (DRIVE),a ;e68f cp b ;e692 jr z,le6b0h ;e693 ld h,00ah ;e695 le697h: ld e,0dch ;e697 le699h: call sub_e7c7h ;e699 dec e ;e69c jr nz,le699h ;e69d call sub_e7a8h ;e69f and 080h ;e6a2 jr z,le6abh ;e6a4 dec h ;e6a6 jr nz,le697h ;e6a7 jr le67fh ;e6a9 le6abh: call sub_e758h ;e6ab jr nz,le6f0h ;e6ae le6b0h: pop bc ;e6b0 pop de ;e6b1 pop hl ;e6b2 ld a,e ;e6b3 and 001h ;e6b4 jr nz,le6c1h ;e6b6 call sub_e7a8h ;e6b8 and 040h ;e6bb ld a,003h ;e6bd jr nz,le73ah ;e6bf le6c1h: push hl ;e6c1 push de ;e6c2 push bc ;e6c3 ld a,c ;e6c4 and 0e0h ;e6c5 rlca ;e6c7 rlca ;e6c8 ld e,a ;e6c9 ld a,b ;e6ca or a ;e6cb jr nz,le6d5h ;e6cc call sub_e77ch ;e6ce and 004h ;e6d1 jr z,le6f0h ;e6d3 le6d5h: in a,(081h) ;e6d5 cp b ;e6d7 jr z,le703h ;e6d8 ld a,b ;e6da out (083h),a ;e6db ld a,018h ;e6dd call sub_e77eh ;e6df call sub_e758h ;e6e2 jr nz,le6ech ;e6e5 cp b ;e6e7 jr z,le703h ;e6e8 jr le6fch ;e6ea le6ech: ld a,038h ;e6ec jr le6f2h ;e6ee le6f0h: ld a,000h ;e6f0 le6f2h: ld e,003h ;e6f2 call sub_e77eh ;e6f4 ld a,0ffh ;e6f7 ld (DRIVE),a ;e6f9 le6fch: ld a,002h ;e6fc pop bc ;e6fe pop de ;e6ff pop hl ;e700 jr le73ah ;e701 le703h: pop bc ;e703 pop de ;e704 pop hl ;e705 push de ;e706 push bc ;e707 ld a,d ;e708 out (082h),a ;e709 push hl ;e70b ld a,e ;e70c and 001h ;e70d ld a,(FDCCMD) ;e70f jr z,le73dh ;e712 out (080h),a ;e714 ld c,084h ;e716 le718h: in d,(c) ;e718 jr z,le718h ;e71a in a,(083h) ;e71c jp p,le72ch ;e71e le721h: ld (hl),a ;e721 inc hl ;e722 in d,(c) ;e723 jr z,le718h ;e725 in a,(083h) ;e727 jp m,le721h ;e729 le72ch: call sub_e7b2h ;e72c jr nz,le737h ;e72f pop bc ;e731 pop bc ;e732 pop de ;e733 inc d ;e734 jr le73ah ;e735 le737h: pop hl ;e737 pop bc ;e738 pop de ;e739 le73ah: or a ;e73a ei ;e73b ret ;e73c le73dh: out (080h),a ;e73d ld c,084h ;e73f ld a,(hl) ;e741 le742h: in d,(c) ;e742 jr z,le742h ;e744 out (083h),a ;e746 jp p,le756h ;e748 le74bh: inc hl ;e74b ld a,(hl) ;e74c in d,(c) ;e74d jr z,le742h ;e74f out (083h),a ;e751 jp m,le74bh ;e753 le756h: jr le72ch ;e756 sub_e758h: ld h,00ah ;e758 ld a,0c4h ;e75a le75ch: out (080h),a ;e75c ld c,084h ;e75e le760h: in d,(c) ;e760 jr z,le760h ;e762 in a,(083h) ;e764 jp m,le760h ;e766 call sub_e7b2h ;e769 jr nz,le773h ;e76c in a,(082h) ;e76e out (081h),a ;e770 ret ;e772 le773h: dec h ;e773 jr z,le77ah ;e774 ld a,0c0h ;e776 jr le75ch ;e778 le77ah: or a ;e77a ret ;e77b sub_e77ch: ld a,008h ;e77c sub_e77eh: or e ;e77e jp p,le790h ;e77f and 01bh ;e782 push af ;e784 ld a,(DRVCMD) ;e785 xor 008h ;e788 out (085h),a ;e78a call sub_e7c7h ;e78c pop af ;e78f le790h: out (080h),a ;e790 call sub_e7c7h ;e792 le795h: in a,(084h) ;e795 and 001h ;e797 jr z,le795h ;e799 ld a,(DRVCMD) ;e79b out (085h),a ;e79e ld h,00ah ;e7a0 le7a2h: call sub_e7c7h ;e7a2 dec h ;e7a5 jr nz,le7a2h ;e7a6 sub_e7a8h: ld a,0d0h ;e7a8 out (080h),a ;e7aa call sub_e7c7h ;e7ac in a,(080h) ;e7af ret ;e7b1 sub_e7b2h: in a,(080h) ;e7b2 ld (STATUS),a ;e7b4 and 094h ;e7b7 ld a,002h ;e7b9 ret nz ;e7bb ld a,(STATUS) ;e7bc and 008h ;e7bf ld a,001h ;e7c1 ret nz ;e7c3 ld a,000h ;e7c4 ret ;e7c6 sub_e7c7h: push bc ;e7c7 ld bc,DPARM ;e7c8 le7cbh: dec bc ;e7cb ld a,b ;e7cc or c ;e7cd jp nz,le7cbh ;e7ce pop bc ;e7d1 ret ;e7d2 CONIN_S: ;.if version_char = ASCII_S ;CONIN_S: ;.endif CON1: CALL CONST ; test keyboard status jr z,CON1 ;e7d6 CON3: ; maybe? CONIN: in a,(001h) ;e7d8 and 07fh ;e7da ret ;e7dc CONST: in a,(000h) ;e7dd and 040h ;e7df ret z ;e7e1 ld a,0ffh ;e7e2 ret ;e7e4 CONOUT: push af ;e7e5 OUT4: in a,(000h) ;e7e6 and 080h ;e7e8 jp z,OUT2 ;e7ea pop af ;e7ed out (001h),a ;e7ee ret ;e7f0 nop ;e7f1 rst 38h ;e7f2 rst 38h ;e7f3 rst 38h ;e7f4 rst 38h ;e7f5 rst 38h ;e7f6 rst 38h ;e7f7 rst 38h ;e7f8 rst 38h ;e7f9 rst 38h ;e7fa rst 38h ;e7fb rst 38h ;e7fc rst 38h ;e7fd rst 38h ;e7fe rst 38h ;e7ff .endif ; ; ; .if version_char = ASCII_M ; ; Bootstrap Loader ; to suit Interak FDC-1 ; BOOT: LD A,60H ; motors on, deselect all OUT (DCONF),A ; select drive 0, motors, LD HL,1000 CALL DELAY ; wait 1 second LD C,00H ; first try 3.5" DD LD B,10 ; try up to 10 times BTRY: PUSH BC LD A,040H OR C OUT (DCONF) ,A ; select drive B, etc LD A,05BH ; step in, force status OUT (DSTAT),A DON0: IN A,(DPOLL) AND 01H JP Z,DON0 DON1: IN A,(DSTAT) ; get status AND 82H ; index pulse, ready? XOR 02H JR NZ,DON1 LD A,0FH ; reset, head load, verify OUT (DSTAT),A RST1: IN A,(DPOLL) ; done? AND 01H JR Z,RST1 IN A,(DSTAT) ; get status AND 1CH XOR 04H ; track 0? JP NZ,BTERR LD A,01H ; sector number OUT (DSECT),A ; to sector register LD L,01H ; low byte of load address LD E,01H ; low byte of go address LD A,08CH ; read sector command OUT (DSTAT),A LD C,DPOLL RDST: IN A,(C) ; poll port address JR Z,RDST IN A,(DDATA) ; get first byte JP P,BTERR LD H,A LD D,A BTLP: IN A,(C) ; poll JR Z,BTLP IN A,(DDATA) ; get data JP P,BRDEND BTLP3: LD (HL),A ; data to memory INC HL IN A,(C) ; poll JR Z,BTLP IN A,(DDATA) ; get data JP M,BTLP3 BRDEND: IN A,(DSTAT) ; get status AND 09CH JP NZ,BTERR ; EXEC POP BC IN A,(DCONF) AND 0C0H ; pass on config OR C ; to system loader LD C,A OUT (DCONF),A EX DE,HL ; start address to HL ; ; PAGE 1-20 ; JP (HL) ; go to it BTERR: POP BC LD A,04H ; try next config ADD A,C AND 0FH LD C,A JP NZ,BTRY DEC B ; tried 10 times? JP NZ,BTRY LD A,20H ; yes, give up OUT (DCONF),A JP DMON LD HL,T0001 JP DELAY ; ; Disk access by Monitor - ; DISK: CALL GETCH RET C LD (COMMAND),A CALL DECIN LD (B005A),A LD A,(COMMAND) ; Get command LD E,01H CP 'R' JR Z,LDP0 LD E,00H CP 'W' JP NZ,ERR LDP0: LD A,(DRIVNO) ; Drive No LD C, A LD A,(CONFIG) ; Configuration AND 0ECH OR C LD C, A ; Combined with drive no LD A,(TRAKNO) ; Track Number LD B,A LD A,(SECTNO) ; Sector Number LD D, A LD HL, ADDSPT ; Addr of Sectors per track DEC A CP (HL) ; ; PAGE 1-21 ; JR C,LDP2 ; Sector on Side 1? INC A SUB (HL) LD D, A LD A,C OR 010H ; Side = 1 LD C,A LDP2: LD H,10 ; Try up to 10 times TRY: PUSH HL LD HL,(DMAADD) ; DMA addr CALL DISKCMD LD (IBUFCX),HL POP HL OR A JP Z,EMESS CP 03H ; Write protected? JR Z,EXT DEC H JR NZ,TRY JR EXT EMESS: LD HL,(IBUFCX) LD (DMAADD),HL LD A,(SECTNO) LD HL,T0052 CP (HL) JP C,ON LD A,(TRAKNO) INC A LD (TRAKNO),A LD A,00H ON: INC A LD (SECTNO),A LD A,(B005A) DEC A LD (B005A),A JR NZ,LDP0 EXT: PUSH AF LD DE,MSTATS CALL SENDM POP AF ; ; PAGE 1-22 ; LD C,A CALL OUTHEX LD HL,DRIVNO LD B,N03 RE4E5: LD C,(HL) PUSH HL PUSH BC CALL OUTHEX POP BC POP HL INC HL DEC B JR NZ,RE4E5 LD HL,(DMAADD) CALL OUTHL RET MSTATS: DB ' E D T S Addr' DB CR,LF,0 ; ; Disk access subroutine for Interak ; FDC-1 disk controller card ; ; On entry: ; B = Track No ; C = Unit number etc R R X S 8 S N N ; D = Sector number ; E = 0 for write, ; 1 for read + D M 0 0 0 0 0 0 ; HL= DMA address ; On exit: ; A = 0 for successful operation ; 1 CRC error in Data/ID field ; 2 Select error ; 3 Disk is write protected ; HL updated to next available addr ; D updated to next sector number ; B,C,E preserved ; DISKCMD: PUSH HL LD A,010H AND C ; Side 1? JR Z,DSK1 LD A,02H ; Side = 1 DSK1: LD H,A ; Save LD A,E AND 01H ; Read or Write? JR Z,DSK2 LD A,N88 ; Read command JR DSK3 DSK2: LD A,NA8 ; Write command DSK3: OR H ; Combine with side LD (FDCCMD),A ; Save command LD A,C AND 0FH ; Remove side and step rate LD H,A ; Save LD A,E AND 0C0H ; Motors, lock doors OR H LD H, A LD A,E AND 01H ; Read command? LD A,H JR NZ,DSK4 AND 04H ; Double density? LD A,H JR NZ,DSK4 LD A,(WPCTRK) ; Yes CP B ; Track > WPCTRK? LD A,H JR NC,DSK4 OR 010H ; Precomp on DSK4: LD (DRVCMD) ,A ; Save comand PUSH DE PUSH BC DI ; Disable Interrupts ; ; Routine to select drive ; IN A,(DCONF) ; Motors running? AND 010H ; ; PAGE 1-24 ; JR Z, DONE LD A,20H ; Motors on deselect all OUT (DCONF),A LD DE,DPARM3 WAIT: CALL WAIT1 DEC DE LD A,D OR E JR NZ,WAIT AGAIN: LD A,0FFH LD (DRIVE),A DONE: LD A,(DRIVE) LD B, A LD A,(DRVCMD) OUT (DCONF),A ; Select Drive AND 03H LD (DRIVE),A CP B ; Same as previous access JR Z,SELEXT ; Yes LD H,10 ; Try ten revolutions INDX: LD E,DPARM2 ILOOP: CALL WAIT1 ; Wait 220 ms DEC E JR NZ,ILOOP CALL GETST AND 80H ; Ready? JR Z, GETTRK DEC H JR NZ,INDX JR AGAIN GETTRK: CALL AREAD JR NZ,SEKERR SELEXT: POP BC POP DE POP HL LD A,E ; Avoid write permit check AND 01H ; if not a write command JR NZ,DSK5 CALL GETST ; Get status ; ; PAGE 1-25 ; AND 040H ; Isolate write protect flag LD A,03H ; Preset error code JR NZ,DSKEX ; Exit with error if set DSK5: PUSH HL PUSH DE PUSH BC LD A,C ; Isolate stepping rate AND 0E0H ; Mask off RLCA RLCA LD E,A ; Save in E register LD A,B ; Get track required OR A JR NZ,SEEKTR CALL RESET AND 04H ; Arrived at track 0? JR Z,SEKERR ; ; Routine to seek track ; SEEKTR: IN A,(DTRACK) ; Get current track CP B ; Is it the one we want? JR Z,FOUND ; Yes LD A,B ; Set required track number OUT (DDATA),A ; Put in data register LD A,18H ; Seek, head load CALL STEP CALL AREAD JR NZ,STPERR CP B JR Z, FOUND JR SKERR3 STPERR: LD A,38H ; Single step JR SKERR2 SEKERR: LD A,00H ; Reset, lift head SKERR2: LD E,03H ; Default step rate CALL STEP LD A,0FFH LD (DRIVE),A SKERR3: LD A,02H ; Preset error code ; fails to seek POP BC POP DE POP HL JR DSKEX FOUND: POP BC POP DE POP HL PUSH DE PUSH BC LD A,D OUT (DSECT),A ; Sector no to FDC PUSH HL ; Save HL in case of mis-read LD A,E AND 01H LD A,(FDCCMD) ; Get command JR Z,WRITE ; ; Routine to read a disk sector ; OUT (DSTAT),A ; Output to FDC LD C,DPOLL ; Poll Port RDLP: IN D,(C) JR Z,RDLP IN A,(DDATA) JP P,RDEND ; INTQ occurred RDLP3: LD (HL),A ; Save in memory INC HL IN D,(C) JR Z,RDLP IN A,(DDATA) ; Get data JP M,RDLP3 RDEND: CALL ERRCHK JR NZ,DERR POP BC ; Get rid of saved HL POP BC POP DE INC D ; Update sector nuiber JR DSKEX ; Return with ACC=0 ; (i.e. no error) DERR: POP HL ; Restore HL POP BC POP DE DSKEX: OR A EI ; Re-enable interrupts RET ; ; Routine to write a disk sector ; WRITE: OUT (DSTAT),A ; Output to FDC LD C,DPOLL ; Poll port LD A,(HL) ; Pre-load Acc fron memory WRLP: IN D, (C) JR Z, WRLP OUT (DDATA),A ; Data to FDC JP P,WREND WRLP3: INC HL LD A,(HL) ; Get next data byte IN D,(C) JR Z,WRLP OUT (DDATA),A JP m,WRLP3 WREND: JR RDEND ; ; Subroutine to read a track address ; Return with track number in A ; AREAD: LD H,LF LD A,0C4H ARD1: OUT (DSTAT),A ; Output to FDC LD C,DPOLL ; Poll port ARDLP: IN D,(C) JR Z,ARDLP IN A,(DDATA) ; Get data JP M,ARDLP CALL ERRCHK JR NZ,ARDERR IN A,(DSECT) ; Get track number OUT (DTRACK),A ; Put into track register RET ARDERR: DEC H JR Z,ARDEX LD A,0C0H JR ARD1 ARDEX: OR A RET ; ; Subroutine to reset drive RESET: LD A,08H ; Reset, head load ; ; Subroutine to step to some track ; STEP: OR E JP P,STEP1 ; Use alternative rate? AND 1BH PUSH AF LD A,(DRVCMD) XOR BS OUT (DCONF),A CALL WAIT1 POP AF STEP1: OUT (DSTAT),A ; Comand to FDC CALL WAIT1 STEP2: IN A,(DPOLL) AND 01H ; Done? JR Z,STEP2 LD A,(DRVCMD) ; Reinstate OUT (DCONF),A LD H,10 STEP3: CALL WAIT1 DEC H JR NZ,STEP3 GETST: LD A,0D0H OUT (DSTAT),A CALL WAIT1 IN A,(DSTAT) RET ERRCHK: IN A,(DSTAT) LD (STATUS),A AND 094H LD A,02 ; Preset error code RET NZ LD A,(STATUS) AND 08H LD A,01H ; Preset error code RET NZ LD A,00H RET WAIT1: PUSH BC LD BC,DPARM SLOOP: DEC BC LD A,B OR C JP NZ,SLOOP POP BC RET CONST: IN A,(KBPORT) ; input from keyboard port ADD A,80H ; test strobe bit JR C,STRB1 ; jump if strobe is 1 to STRB1 XOR A ; otherwise zero everything RET ; and return (no key pressed) STRB1: LD (KSAVE),A ; Save value of key (7 bit ASCII) IN A,(KBPORT) ; input from keyboard again ADD A,80H ; test strobe bit again JR C,STRB1 ; wait for strobe to go away LD A,0FFH ; A= 0FF means data valid RET ; return if key pressed CON1: CALL CONST ; test keyboard status CONIN: LD A,(KSAVE) ; Get latest key pressed OR A ; see if it is zero ie no key JR Z,CON1 ; go back to look again CON3: ; ; PAGE 1-30 ; PUSH AF ; Save A XOR A ; Load A with zero LD (KSAVE),A ; wipe the keydata store to zero POP AF ; Restore A RET ; and return OUT4: POP AF CONOUT: PUSH HL ; User defined console output PUSH BC PUSH DE CP CTRL_Z JP Z,CLRSCR LD HL,(CURPOS) PUSH AF LD A,(EFLAG) AND A JP NZ,ESCSEQ POP AF CP DEL ; DEL JR Z,BACKSP CP ' ' ; Space JP P,CHAR CP CR ; CR JR Z,CRETN CP LF ; LF JR Z,LFEED CP VT ; VT JR Z,UPLINE CP BS ; BS JR Z,BACKSP CP FFEED ; Non-destructive JR Z,CURSRT CP HT ; TAB JR Z,TAB ; CP ESC ; ESC JP Z,ESCAP CP RS ; HOME JP Z,CURHOM ; ; Ignore all other control characters ; POP DE POP BC POP HL ; ; PAGE 1-31 ; RET CHAR: AND 07FH LD (HL),A LD A,(IFLAG) OR (HL) LD (HL),A LD A,L AND '?' ; 3F CP '?' ; 3F JR Z,NEWLN INC HL SETCUR: LD A,(HL) XOR 80H ; Toggle the high bit LD (HL),A LD (CURPOS),HL POP DE ; Restore DE POP BC ; BC POP HL ; HL RET ; and return NEWLN: LD A,L AND 0C0H ; Zero low-order bits LD L,A JR LFEED2 CLRCUR: PUSH AF LD A,(HL) XOR 80H LD (HL),A POP AF RET BACKSP: CALL CLRCUR DEC HL JR SETCUR TAB: LD (HL),' ' INC HL LD A,L AND 007H JR NZ,TAB JR SETCUR CRETN: ; ; PAGE 1-32 ; CALL CLRCUR LD A,L AND 0C0H LD L,A JR SETCUR LFEED: CALL CLRCUR LFEED2: LD DE, COLS ADD HL, DE LD A,H CP NF6 JR C,SETCUR LD HL,VDUST+COLS LD DE,VDUST LD BC,ROWS*COLS LDIR LD HL,TF5C0 JR SETCUR UPLINE: CALL CLRCUR LD DE,TFFC0 ADD HL, DE JR SETCUR CURSRT: CALL CLRCUR INC HL JR SETCUR CLRSCR: LD HL,VDUST LD DE,VDUST+1 LD BC,ROWS*COLS+COLS ; (ROWS+1)*COLS LD (HL),' ' LDIR XOR A LD (EFLAG),A LD (IFLAG),A LD HL,VDUST JR SETCUR CURHOM: CALL CLRCUR LD HL,VDUST JR SETCUR ESCAP: LD A,01H ESCEX: LD (EFLAG),A POP DE POP BC POP HL RET ESCSEQ: CP 1 JR Z, LETT CP 2 JR Z, CPOS1 ; CPOS CALL CLRCUR LD HL,VDUST SUB 20H ; Calc Row no JR Z, RPOSN LD DE,COLS CPLOOP: ADD HL,DE DEC A JR NZ,CPLOOP RPOSN: LD (EFLAG),A POP AF ; Set col code SUB 20H ; Calc col no LD D,0 LD E,A ADD HL,DE JP SETCUR CPOS1: POP AF JR ESCEX ; Save Row no LETT: XOR A LD (EFLAG),A POP AF ; POS CP '=' JR NZ,ION LD A,2 JR ESCEX ION: CP '3' JR NZ,IOFF LD A,80H ION2: LD (IFLAG),A ION3: XOR A JR ESCEX IOFF: CP '4' JR NZ,IGNOR XOR A JR ION2 IGNOR: JR ION3 ; Ignore others ; ; PROBABLY JUNK TO END OF PROG DB 0,0,0E5H,0C3H,0ADH,09H,031H LASTBY: DB 0AFH .endif .END