..Z80 ORG 0 L0000: JP COLD JP MESG JP HOME JP RDHST JP WRTHST JP DISCIO JP RDIO JP WRIO JP BTERM DW ROMDATX COLD: IM 0 LD SP,L0000 LD IY,ROMDATY CALL IUSART ;INITIALIZE USARTS LD DE,SIGNON ;SIGNON MESSAGE CALL L01B1 ;PRINT MESSAGE CALL ROMTST ;ROM CRC CHECK CALL BUFCHK ;MOV CODE TO HIGH MEMORY CALL RAMTST ;POST MOVE CRC CALL LFC00 ;CALL RELOC CODE WARM: LD DE,BOOTMSG ;BOOTMSG CALL MESG ;PRINT MESSAGE L0041: CALL CINY ;GET CHAR FROM CRT CP 0DH ;IS IT A CARRIAGE RETURN JR NZ,L0041 ;LOOP IF NOT LD DE,CRLF ;CR LF MESSAGE CALL MESG ;PRINT TO CRT JP BOOTCPM ;READ IN CPM MEMERR: CALL MESG LD DE,RERR CALL MESG HALT IUSART: LD A,80H OUT (0FDH),A OUT (0FFH),A OUT (0FDH),A OUT (0FFH),A LD A,40H OUT (0FDH),A OUT (0FFH),A LD A,0CEH OUT (0FDH),A OUT (0FFH),A LD A,37H OUT (0FDH),A OUT (0FFH),A RET CRLF: DB 0DH,0AH,0 L007B: DB ':',0A0H,0,0C5H,0F6H,4 ROMTST: ;ROM CRC LD HL,L0000 LD BC,07FDH CALL CHKSUM LD DE,ROMMSG JR NZ,MEMERR RET RAMTST: ;RAM CRC ON RELOC CODE LD HL,LFC00 LD BC,03F8H CALL CHKSUM LD DE,RAMBAD JR NZ,MEMERR RET CHKSUM: XOR A PUSH AF CHK: POP AF XOR (HL) INC HL DEC BC PUSH AF LD A,B OR C JR NZ,CHK POP AF RET BUFCHK: LD HL,L00C4 LD DE,LFC00 LD BC,0B2H LDIR LD BC,PLOP PUSH DE POP HL INC DE LD (HL),0FFH LDIR LD (HL),1FH RET L00C4: IN A,(0F6H) LD A,(L0000) CP 0C3H OUT (0F6H),A JR NZ,MTEST JP WARM MTEST: LD DE,TSTMSG CALL MESG IN A,(0F6H) LD HL,L0000 LD BC,0FBFFH CALL 0FC31H OR A OUT (0F6H),A LD DE,RAMBAD JP NZ,MEMERR LD DE,ROMOK CALL MESG JP WARM LD (0FCB2H),HL LD HL,0FC84H L00FB: LD D,(HL) INC HL BIT 7,(HL) JR NZ,L0119 LD E,(HL) BIT 6,E RES 6,E INC HL PUSH HL JR Z,L010F CALL 0FC57H JR L0116 L010F: LD IX,0FC77H CALL 0FC5BH L0116: POP HL JR L00FB L0119: XOR A RET LD IX,0FC79H LD HL,(0FCB2H) LD A,E ADD A,L LD L,A LD A,H ADC A,0 LD H,A CALL 0FC75H INC HL INC HL INC HL LD A,B CP H RET C JR NZ,0129H LD A,C CP L RET C JR 0129H JP (IX) LD (HL),D RET LD A,(HL) CP D JR NZ,0142H RET POP AF POP AF POP AF LD A,0FFH RET RST 38H NOP NOP LD BC,02FFH NOP LD B,C RST 38H LD B,D RST 38H LD B,B NOP NOP RST 38H LD BC,0200H NOP LD B,D NOP LD B,B RST 38H LD B,C XOR D NOP LD D,L LD (BC),A XOR D LD BC,41AAH LD D,L LD BC,40AAH LD D,L NOP LD D,L LD B,D LD D,L LD B,C LD D,L LD B,B NOP ADD A,B BOOTCPM: LD HL,ROMDATX LD DE,0FF00H LD BC,42H LDIR LD IX,0FF00H LD IY,0FF1FH CALL L0433 CALL DISCIO LD A,(IX+07H) OR A JP Z,LFE00 BTERM: LD DE,BTERR JP MEMERR CRTOUT: IN A,(0FDH) BIT 0,A JR Z,CRTOUT LD A,C OUT (0FCH),A RET CRTIN: IN A,(0FDH) BIT 1,A JR Z,CRTIN IN A,(0FCH) AND 7FH RET L01B1: LD B,32H L01B3: LD A,0AH CALL L01C3 DJNZ L01B3 MESG: LD A,(DE) OR A RET Z CALL L01C3 INC DE JR MESG L01C3: LD C,A PUSH DE PUSH HL LD L,(IY+16H) LD H,(IY+17H) CALL CNTJP POP HL POP DE RET CNTJP: JP (HL) RDHST: LD HL,RDIO LD (IX+0AH),L ;ADD IO ADDTRSS TO RAMDATX TABLE LD (IX+0BH),H LD C,6 ;6 FOR READ JR IOHST ;DISK READ WRITE ROUTINE WRTHST: LD HL,WRIO LD (IX+0AH),L LD (IX+0BH),H LD C,5 IOHST: LD A,(IX+00H) ;LOAD HSTDSK IN ACC CALL GDSK ;GET MTAB ADDRESSIN HL INC HL ;INCREMENT TO DISKDEF1 ENTRY LD A,(HL) ;GET DSKDEF1 IN ACC AND 40H ;MASK TO CHECK FOR DOUBLE SIDED OR C ;OR TO 5 FOR WRITE OR 6 FOR READ LD (IX+16H),A ;STORE INTO CMDBUF(0) LD (IX+15H),9 ;CMDCNT HAD 9 BYTES LD A,18H ;MSK OUT SECTOR SIZE BITS IN AND (HL) ;DSKDEF1 RRCA ;AND SHIFT TO 2 LSB RRCA RRCA LD (IX+1BH),A ;STORE SECTOR SIZE IN CMDBUF(5) LD B,128 LD DE,128 ;120 BYTE SECTORS? CP 0 JR Z,L0220 ;JUMP IF 128 LD B,0FFH ;B IS FF FOR 256, 512 AND 1024 BYTE SEC LD DE,0 ;DE IS 0 FOR 256 BYTE SEC CP 1 JR Z,L0220 ;JUMP IF 256 LD D,1 ;DE IS 1 FOR 512 SEC CP 2 JR Z,L0220 ;JUMP IF 512 LD D,3 ;ELSE 3E IS 3 FOR 1024 SEC (DEFAULT) L0220: LD (IX+1EH),B ;CMDBUF(7) IS 128 FOR 128 SEC ;AND FF FOR ALL OTHERS BIT 7,(IX+0DH) ;IS SEC SIZE > 128 JR NZ,L022F ;JUMP IF YES LD (IX+0CH),E ;ELSE STORE 0 FOR 256, 1 FOR 512 LD (IX+0DH),D ;AND 3 FOR 1024 IN RAMDATX SECSIZ L022F: XOR A ;ZERO ACC BIT 2,(HL) ;CHECK DSKDEF1 FOR DOUBLE SIDED LD B,(IX+01H) ;LOAD B WITH TRACK LD C,(IX+02H) ;C IS SECTOR JR Z,L023D ;JUMP IF SINGLE SIDED RR B ;ELSE, DIVIDE TRACK BY 2 RLA ;IF TRACK WAS ODD, CARRY WAS SET IN ;DIVIDE. ROTATE THAT INTO ACC L023D: LD (IX+19H),A ;STORE ODD/EVEN IN CMDBUF(3) RLCA ;X 4 RLCA LD (IX+09H),A ;STORE IN PHYSHD LD (IX+08H),B ;STOR TRACK IN PHYSTRK LD (IX+18H),B ;AND AT CMDBUF(2) LD (IX+1AH),C ;STORE SECTOR IN CMDBUF(4) LD A,3 ;MASK DSKDEF1 DRIVE BITS AND (HL) OR (IX+09H) ;OR WITH PHYSHD LD (IX+17H),A ;STOR IT IN CMDBUF(1) LD DE,5 ;GET EOT SECTOR ADD HL,DE LD A,(HL) LD (IX+1CH),A ;STORE IN CMDBUF(6) INC HL ;GET GPL BYTE LD A,(HL) ;STOR IN CMDBUF(7) LD (IX+1DH),A DISCIO: LD B,(IX+04H) ;GET NUMBER OF RETRYS LD DE,0300H ;????????????????????????? L026A: PUSH BC ;SAVE REGS PUSH DE LD A,8 ; CALL L0435 ;SEEK TRACK AND WAIT FOR HEAD TO SETTLE CALL L0309 PUSH IY CALL STRTI0 CALL L02FD POP IY LD B,7 PUSH IX POP HL LD DE,0EH ADD HL,DE L0287: CALL INFDC INI JR NZ,L0287 POP DE POP BC LD A,(IX+0EH) AND '@' JR Z,L02C4 CALL ECODE LD A,1 CP C JR Z,L02B4 LD A,6 CP C CALL Z,CNT LD A,2 CP C CALL Z,L0430 INC E LD A,0BH CP B CALL Z,L042C DJNZ L026A L02B4: LD A,(IX+07H) CP 0FFH JR Z,L02C5 CALL L0317 JR C,L02C5 OR A JP NZ,DISCIO L02C4: LD C,A L02C5: LD (IX+07H),C RET STRTI0: LD C,0FBH PUSH IX POP HL LD DE,15H ADD HL,DE LD B,(HL) INC HL CALL RDY STATLP: CALL OUTFDC OUTI JR NZ,STATLP LD B,(IX+0CH) LD E,(IX+0DH) RES 7,E LD D,(IX+03H) DEC D LD L,(IX+0AH) LD H,(IX+0BH) PUSH HL POP IY LD L,(IX+05H) LD H,(IX+06H) RET L02FA: BIT 7,A RET NZ L02FD: IN A,(0FAH) BIT 5,A JR Z,L02FA PUSH DE LD DE,L0000 JP (IY) L0309: LD HL,05CFH PUSH DE LD D,0 SRA E ADD HL,DE POP DE LD A,(HL) OUT (0F7H),A RET L0317: LD A,C RLCA LD E,A LD D,0 LD HL,0614H ADD HL,DE LD E,(HL) INC HL LD D,(HL) PUSH BC PUSH DE LD DE,DMESG CALL MESG LD A,'A' ADD A,(IX+00H) CALL L01C3 LD DE,L007B CALL MESG POP DE CALL MESG CALL ERSP POP BC RET VIRTM: CALL MESG PLOP: CALL CINY ;GET TERM INPUT CHAR CP 0DH ;IS IT A CR JR NZ,PLOP ;LOOP IF NOT LD DE,CRLF ;ELSE PUT OUT CRLF JP MESG ERSP: LD DE,RESM ;OUTPUT RETRY MESSAGE CALL MESG ERLP: CALL CINY ;GET RESPONSE AND 0DFH ;CONVERT TO UPPER CASE LD E,A CP 'A' ;IS IT AN 'A' SCF ;SET CARRY FLAG JR Z,ERET ;JUMP IF ABORT CP 'R' ;IS IT AN 'R' JR Z,ERET ;JUMP TO RETRY SUB 'I' ;IS IT AN 'I' JR NZ,ERLP ;JMP TO IGNORE ROUTINE ERET: PUSH AF LD A,E CALL L01C3 LD DE,CRLF CALL MESG POP AF RET CINY: PUSH HL ;SAVE HL LD L,(IY+18H) ;GET CNIN PTR FROM RAMDATY LD H,(IY+19H) CALL CNTJP ;DO INDIRECT CALL POP HL ;RESTORE HL RET RLOOP1: AND 20H JR Z,EXDN IN A,(0FAH) CP 0F0H JR Z,RDSC DEC DE LD A,E OR D JR Z,L03C0 RDIO: IN A,(0FAH) CP 0F0H JR NZ,RLOOP1 RDSC: INI POP DE PUSH DE LD A,E OR D JR NZ,RLOOP2 DEC B RLOOP2: EI HALT IN A,(0FAH) AND ' ' JR Z,EXDN INI JR NZ,RLOOP2 DEC E JP P,039DH POP DE DEC D PUSH DE JP P,039DH EI HALT IN A,(0F8H) INI EXDN: POP DE RET L03C0: LD A,8 OUT (0F7H),A L03C4: IN A,(0F5H) IN A,(0FAH) BIT 5,A JR NZ,L03C4 JR EXDN WLOOP1: AND ' ' JR Z,EXDN IN A,(0FAH) CP 0B0H JR Z,WRSC DEC DE LD A,E OR D JR Z,L03C0 WRIO: IN A,(0FAH) CP 0B0H JR NZ,WLOOP1 WRSC: OUTI POP DE PUSH DE LD A,E OR D JR NZ,WLOOP2 DEC B WLOOP2: EI HALT IN A,(0FAH) AND ' ' JR Z,EXDN OUTI JR NZ,WLOOP2 DEC E JP P,03E7H POP DE DEC D PUSH DE JP P,03E7H EI HALT IN A,(0F8H) OUTI POP DE RET CNT: DEC E DEC D RET NZ LD B,1 RET HOME: BIT 1,(IY+0BH) JR NZ,L041A RES 0,(IY+0BH) L041A: LD A,(IX+00H) PUSH AF LD A,(IY+00H) LD (IX+00H),A CALL L0433 POP AF LD (IX+00H),A RET L042C: LD E,0 JR L0433 L0430: CALL CNT L0433: LD A,0 L0435: PUSH BC ; PUSH DE LD C,A ;SAVE A IN C (8 CODE ROME READ ROUTINE) LD A,(IX+00H) ;LOAD ACC WITH DRIVE PUSH AF ;SAVE DRIVE CALL GDSK ;GET START OF MTAB (FOR DRIVE 0) LD A,(HL) ;GET DSKDEF0 AND 7 ;MASK MOTOR CONTROL BITS LD E,A ;STORE MOTOR CONTRO IN E INC HL ;INCREMENT POINTER TO DSKDEF1 POP AF ;GET DRIVE BACK IN ACC CP (IY+11H) ;IS IT THE SAME ASS CURRENT DSK JR Z,L0465 ;JUMP IF DRIVE SAME LD (IY+11H),A ;ELSE STORE NEW DRIVE BIT 7,(HL) ;IS IT A VIRTUAL DRIVE PUSH BC ;SAVE CODE JR Z,L0461 ;IF VIRTUAL JUMP CP (IY+13H) ;ELSE COMPARE TO VIRTUAL DRIVE LD (IY+13H),A ;UPDATE VIRTUAL DRIVE PUSH AF ;SAVE EVERYTHING PUSH DE PUSH HL CALL NZ,VIRT ;PRINT EXCHANGE DISK MESSAGE POP HL POP DE POP AF L0461: CALL SPECIFY ;SPECIFY SRT/HUT AND HLT/ND POP BC L0465: BIT 6,(HL) ;HL POINTS TO DSKDEF1. SINGLE OR DOUBLE SIDED JR Z,L0478 ;JUMP IF SINGLE LD A,19 ;LOAD ACC WITH 19 TRACKS BIT 5,(HL) ;CHECK FOR 40 OR 80 TRACKS JR Z,L0471 ;JUMP IF 40 LD A,39 ;LOAD ACC WITH 39 TRACKS L0471: CP (IX+08H) ;COMPARE TO PRESENT TRACK JR NC,L0478 ;JUMP IF TRACK GREATER THAN MAX SET 3,E ;UPDATE MOTOR CONTROL BYTE L0478: LD A,7 ;LOAD ACC WITH 7 OUT (0F7H),A ;TURN ON MOTOR????????? IN A,(0F5H) AND 7 LD D,A AND E PUSH AF LD A,D OR E OUT (0F8H),A LD (IY+12H),A CALL L04C9 ;GET CURRENT TRACK FROM MTAB IN D LD A,(IX+08H) ;GET PHYSICAL TRACK IN A BIT 3,C ; JR Z,L0497 CP D JR Z,L049D L0497: CALL SEEK ;DO DRIVE SEEK OR HOME POP AF SCF PUSH AF L049D: POP AF INC HL ;INC HL TO MOTOR WAIT TIME CALL WAIT ;WAIT FOR HEAD TO SETTLE POP DE POP BC RET VIRT: INC A ;INCREMENT DRIVE NUMBER SET 6,A ;SET BIT 6 TO MAKE IT TO ASCII LD E,(IY+0FH) ;LOAD DE WITH VIRT DRIVE DRIVE PTR LD D,(IY+10H) LD (DE),A ;STORE ASCII DRIVE IN MESSAGE LD E,(IY+0DH) ;GET MESSAGE PTR LD D,(IY+0EH) JP VIRTM ;OUTPUT MESSAGE GDSK: PUSH IY POP HL ;GET RAMDATY INTO HL LD DE,1AH ADD HL,DE ;GET START OF MTAB LD D,A ;MULTIPLY DRIVE NUM BY 9 RLCA RLCA RLCA ADD A,D LD E,A ; LD D,0 ADD HL,DE ;ADD TO MTAB START TO GET CORRECT ;ENTRY FOR THE DRIVE RET L04C9: PUSH HL ;SAVE HL - IT POINTS TO DSKDEF1 LD DE,7 ;OFFSET OF 7 TO CURRENT TRACK ADD HL,DE LD D,(HL) ;LOAD CURRENT TRACK IN D POP HL RET WAIT: LD B,(IY+12H) ;LOAD B WITH PHYS DISK LD C,0F8H ;LOAD C WITH PORT NUMBER LD D,(HL) ;LOAD D WITH MOTOR WAIT TIME LD E,0 ;LOAD E WITH 0 INC HL ;INCREMENT TO HEAD SETTLE TIME JR NC,L0504 ;JUMP IF CARRY NOT SET IM 2 ;SET INT MODE 2 LD A,0 ;SET INT MASK LD I,A JR NZ,L04F0 ;JUMP IF NOT 0 EI ;ENABLE INTERUPTS L04E5: DEC DE ;DECREMENT MOTOR WAIT TIME LD A,D ;CHECK IF IT IS 0 OR E JR Z,L04F2 ;JUMP IF TIME OUT LD C,0F8H ;ELSE LOAD C WITH PORT # OUT (C),B ;OUTPUT THE PYYS DISK JR L04E5 ;JUMP TO LOOP L04F0: LD D,(HL) ;IF ZERO LOAD D WITH HEAD SETTLE TIME EI ;ENABLE INTERUPTS L04F2: OUT (C),B ;OUTPUT PHYS DRIVE TO PORT F8 JR L04F2 ;ENDLESS LOOP WAITING FOR INTERUPT IM 0 ;RESET TO INTERUPT MODE 0 INC SP ;INCREMENT STACK POINTER TWICE INC SP CALL SINTR ;CHECK FDC INTERUPT STATUS LD A,D ; CP (HL) ;CHECK WAIT TIME JR NC,L0505 ;JUMP IF NOT ENOUGH LD D,(HL) ;RELOAD WAIT IME IN D JR L0505 ;JUMP L0504: RET NZ L0505: OUT (C),B ;LOOP UNTIL HEAD SETTLE DONE OUT (C),B NOP DEC DE LD A,D OR E JP NZ,L0505 RET RDY: IN A,(0FAH) ;WAIT FOR FDC TO NOT BUSY BIT 4,A JR NZ,RDY RET OUTFDC: IN A,(0FAH) ;WAIT FOR FDC TO BE READY FOR WRITE AND 0C0H CP 80H JR NZ,OUTFDC RET INFDC: IN A,(0FAH) AND 0C0H CP 0C0H JR NZ,INFDC RET SEEK: CALL OUTFDC ;WAIT FOR FDC NOT BUSY LD A,7 ;SEEK OR RECAL (HOME) OR C OUT (0FBH),A ;LOAD FDC CALL OUTFDC ;WAIT LD A,3 ;ADD DRIVE BITS AND (HL) BIT 3,C JR Z,HDO ;JUMP IF RECAL OR (IX+09H) ;ELSE ADD HEAD HDO: OUT (0FBH),A ;OUTPUT TO FDC BIT 3,C ;RETURN IF RECAL RET Z CALL OUTFDC ;ELSE WAIT FOR FDC READY LD A,(IX+08H) ;LOAD ACC WITH PHYS TRACK OUT (0FBH),A ;AND OUTPUT IT RET SPECIFY: PUSH HL ;SAVE HL - POIINTS TO DSKDEF1 INC HL INC HL INC HL ;INCREMENT TO FDC BYTES CALL OUTFDC ;WAIT FOR FDC LD A,3 ;SEND FDC 3 CODE FOR SPECIFY OUT (0FBH),A LD BC,02FBH ;SET UP FOR INDIRECT PORTS SPLP: CALL OUTFDC ;WAIT FOR FDC OUTI ;OUTPUT TO FDC SRT/HUT AND HLT/ND JR NZ,SPLP POP HL ;SESET HL TO DSKDEF1 RET SINT: CALL OUTFDC ;WAIT FOR FDC LD A,8 ;SEND OUT INT STATUS CODE OUT (0FBH),A CALL INFDC ;WAIT FOR RESPONSE IN A,(0FBH) ;GET IT IN ACC CALL INFDC ;WAIT FOR NEXT BYTE IN A,(0FBH) ;READ IT ALSO INTO ACC RET SINTR: CALL SINT ;CHECK FDC INT STATUS PUSH HL PUSH DE LD DE,5 ADD HL,DE LD (HL),A POP DE POP HL RET ECODE: LD C,1 BIT 1,(IX+0FH) RET NZ INC C BIT 1,(IX+10H) RET NZ BIT 4,(IX+10H) RET NZ INC C BIT 5,(IX+10H) RET NZ INC C BIT 5,(IX+0FH) RET NZ INC C BIT 7,(IX+0FH) RET NZ BIT 2,(IX+0FH) RET NZ BIT 0,(IX+0FH) RET NZ BIT 6,(IX+10H) RET NZ BIT 0,(IX+10H) RET NZ INC C BIT 3,(IX+0EH) RET NZ INC C BIT 4,(IX+0FH) RET NZ INC C BIT 4,(IX+0EH) RET NZ INC C RET DB 8,9,7,0AH,6 ROMDATX: DB 0,0,1,1,14H,0,0FEH DB 0,0,0,93H L05CF: DB 3,0,0,0,0,0,0,0,0 DB 0,9,'F',0,0,0,1,3,5,1CH,0FFH ROMDATY: DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0FFH,0,0,0,0,9CH,1,0A6H DB 1,1,0D8H,'X',5,'o',3,5,1CH,0FFH DB '5',6,'(',6,'F',6,'F',6,'R' DB 6,'h',6,']',6,'h',6,'y',6 DB 'Wrong track',0AEH,0,'Write ' DB 'protected',0AEH,0,'Data error' DB 0AEH,0,'Not found',0AEH,0,'Lost ' DB 'data',0AEH,0,'Drive not ready' DB 0AEH,0,'Unknown error',0AEH,0 DMESG: DB 0DH,0AH,'Disk error on drive' DB 0A0H,0 RESM: DB 0DH,0AH,'Type R to try again, ' DB 'A to abort, or I to ignore:' DB 0A0H,0 BTERR: DB 0AH,'Error on CP/M system diskette.' DB 0 RERR: DB 0DH,0AH,'Push reset to try ' DB 'again.',0A0H,0 SIGNON: DB 0DH,'Micro-Decision -- ROM ' DB 'Rev. 1.3',0DH,0AH,'Copyright ' DB '1982 Morrow Designs, Inc.' DB 0DH,0AH,0AH,0 TSTMSG: DB 'Testing memory -- please stand ' DB 'by: ',0 ROMOK: DB 'Memory O.K.',0DH,0AH,0AH,0 BOOTMSG: DB 'Insert CP/M system diskette ' DB 'in Drive A and press [RETURN] ' DB 7,0 RAMBAD: DB 7,7,'RAM Memory error',0 ROMMSG: DB 7,7,'ROM Memory error',0,0FFH DB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH DB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH DB 0FFH,13H,0FFH,0FFH END