;; KC compact disc interface uses a patched AMSDOS ROM ;; ;; Differences: ;; - Read data (C666) has been patched to support double sided discs. ;; bit 2 = side, bit 1,0 = drive ;; ;; - |CPM has been patched to recognise Microdos format and to boot Microdos discs. ;; ;; - step rate has been speeded up ;; ;; - CR,LF message has had CR,LF swapped around. No effect. ;; ;; - Two chars ":" and ";" in invalid chars for filename have been swapped. No effect. ;; ;; - Supports 4 "drives", drives 2 and 3 are ram discs. ;; ;; - If drive 2 or 3 are selected, then it stops auto detect. Then when disc motor is turned on/off it actually ;; stores data to ram. Implements a kind of ram disc. ;; ;; The following are the changed data.. All other data is the same ;; |CPM function ;; CP/M function "boot" ;;--------------------------------------------------------------------- ;; Original AMSDOS rom c1b2 cd12b9 call $b912 ; firmware function: HI: KL CURR SELECTION c1b5 4f ld c,a c1b6 21dcc1 ld hl,$c1dc c1b9 c316bd jp $bd16 ; firmware function: MC START PROGRAM ;;--------------------------------------------------------------------- ;; KC Compact disc ROM ;; C1B7, B8 are different c1b2 cd12b9 call &b912 ; firmware function: HI: KL CURR SELECTION c1b5 4f ld c,a c1b6 2184dd ld hl,&dd84 c1b9 c316bd jp &bd16 ; firmware function: MC START PROGRAM ;;--------------------------------------------------------------------- ;; Original AMSDOS rom c4ef ff rst $38 ;; unused ;; setup XDPB c4f0 79 ld a,c c4f1 fe02 cp $02 ;;--------------------------------------------------------------------- ;; KC Compact disc ROM c4ef 38 ;; unused ;; setup XDPB c4f0 c30cdc jp $dc0c ;;--------------------------------------------------------------------- ;; Original AMSDOS ROM ;; Displaying a directory entry ;; display file size d598 210c00 ld hl,$000c ;;--------------------------------------------------------------------- ;; KC Compact disc ROM c598 c306dc jp &dc06 ;;------------------------------------------------------------------------- ;; Original AMSDOS ROM ;; default BIOS: SETUP DISC parameters c5d4: defw &0032 ;; motor on time in 20ms units defw &00fa ;; motor off time in 20ms units defb &af ;; write off time in 10ms units defb &0f ;; head settle time in 1ms units defb &0c ;; step rate in 1ms units defb &01 ;; head unload delay defb &03 ;; head load delay and dma flag ;;------------------------------------------------------------------------- ;; KC Compact ROM ;; ;; Step rate is quicker than for CPC ;; default BIOS: SETUP DISC parameters c5d4: defw &0032 ;; motor on time in 20ms units defw &00fa ;; motor off time in 20ms units defb &af ;; write off time in 10ms units defb &0f ;; head settle time in 1ms units defb &04 ;; step rate in 1ms units defb &01 ;; head unload delay defb &03 ;; head load delay and dma flag ;;---------------------------------------------------- ;; Original AMSDOS ROM c666 cd76c9 call $c976 ;; spin up motor c669 3e66 ld a,$66 ;; read data (mfm, skip) c66b 0610 ld b,$10 c66d 2262be ld ($be62),hl ;;---------------------------------------------------- ;; KC Compact ROM ;; E = drive/side ;; bit 2 = side ;; bit 1,0 = drive c666 3e66 ld a,&66 c668 cd76c9 call &c976 ;; spin up motor c66b 0610 ld b,&10 c66d c303dc jp &dc03 ;; read data patched to read double sided discs ;;---------------------------------------------------- ;; Original AMSDOS ROM ;; enabling motor or not... c976 2276be ld ($be76),hl ;;---------------------------------------------------- ;; KC Compact ROM ;; if you don't enable motor or not c976 c309dc jp &dc09 ;;------------------------------------------------- ;; Original AMSDOS ROM ;; In get address of XDPB ca64 2a42be ld hl,($be42) ; HL = XDPB for drive 0 ;;------------------------------------------------- ;; KC Compact ROM ca64 c300dc jp &dc00 ;;------------------------------------------------- ;; Original AMSDOS ROM cb86 0d dec c cb87 0a ld a,(bc) cb88 ff rst &38 ;;------------------------------------------------- ;; KC Compact ROM ;; ;; CR,LF have been reversed cb86 0a ld a,(bc) cb87 0d dec c cb88 ff rst &38 ;;------------------------------------------------- ;; Original AMSDOS ROM ;; table of invalid characters for filename dbb2 defb '<' defb '>' defb '.' defb ',' defb ';' defb ':' defb '=' defb '[' defb ']' defb '_' defb '%' defb '|' defb '(' defb ')' defb '/' defb '\' defb &7f defb 0 ;;------------------------------------------------- ;; KC Compact ROM ;; : and ; are swapped in table ;; table of invalid characters dbb2 defb '<' defb '>' defb '.' defb ',' defb ':' defb ';' defb '=' defb '[' defb ']' defb '_' defb '%' defb '|' defb '(' defb ')' defb '/' defb '\' defb &7f defb 0 ;;------------------------------------------------- ;; Original AMSDOS ROM ;; &dc00-&dfff all filled with &ff ;;------------------------------------------------- ;; KC Compact disc ROM ;; called in get address of XDPB dc00 c30fdc jp &dc0f ;; read data patched to allow reading of double sided discs dc03 c321dc jp &dc21 ;; called when displaying a directory dc06 c399dc jp &dc99 dc09 c3abdc jp &dcab dc0c c3f2dc jp &dcf2 ;;--------------------------------------------------------- ;; expanded disc param block for drive B? dc0f 6f ld l,a dc10 7b ld a,e dc11 d601 sub &01 dc13 7d ld a,l dc14 2a42be ld hl,(&be42) dc17 114000 ld de,&0040 dc1a 3801 jr c,&dc1d dc1c 19 add hl,de dc1d 5f ld e,a dc1e 19 add hl,de dc1f d1 pop de dc20 c9 ret ;;--------------------------------------------------------- ;; called in read data ;; H = command byte dc21 2262be ld (&be62),hl dc24 67 ld h,a dc25 69 ld l,c dc26 2274be ld (&be74),hl dc29 48 ld c,b dc2a 2130dc ld hl,&dc30 dc2d c3ffc6 jp &c6ff ;; execute function with retry ;; function to call dc30 2a74be ld hl,(&be74) dc33 017efb ld bc,&fb7e dc36 7c ld a,h ;; command byte dc37 cd5cc9 call &c95c ;; fdc send command byte dc3a 7d ld a,l dc3b e63f and &3f dc3d 6f ld l,a dc3e 3e10 ld a,&10 ;; XDPB: sectors/track dc40 cd5cca call &ca5c ;; get XDPB parameter by index dc43 bd cp l dc44 2e00 ld l,&00 dc46 3003 jr nc,&dc4b dc48 cbd3 set 2,e ;; side 2 dc4a 6f ld l,a dc4b 3a74be ld a,(&be74) dc4e 95 sub l dc4f 6f ld l,a dc50 7b ld a,e ;; drive/side dc51 cd5cc9 call &c95c ;; fdc send command byte dc54 7c ld a,h dc55 fe4d cp &4d ;; format dc57 2019 jr nz,&dc72 dc59 cb93 res 2,e ;; side 0 dc5b 3e14 ld a,&14 ;; N sector size dc5d cd59c9 call &c959 ;; write XDPB parameter to FDC dc60 3e10 ld a,&10 ;; sectors/track dc62 cd59c9 call &c959 ;; write XDPB parameter to FDC dc65 3e12 ld a,&12 ;; gap length for format dc67 cd59c9 call &c959 ;; write XDPB parameter to FDC dc6a 3e13 ld a,&13 ;; filler byte dc6c cd5cca call &ca5c ;; get XPDB parameter by index dc6f c3c1c6 jp &c6c1 ;; send last byte and then transfer execution phase dc72 7a ld a,d ;; C dc73 cd5cc9 call &c95c ;; fdc send command byte ;; H dc76 7b ld a,e dc77 e604 and &04 ;; take bit 2 of drive/side specified and transfer into bit 0 dc79 cb3f srl a dc7b cb3f srl a dc7d cd5cc9 call &c95c ;; fdc send command byte dc80 cb93 res 2,e dc82 7d ld a,l ;; R dc83 cd5cc9 call &c95c ;; fdc send command byte dc86 3e14 ld a,&14 ;; sector size dc88 cd59c9 call &c959 ;; write XDPB parameter to FDC dc8b 7d ld a,l ;; EOT dc8c cd5cc9 call &c95c ;; fdc send command byte dc8f 3e11 ld a,&11 ;; gap length read/write dc91 cd59c9 call &c959 ;; write XDPB parameter to FDC dc94 3eff ld a,&ff ;; data length dc96 c3c1c6 jp &c6c1 ;; send last byte and then transfer execution phase ;;--------------------------------------------------------- dc99 1152dd ld de,&dd52 ;; data format dc9c fec0 cp &c0 dc9e 2803 jr z,&dca3 dca0 116bdd ld de,&dd6b ;; other format dca3 011900 ld bc,&0019 dca6 eb ex de,hl dca7 edb0 ldir dca9 37 scf dcaa c9 ret ;;--------------------------------------------------------- dcab 2276be ld (&be76),hl dcae f5 push af dcaf 3e18 ld a,&18 ;; auto select dcb1 cd5cca call &ca5c ;; get XDPB parameter by index dcb4 fe01 cp &01 dcb6 cabddc jp z,&dcbd ;; signal to not detect format? dcb9 f1 pop af dcba c379c9 jp &c979 ;; standard motor control ;; do not detect format is signalled ;; HL = address of buffer for read/write ;; A = command byte to execute dcbd f1 pop af dcbe e5 push hl dcbf d5 push de dcc0 c5 push bc dcc1 47 ld b,a dcc2 3e13 ld a,&13 ;; filler byte dcc4 cd5cca call &ca5c ;; get XDPB parameter by index dcc7 82 add a,d ;; ? dcc8 cb21 sla c dcca 51 ld d,c dccb 1e00 ld e,&00 dccd 21003e ld hl,&3e00 dcd0 19 add hl,de dcd1 f3 di ;; A = organization to use dcd2 cd5bbd call &bd5b ;; KL BANK SWITCH dcd5 f5 push af ;; store previous organization dcd6 ed5b76be ld de,(&be76) ;; buffer for sector read/write dcda 78 ld a,b dcdb fe66 cp &66 ;; read data? dcdd 2801 jr z,&dce0 dcdf eb ex de,hl dce0 010002 ld bc,&0200 dce3 edb0 ldir dce5 f1 pop af ;; A = organization to use dce6 cd5bbd call &bd5b ;; KL BANK SWITCH dce9 fb ei dcea c1 pop bc dceb d1 pop de dcec e1 pop hl dced f1 pop af dcee 3e00 ld a,&00 dcf0 37 scf dcf1 c9 ret ;;--------------------------------------------------------- ;; C = drive ;; ;; if drive is 2 or 3 ;; then it selects a special format and doesn't allow auto detect dcf2 79 ld a,c dcf3 fe04 cp &04 dcf5 210000 ld hl,&0000 dcf8 d0 ret nc ;; quit if drive > 4 dcf9 d5 push de dcfa 116bdd ld de,&dd6b ;; 9 sectors per track, sector id &1, auto detect dcfd fe01 cp &01 dcff 280a jr z,&dd0b dd01 1120dd ld de,&dd20 ;; do not auto detect (drive 2) dd04 fe02 cp &02 dd06 2803 jr z,&dd0b dd08 1139dd ld de,&dd39 ;; do not auto detect (drive 3) ;; copy it in dd0b f5 push af dd0c c5 push bc dd0d 2a42be ld hl,(&be42) dd10 014000 ld bc,&0040 dd13 09 add hl,bc dd14 eb ex de,hl dd15 011900 ld bc,&0019 dd18 edb0 ldir dd1a c1 pop bc dd1b f1 pop af dd1c d1 pop de dd1d c3f7c4 jp &c4f7 ;; continue with AMSDOS detect code ;; filler byte defines where to put data? ;; 32 sectors per track ;; sector id &01 dd20: defb &80,&00,&03,&07,&00,&3f,&00,&1f,&00,&80,&00,&00,&00,&00,&00,&01,&20,&2a,&52,&c4,&02,&04,&00,&00,&01 ;; 32 sectors per track ;; sector id &01 dd39: defb &80,&00,&05,&0f,&03,&5f,&00,&7f,&00,&80,&00,&00,&00,&00,&00,&01,&20,&2a,&52,&e8,&02,&04,&00,&00,&01 ;; 9 sectors per track ;; sector id &c1 dd52: defb &20,&00,&03,&07,&00,&b3,&00,&3f,&00,&c0,&00,&10,&00,&00,&00,&c1,&09,&2a,&52,&e5,&02,&04,&00,&00,&00 ;; 9 sectors per track ;; sector id &01 dd6b: defb &48,&00,&05,&1f,&03,&b0,&00,&7f,&00,&80,&00,&10,&00,&01,&00,&01,&09,&2a,&52,&e5,&02,&04,&00,&00,&00 ;;------------------------------------------------------------------------- ;; |CPM patch to recognise and boot Microdos dd84 cd76c9 call &c976 ;; spin up motor dd87 1600 ld d,&00 dd89 0e10 ld c,&10 dd8b 215dc5 ld hl,&c55d ;; read id dd8e cdffc6 call &c6ff ;; execute function with retry dd91 d2dcc1 jp nc,&c1dc ;; jump to normal (CPC) cpm boot ;; This checks the ID. It will bail out if it finds a CPC sector ID ;; e.g. &c1 or &41 dd94 3a51be ld a,(&be51) ;; R from result phase/ID field dd97 e6c0 and &c0 dd99 c2dcc1 jp nz,&c1dc ;; jump to normal (CPC) cpm boot ;; bit 7,6 must both be zero to get here dd9c 3a52be ld a,(&be52) ;; N from result phase/ID field dd9f fe03 cp &03 dda1 c2dcc1 jp nz,&c1dc ;; jump to normal (CPC) cpm boot ;; Sector size must be 3 (1024 byte sectors) dda4 f3 di dda5 21fdde ld hl,&defd dda8 11053f ld de,&3f05 ;; n, eot, gpl, dtl ddab 010400 ld bc,&0004 ddae edb0 ldir ;; boot from drive 0 ddb0 3e00 ld a,&00 ddb2 32013f ld (&3f01),a ddb5 0605 ld b,&05 ddb7 c5 push bc ddb8 af xor a ;; track 0 ddb9 32023f ld (&3f02),a ;; c ddbc 32033f ld (&3f03),a ;; h ddbf 3e01 ld a,&01 ddc1 32043f ld (&3f04),a ;; r ddc4 3e05 ld a,&05 ddc6 32063f ld (&3f06),a ;; eot ;; read data ;; 3f00 = command ;; 3f01 = drive/side ;; 3f02 = c ;; 3f03 = h ;; 3f04 = r ;; 3f05 = n ;; 3f06 = eot ;; 3f07 = gpl ;; 3f08 = dtl ;; seek: ;; 3f00 = command ;; 3f01 = drive ;; 3f02 = track ddc9 cd5fde call &de5f ;; seek ddcc c253de jp nz,&de53 ;; track 0, sector 1, side 0 ddcf 21803f ld hl,&3f80 ;; 3f80 ddd2 f3 di ddd3 cdccde call &decc ;; read sector ddd6 c253de jp nz,&de53 ddd9 3e01 ld a,&01 dddb 32033f ld (&3f03),a ;; h ddde 32043f ld (&3f04),a ;; r dde1 3e04 ld a,&04 ;; drive 0, side 1 dde3 32013f ld (&3f01),a ;; track 0, sector 1, side 1 dde6 cd5fde call &de5f ;; seek dde9 2068 jr nz,&de53 ddeb 218053 ld hl,&5380 ;; 5380 ddee cdccde call &decc ;; read sector ddf1 2060 jr nz,&de53 ddf3 3e00 ld a,&00 ;; drive 0, side 0 ddf5 32013f ld (&3f01),a ddf8 af xor a ddf9 32033f ld (&3f03),a ;; h ddfc 3c inc a ;; =1 ddfd 32043f ld (&3f04),a ;; r de00 32023f ld (&3f02),a ;; track de03 cd5fde call &de5f ;; seek de06 204b jr nz,&de53 ;; track 1, sector 1, side 0 de08 218067 ld hl,&6780 ;; 6780 de0b cdccde call &decc ;; read sector de0e 2043 jr nz,&de53 de10 3e01 ld a,&01 de12 32033f ld (&3f03),a ;; h de15 32043f ld (&3f04),a ;; r de18 32023f ld (&3f02),a ;; track de1b 3e04 ld a,&04 de1d 32013f ld (&3f01),a ;; drive 0, side 1 de20 3e01 ld a,&01 de22 32063f ld (&3f06),a ;; eot de25 cd5fde call &de5f ;; seek de28 2029 jr nz,&de53 ;; track 1, sector 1, side 1 de2a 21807b ld hl,&7b80 ;; 7b80 de2d cdccde call &decc ;; read sector de30 2021 jr nz,&de53 ;; ident string: ;; 3f80 = &00 ;; 3f81 = &44 ;; 3f82 = &4f ;; 3f83 = &53 ;; &0,"DOS" ;; perform check on first two chars of ident string de32 a7 and a de33 2a803f ld hl,(&3f80) de36 110044 ld de,&4400 de39 ed52 sbc hl,de de3b c258de jp nz,&de58 ;; perform check on last two chars of ident string de3e 2a823f ld hl,(&3f82) de41 114f53 ld de,&534f de44 ed52 sbc hl,de de46 c258de jp nz,&de58 ;; execute de49 3a013f ld a,(&3f01) ;; drive/track de4c fb ei de4d cde5c9 call &c9e5 ;; turn off motor de50 c30040 jp &4000 ;; execute ;; retry de53 c1 pop bc de54 05 dec b de55 c2b7dd jp nz,&ddb7 ;; we have done enough retries de58 fb ei de59 cde5c9 call &c9e5 ;; turn off motor de5c c30000 jp &0000 ;; reset back to BASIC ;;-------------------------------------------------------------------------- ;; perform seek de5f 010f03 ld bc,&030f ;; 3 bytes, seek command de62 cd86de call &de86 ;; write FDC command ;; delay for seek to complete de65 3e21 ld a,&21 de67 cdeede call &deee de6a 3d dec a de6b 20fa jr nz,&de67 de6d 010801 ld bc,&0108 ;; 1 byte, sense interrupt status de70 cd8ade call &de8a ;; This is a bug. should be &de86 ;; so in effect we will try to execute ;; command at &3f03 ;; normally a sense interrupt status command will return ;; either just &80 ;; or ST0 and current track number ;; ;; The delay above would have waited until the seek had completed. ;; Then the FDC should signal it has completed and we should read it. de73 cd9ede call &de9e ;; read FDC data de76 47 ld b,a de77 87 add a,a de78 c8 ret z de79 cd9ede call &de9e ;; read FDC data de7c 78 ld a,b de7d e6f0 and &f0 de7f fec0 cp &c0 de81 28ea jr z,&de6d ;; here we are checking for seek complete I assume de83 ee20 xor &20 de85 c9 ret ;;-------------------------------------------------------------- ;; initial command address ;; C = first byte of command ;; B = number of command bytes de86 21003f ld hl,&3f00 de89 71 ld (hl),c ;; B = number of command bytes ;; HL = address of command bytes de8a c5 push bc de8b 017efb ld bc,&fb7e de8e ed78 in a,(c) de90 e6c0 and &c0 de92 fe80 cp &80 de94 20f8 jr nz,&de8e de96 0c inc c de97 04 inc b de98 eda3 outi de9a c1 pop bc de9b 10ed djnz &de8a de9d c9 ret ;;-------------------------------------------------------------- ;; read FDC data de9e c5 push bc de9f 017efb ld bc,&fb7e dea2 ed78 in a,(c) dea4 e6c0 and &c0 dea6 fec0 cp &c0 dea8 20f8 jr nz,&dea2 deaa 0c inc c deab ed78 in a,(c) dead c1 pop bc deae c9 ret ;;-------------------------------------------------------------- ;; read FDC result phase deaf 0607 ld b,&07 deb1 21093f ld hl,&3f09 deb4 cd9ede call &de9e ;; read FDC data deb7 77 ld (hl),a deb8 23 inc hl deb9 10f9 djnz &deb4 debb 21093f ld hl,&3f09 debe 7e ld a,(hl) debf e6c0 and &c0 dec1 d640 sub &40 dec3 2004 jr nz,&dec9 dec5 23 inc hl dec6 cb7e bit 7,(hl) dec8 c0 ret nz dec9 af xor a deca 3d dec a decb c9 ret ;;-------------------------------------------------------------- ;; read sector ;; HL = address to load sector to decc e5 push hl decd 014609 ld bc,&0946 ;; 9 bytes, first command byte &46 = read data ded0 cd86de call &de86 ;; write FDC command ded3 e1 pop hl ded4 cddcde call &dedc ;; read FDC execution phase ded7 cdafde call &deaf ;; read FDC result phase deda a7 and a dedb c9 ret ;;-------------------------------------------------------------- ;; read execution phase from FDC dedc 017efb ld bc,&fb7e dedf ed78 in a,(c) dee1 f2dfde jp p,&dedf dee4 e620 and &20 dee6 c8 ret z dee7 0c inc c dee8 eda2 ini deea 04 inc b deeb 0d dec c deec 18f1 jr &dedf ;;-------------------------------------------------------------- ;; perform a delay deee f5 push af deef 3e0a ld a,&0a def1 f5 push af def2 3efa ld a,&fa def4 3d dec a def5 20fd jr nz,&def4 def7 f1 pop af def8 3d dec a def9 20f6 jr nz,&def1 defb f1 pop af defc c9 ret ;;-------------------------------------------------------------- ;; copied into ram defd 03 ;; n defe 05 ;; eot deff 1e ;; gpl df00 ff ;; dtl ;; In AMSDOS ROM this is code for CPM2.2 ;; In KC Compact ROM this is all filled with &ff