; Disassembly of the file "z:\ramdisk\home\knoppix\none\CPM_KRYSS_Loader.bin"
; 
; CPU Type: Z80
; 
; Created with dZ80 2.0
; 
; on Sunday, 14 of October 2012 at 06:55 PM
; 
0000 00        NOP
0001 00        NOP
0002 00        NOP
0003 3E00      LD      A,00
0005 D3FE      OUT     ($FE),A	; SO=0, O6=0 (DRAM#1 CPU access), O5=0, border=black
0007 211600    LD      HL,$0016	; copy rest of
000a 1100FC    LD      DE,$FC00	; this code
000d 010004    LD      BC,$0400	; from 0016
0010 EDB0      LDIR		; to FC00
0012 C325FC    JP      $FC25	; run copied code from FC25 (003B in this code)

0015 00        DB      $00
		ORG	FC00	; next line at FC00 after copying
0016 7F        DB      $7F	; (FC00) CTC0 vector \ CTC INT. ROUTINE #2
0017 FC        DB      $FC	; (FC01) CTC0 vector / (does nothing)
0018 7F        DB      $7F	; (FC02) CTC1 vector \ CTC INT. ROUTINE #2
0019 FC        DB      $FC	; (FC03) CTC1 vector / (does nothing)
001A 72        DB      $72	; (FC04) CTC2 vector \ CTC INT. ROUTINE #1
001B FC        DB      $FC	; (FC05) CTC2 vector / (replaces CTC0 vector with CTC1 vector)
001C 7F        DB      $7F	; (FC06) CTC3 vector \ CTC INT. ROUTINE #2
001D FC        DB      $FC	; (FC07) CTC3 vector / (does nothing)
001E 00        DB      $00	; (FC08) used as flag: =00 right before & during track reading, =FF after
001F 00        DB      $00	; (FC09) \ storage start address
0020 00        DB      $00	; (FC0A) / for data read from disk (0000 initially)
0021 00        DB      $00	; (FC0B) \ storage start address for the second system track
0022 24        DB      $24	; (FC0C) / (18 sectors * 512 bytes = 12h*200h = 2400h)
0023 00        DB      $00	; (FC0D) \ current storage address
0024 00        DB      $00	; (FC0E) / for data read from disk
0025 00        DB      $00	; (FC0F) time constant for CTC channel 1 (256 bytes to read)
0026 24        DB      $24	; (FC10) time constant for CTC channel 2 (24=2*12 -> 2*12h*256=12h*512=18 sectors=1 track both sides)
0027 EF        DB      $EF	; (FC11) \ these 2 bytes are arguments for a Specify command
0028 FF        DB      $FF	; (FC12) / (SRT=E=2ms, HUT=F=240ms, HLT=7F=254ms, ND=1->Non-DMA mode)
0029 00        DB      $00	; (FC13) arg#1: Side, Drive No.
002A 00        DB      $00	; (FC14) arg#2: C (Track no.)
002B 00        DB      $00	; (FC15) arg#3: H (Head no.)
002C 01        DB      $01	; (FC16) arg#4: R (Sector no.)
002D 02        DB      $02	; (FC17) arg#5: N (Bytes/sector) *** 2 means 512 bytes/sector=128*2^N ***
002E 09        DB      $09	; (FC18) arg#6: EOT (Last sector no. of a track) *** 9 sectors/track ***
002F 20        DB      $20	; (FC19) arg#7: GPL (Gap 3 Length, betw sectors)
0030 FF        DB      $FF	; (FC1A) arg#8: DTL (Data Length, no.of bytes to be rd/wr into sector) =FF if N!=0
0031 FF        DB      $FF
0032 00        DB      $00	; (FC1C) result byte#1: ST0
0033 00        DB      $00	; (FC1D) result byte#2: ST1 / PCN
0034 00        DB      $00	; (FC1E) result byte#3: ST2
0035 00        DB      $00	; (FC1F) result byte#4: C
0036 00        DB      $00	; (FC20) result byte#5: H
0037 00        DB      $00	; (FC21) result byte#6: R
0038 00        DB      $00	; (FC22) result byte#7: N
0039 00        DB      $00	;
003A 00        DB      $00

003B F3        DI
003C 2100FC    LD      HL,$FC00
003F F9        LD      SP,HL	; stack at FC00
0040 ED5E      IM      2
0042 7C        LD      A,H	; upper half of CTC interrupt table start address (FC)...
0043 ED47      LD      I,A	; ...is stored in register I (see Z80 docs)
0045 7D        LD      A,L	; lower half of CTC interrupt table start address (00)...
0046 D3E3      OUT     ($E3),A	; ... is sent to CTC channel 0
				; int. vectors at (FC00-FC01) for CTC0, (FC02-FC03) for CTC1
				;		  (FC04-FC05) for CTC2, (FC06-FC07) for CTC3
0048 3EFF      LD      A,$FF	; data for CTC0 on next line: set CTC0 to counter mode and enable CTC0 interrupts
004A D3E3      OUT     ($E3),A	; write FF to CTC channel 0 (Enable Interrupt, Counter Mode,
				; Rising Edge, Time Const. Follows, Reset, Control).
				; MEANING: Reset, Enable Interrupts for Channel 0, a Time Constant follows.
004C 3E01      LD      A,$01	; time constant for CTC0 on next line: generate INT for each byte transferred from 8272 to ┬ÁP
004E D3E3      OUT     ($E3),A	; write 01 to CTC channel 0
				; MEANING: Time Constant byte (=01, for 1 byte read).
0050 3E7B      LD      A,$7B	; data for CTC3 on next line: disable int, Counter Mode, rising edge,
				; No Time Const. Follows, Software Reset
0052 D3FB      OUT     ($FB),A	; write 7B to CTC channel 3 (disable interrupt)
0054 217FFC    LD      HL,$FC7F	; CTC0 interrupt vector (for CTC INT. ROUTINE #2) to be set by CTC_1+2_INIT next
0057 CD82FC    CALL    $FC82	; call CTC_1+2_INIT
005A CDC5FC    CALL    $FCC5	; call 8272_RD (make sure 8272 is finished with any possible previous command)
005D 2111FC    LD      HL,$FC11	; start addr for arg bytes of a Specify command (0027 within this code)
0060 010303    LD      BC,$0303	; B=03 for 3 command bytes, C=03 for 8272 Specify opcode
0063 CDA5FC    CALL    $FCA5	; call 8272_WR (send a Specify command to 8272)
0066 D9        EXX		; <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <---|
0067 010402    LD      BC,$0204	; B=02 for 2 command bytes, C=04 for 8272 Sense Drive Status opcode		      |
006A CDA2FC    CALL    $FCA2	; call 8272_WR_HL (send a Sense Drive Status command to 8272, arg bytes from FC13)    |
006D CDC5FC    CALL    $FCC5	; call 8272_RD (reads command result, returns ST3 in register A)		      |
0070 CB6F      BIT     5,A	; test bit 5 of ST3 (RDY), should be 1(?) if READY				      |
0072 D9        EXX		;										      |
0073 2005      JR      NZ,$007A	; if crt drive# is READY --->|							      |
0075 34        INC     (HL)	; HL=FC13 points to first command arg (drive# and head#), this increments drive#      |
0076 CB96      RES     2,(HL)	; set head# to 0	     |							      |
0078 18EC      JR      $0066	; ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> --->|
007A CDE7FC    CALL    $FCE7	; call TRACK_READ <--- <-----|	reads track 00 both sides
007D CDE7FC    CALL    $FCE7	; call TRACK_READ		reads track 01 both sides
0080 C30000    JP      $0000	; runs the code at the beginning of sector 1 track 00 side 0

0083 EDA2      INI		; ######## CTC INT. ROUTINE #3 (FC6D) #######
0085 FB        EI		; this routine reads bytes from FDD
0086 ED4D      RETI
				; ######## CTC INT. ROUTINE #1 (FC72) #######
				; this is executed when CTC2 generates an interrupt, which
				; happens after one full track has been read (both sides,
				; 9 sectors each side, 18 sectors in total)
0088 E5        PUSH    HL
0089 2A02FC    LD      HL,($FC02) ; \ overwrite current CTC0 int. vector in (FC00-FC01)
008C 2200FC    LD      ($FC00),HL ; / with CTC1 int. vector from (FC02-FC03)
008F 2108FC    LD      HL,$FC08	; location FC08 used as a flag:
0092 36FF      LD      (HL),$FF	; (FC08)=FF right after a track has been completely read
0094 E1        POP     HL
0095 FB        EI		; ######## CTC INT. ROUTINE #2 (FC7F) #######
0096 ED4D      RETI		; this int. routine does nothing
				; ######## CTC_1+2_INIT (FC82) #########
				; inputs: HL=CTC0 interrupt vector
0098 F3        DI
0099 2200FC    LD      ($FC00),HL ; set CTC0 interrupt vector to contents of HL
009C 3E7F      LD      A,$7F	; data for CTC1 on next line: disable int, Counter Mode, rising edge,
				; Time Const. Follows, Software Reset
009E D3EB      OUT     ($EB),A	; write 7F to CTC channel 1
00A0 3A0FFC    LD      A,($FC0F) ; time constant for CTC channel 1
00A3 D3EB      OUT     ($EB),A	; write time constant to CTC channel 1
00A5 3EFF      LD      A,$FF	; data for CTC2 on next line: enable int, Counter Mode, rising edge,
				; Time Const. Follows, Software Reset
00A7 D3F3      OUT     ($F3),A	; write 7F to CTC channel 2
00A9 3A10FC    LD      A,($FC10) ; time constant for CTC channel 2
00AC D3F3      OUT     ($F3),A	; write time constant to CTC channel 2
00AE C9        RET
				; ######## 8272_POLL (FC99) #########
00AF DBF5      IN      A,($F5)	; read 8272 Status Register			| this routine polls the 8272 Status Register
00B1 CB7F      BIT     7,A	; test bit 7 (RQM)				| until 8272 is ready to send or receive
00B3 28FA      JR      Z,$00AF	; if bit 7 = 0 read 8272 Status Register again	| data to or from the CPU. When ready (RQM=1)
00B5 CB77      BIT     6,A	; test bit 6					| bit 6 is tested (DIO, 0=receive/1=send)
00B7 C9        RET
				; ######## 8272_WR_HL (FCA2) #########
00B8 2113FC    LD      HL,$FC13	; routine below with arg bytes taken from FC13
				; ######## 8272_WR (FCA5) #########
				; send a command to 8272
				; inputs: HL=start addr of bytes to be sent (command args)
				;	  C=first byte to be sent (command opcode)
				;	  B=nr of command bytes (opcode+args)
00BB DBF5      IN      A,($F5)	; <--- <--- <--- <--- <---| read 8272 Status Register
00BD CB67      BIT     4,A	; test bit 4 (FDC Busy)	  |
00BF 20FA      JR      NZ,$00BB	; ---> ---> ---> ---> --->| repeat if FDC busy
00C1 1802      JR      $00C5	; ---> ---> --->|
00C3 4E        LD      C,(HL)	; <--- <--- <---- <--- <--- <---|
00C4 23        INC     HL	;		|		|
00C5 F3        DI		; <--- <--- <---|		|
00C6 CD99FC    CALL    $FC99	; call 8272_POLL		|
00C9 C4D7FC    CALL    NZ,$FCD7	; call CPM_TO_COBRA if 8272 to send data
00CC 59        LD      E,C	;				|
00CD 0EFD      LD      C,$FD	;				|
00CF ED59      OUT     (C),E	; send byte to 8272 Data Reg	|
00D1 10F0      DJNZ    $00C3	; ---> ---> ---> ---> ---> ---->|
00D3 FB        EI
00D4 C9        RET
				; ######## 8272_SIS (FCBF) ########
00D5 010801    LD      BC,$0108	; B=01 for 1 command bytes, C=08 opcode for Sense Interrupt Status
00D8 CDA5FC    CALL    $FCA5	; call 8272_WR (send Sense Interrupt Status command to 8272)
				; ######## 8272_RD (FCC5) #########
				; reads last command result bytes from 8272
				; outputs: A=first result byte
				;	   (FC1C-FC22)=the max. 7 result bytes in order
00DB 211CFC    LD      HL,$FC1C	; start address to store 8272 command result bytes
00DE 0608      LD      B,$08	; counter (8 bytes to read from 8272)
00E0 CD99FC    CALL    $FC99	; call 8272_POLL <--- <--- <----|
00E3 2813      JR      Z,$00F8	; ---> ---> --->|if all result bytes are read, exit (normal exit)
00E5 36FF      LD      (HL),$FF	;		|		|
00E7 DBFD      IN      A,($FD)	; read 8272 Data| Register	|
00E9 77        LD      (HL),A	; store result	|		|
00EA 23        INC     HL	; increment storage pointer	|
00EB 10F3      DJNZ    $00E0	; ---> ---> --------> ---> ---->|
00ED F3        DI		; ######## CPM_TO_COBRA (FCD7) ######## if 8 result bytes read and still reading, exit (error)
00EE AF        XOR     A	;		| A=00
00EF 6F        LD      L,A	;		|
00F0 67        LD      H,A	;		| HL=0000 (jump address)
00F1 F6C1      OR      $C1	;		| A=C1
00F3 D3FE      OUT     ($FE),A	;		| set SO=1, O6=1, border=blue
00F5 ED4F      LD      R,A	;		| set bit 7 of R to 1 (change to startup config)
00F7 E9        JP      (HL)	;		| jump to 0000 in startup config
00F8 211CFC    LD      HL,$FC1C	; <--- <--- <---|
00FB 7E        LD      A,(HL)	; return with first result byte in A
00FC C9        RET
				; ######## TRACK_READ (FCE7) #########
				; reads one track both sides (9 sectors/side, 18 sectors in total)
00FD 010F03    LD      BC,$030F	; B=03 for 3 command bytes, C=0F opcode for Seek command
0100 CDA2FC    CALL    $FCA2	; call 8272_WR_HL (Seek command with args from FC13)
0103 CDBFFC    CALL    $FCBF	; call 8272_SIS (returns first result byte (ST0) in A) <--- <--- <--- <--|
0106 CB6F      BIT     5,A	; test bit 5 of first result byte ST0 (Seek End bit, if 1 Seek ended ok) |
0108 28F9      JR      Z,$0103	; if Seek not ended, repeat SIS   ---> ---> ---> ---> ---> ---> ---> --->|
010A E650      AND     $50	; test bits 6 and 4 (Abnorm. Termination/Equipment Check/Track00 not reached)
010C C4D7FC    CALL    NZ,$FCD7	; if any of above errors, CPM_TO_COBRA
010F CDBFFC    CALL    $FCBF	; call 8272_SIS (returns first result byte (ST0) in A)
0112 FE80      CP      $80	; check if invalid command (SIS after SIS should give ST0=80, invalid command)
0114 20F9      JR      NZ,$010F	; if ST0 not 80, go back 2 lines (repeat SIS)
0116 DBF5      IN      A,($F5)	; read 8272 Status Register <---|
0118 E60F      AND     $0F	; test bits 0-3 (FDD 0-3 Busy)	|
011A 20FA      JR      NZ,$0116	; if any drive busy --> ---> -->|
011C 0603      LD      B,$03	; counter for max. 3 loops to be executed next
011E D9        EXX		; <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <----|
011F 014A02    LD      BC,$024A	; B=02 for 2 command bytes, C=4A opcode for Read ID command in MFM mode	|
0122 CDA2FC    CALL    $FCA2	; call 8272_WR_HL (send Read ID command with arg from (FC13))		|
0125 CDC5FC    CALL    $FCC5	; call 8272_RD (returns ST0 in A)					|
0128 E6C0      AND     $C0	; test bits 6, 7 (normal termination if both =0)			|
012A D9        EXX		;									|
012B 2805      JR      Z,$0132	; --->| if normal termination skip next 2 lines				|
012D 10EF      DJNZ    $011E	; ------> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ->|
012F CDD7FC    CALL    $FCD7	;     | CPM_TO_COBRA
0132 060A      LD      B,$0A	; <---| B as counter for max 10 lops next
0134 C5        PUSH    BC	; <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <-|
0135 AF        XOR     A	; location FC08 used as a flag:								 |
0136 3208FC    LD      ($FC08),A ; =00 right before and during track reading						 |
0139 216DFC    LD      HL,$FC6D	; CTC0 interrupt vector to be used next (for CTC INT. ROUTINE #3 - saves FDD bytes)	 |
013C CD82FC    CALL    $FC82	; call CTC_1+2_INIT									 |
013F 01C609    LD      BC,$09C6	; B=09 for 9 command bytes, C=C6 opcode for Read Data (MT, MFM) on next line		 |
0142 CDA2FC    CALL    $FCA2	; call 8272_WR_HL (send a Read Data (MT, MFM) to 8272) which leaves C=FD		 |
0145 2A09FC    LD      HL,($FC09) ; HL=storage start address for data read from disk (0000 to begin, 2400 after 1 track) |
0148 76        HALT		; wait for first interrupt from CTC <--- <--- <-| ## one interrupt per byte read,	 |
0149 DBF5      IN      A,($F5)	; read 8272 Main Status Register		| ## bytes read by INI from (C)=(FD)	 |
014B E620      AND     $20	; test bit 5 (Non-DMA, 1 during exec in Non-DMA,| 0 when exec finished)			 |
014D 20F9      JR      NZ,$0148	; if exec not finished yet ---> ---> ---> ----->|					 |
014F 220DFC    LD      ($FC0D),HL ; save current storage address for data read from disk				 |
0152 217FFC    LD      HL,$FC7F	; CTC0 interrupt vector to be used next (for CTC INT. ROUTINE #2 - does nothing)	 |
0155 CD82FC    CALL    $FC82	; call CTC_1+2_INIT									 |
0158 CDC5FC    CALL    $FCC5	; call 8272_RD (after this HL=FC1C)							 |
015B 3A08FC    LD      A,($FC08) ; location FC08 used as a flag for track reading					 |
015E B7        OR      A
015F C1        POP     BC
0160 2805      JR      Z,$0167	; ------>| if track reading in progress skip 3 lines and restart loop			 |
0162 7E        LD      A,(HL)	;	 | (HL)=(FC1C)=first result byte (ST0) of the 8272 Read Data command		 |
0163 E6D8      AND     $D8	;	 | test bits 7 6 4 3 (Interrupt Code, Equipment Check, Not Ready)		 |
0165 2805      JR      Z,$016C	; ---> ---> ---> ---> ---> ---> ---> ---> --->| if none of above errors			 |
0167 10CB      DJNZ    $0134	; <------|---> ---> ---> ---> ---> ---> --->---> ---> ---> ---> ---> ---> ---> ---> ---->|
0169 CDD7FC    CALL    $FCD7	; call CPM_TO_COBRA			      |
016C 2114FC    LD      HL,$FC14	; storage address for current track no. <-----|
016F 34        INC     (HL)	; increment current track number
0170 2A0BFC    LD      HL,($FC0B) ; copy the value of storage addr for second system track...
0173 2209FC    LD      ($FC09),HL ; ...over the value of current storage addr
0176 C9        RET

0177 E9        JP      (HL)
0178 211CFC    LD      HL,$FC1C
017B 7E        LD      A,(HL)
017C C9        RET

017D 010F03    LD      BC,$030F

0180 E5        DB      $E5	; unused portion of the sector (filled with E5 when formatted)
0181 E5        DB      $E5
0182 E5        DB      $E5
0183 E5        DB      $E5
0184 E5        DB      $E5
0185 E5        DB      $E5
0186 E5        DB      $E5
0187 E5        DB      $E5
0188 E5        DB      $E5
0189 E5        DB      $E5
018A E5        DB      $E5
018B E5        DB      $E5
018C E5        DB      $E5
018D E5        DB      $E5
018E E5        DB      $E5
018F E5        DB      $E5
0190 E5        DB      $E5
0191 E5        DB      $E5
0192 E5        DB      $E5
0193 E5        DB      $E5
0194 E5        DB      $E5
0195 E5        DB      $E5
0196 E5        DB      $E5
0197 E5        DB      $E5
0198 E5        DB      $E5
0199 E5        DB      $E5
019A E5        DB      $E5
019B E5        DB      $E5
019C E5        DB      $E5
019D E5        DB      $E5
019E E5        DB      $E5
019F E5        DB      $E5
01A0 E5        DB      $E5
01A1 E5        DB      $E5
01A2 E5        DB      $E5
01A3 E5        DB      $E5
01A4 E5        DB      $E5
01A5 E5        DB      $E5
01A6 E5        DB      $E5
01A7 E5        DB      $E5
01A8 E5        DB      $E5
01A9 E5        DB      $E5
01AA E5        DB      $E5
01AB E5        DB      $E5
01AC E5        DB      $E5
01AD E5        DB      $E5
01AE E5        DB      $E5
01AF E5        DB      $E5
01B0 E5        DB      $E5
01B1 E5        DB      $E5
01B2 E5        DB      $E5
01B3 E5        DB      $E5
01B4 E5        DB      $E5
01B5 E5        DB      $E5
01B6 E5        DB      $E5
01B7 E5        DB      $E5
01B8 E5        DB      $E5
01B9 E5        DB      $E5
01BA E5        DB      $E5
01BB E5        DB      $E5
01BC E5        DB      $E5
01BD E5        DB      $E5
01BE E5        DB      $E5
01BF E5        DB      $E5
01C0 E5        DB      $E5
01C1 E5        DB      $E5
01C2 E5        DB      $E5
01C3 E5        DB      $E5
01C4 E5        DB      $E5
01C5 E5        DB      $E5
01C6 E5        DB      $E5
01C7 E5        DB      $E5
01C8 E5        DB      $E5
01C9 E5        DB      $E5
01CA E5        DB      $E5
01CB E5        DB      $E5
01CC E5        DB      $E5
01CD E5        DB      $E5
01CE E5        DB      $E5
01CF E5        DB      $E5
01D0 E5        DB      $E5
01D1 E5        DB      $E5
01D2 E5        DB      $E5
01D3 E5        DB      $E5
01D4 E5        DB      $E5
01D5 E5        DB      $E5
01D6 E5        DB      $E5
01D7 E5        DB      $E5
01D8 E5        DB      $E5
01D9 E5        DB      $E5
01DA E5        DB      $E5
01DB E5        DB      $E5
01DC E5        DB      $E5
01DD E5        DB      $E5
01DE E5        DB      $E5
01DF E5        DB      $E5
01E0 E5        DB      $E5
01E1 E5        DB      $E5
01E2 E5        DB      $E5
01E3 E5        DB      $E5
01E4 E5        DB      $E5
01E5 E5        DB      $E5
01E6 E5        DB      $E5
01E7 E5        DB      $E5
01E8 E5        DB      $E5
01E9 E5        DB      $E5
01EA E5        DB      $E5
01EB E5        DB      $E5
01EC E5        DB      $E5
01ED E5        DB      $E5
01EE E5        DB      $E5
01EF E5        DB      $E5
01F0 E5        DB      $E5
01F1 E5        DB      $E5
01F2 E5        DB      $E5
01F3 E5        DB      $E5
01F4 E5        DB      $E5
01F5 E5        DB      $E5
01F6 E5        DB      $E5
01F7 E5        DB      $E5
01F8 E5        DB      $E5
01F9 E5        DB      $E5
01FA E5        DB      $E5
01FB E5        DB      $E5
01FC E5        DB      $E5
01FD E5        DB      $E5
01FE E5        DB      $E5
01FF E5        DB      $E5