; Disassembly of the file "Z:\home\knoppix\Public\LK.SYS"
; 
; CPU Type: Z80
; 
; Using the opcode map file "Z:\home\knoppix\Public\LK.SYS.opmap"
; ; Created with dZ80 2.0
; 
; on Saturday, 31 of December 2016 at 08:22 PM
; 
0000 E5		DEFB	$E5	; Unused area (E5 is opcode for PUSH HL)
0001 E5		DEFB	$E5	; This CP/M Loader is identical to CPM_CHRIS_Loader.asm
0002 E5		DEFB	$E5	; except this area is empty instead of having the code
0003 E5		DEFB	$E5	; for the PLUS logo
0004 E5		DEFB	$E5
0005 E5		DEFB	$E5
0006 E5		DEFB	$E5
0007 E5		DEFB	$E5
0008 E5		DEFB	$E5
0009 E5		DEFB	$E5
000A E5		DEFB	$E5
000B E5		DEFB	$E5
000C E5		DEFB	$E5
000D E5		DEFB	$E5
000E E5		DEFB	$E5
000F E5		DEFB	$E5
0010 E5		DEFB	$E5
0011 E5		DEFB	$E5
0012 E5		DEFB	$E5
0013 E5		DEFB	$E5
0014 E5		DEFB	$E5
0015 E5		DEFB	$E5
0016 E5		DEFB	$E5
0017 E5		DEFB	$E5
0018 E5		DEFB	$E5
0019 E5		DEFB	$E5
001A E5		DEFB	$E5
001B E5		DEFB	$E5
001C E5		DEFB	$E5
001D E5		DEFB	$E5
001E E5		DEFB	$E5
001F E5		DEFB	$E5
0020 E5		DEFB	$E5
0021 E5		DEFB	$E5
0022 E5		DEFB	$E5
0023 E5		DEFB	$E5
0024 E5		DEFB	$E5
0025 E5		DEFB	$E5
0026 E5		DEFB	$E5
0027 E5		DEFB	$E5
0028 E5		DEFB	$E5
0029 E5		DEFB	$E5
002A E5		DEFB	$E5
002B E5		DEFB	$E5
002C E5		DEFB	$E5
002D E5		DEFB	$E5
002E E5		DEFB	$E5
002F E5		DEFB	$E5
0030 E5		DEFB	$E5
0031 E5		DEFB	$E5
0032 E5		DEFB	$E5
0033 E5		DEFB	$E5
0034 E5		DEFB	$E5
0035 E5		DEFB	$E5
0036 E5		DEFB	$E5
0037 E5		DEFB	$E5
0038 E5		DEFB	$E5
0039 E5		DEFB	$E5
003A E5		DEFB	$E5
003B E5		DEFB	$E5
003C E5		DEFB	$E5
003D E5		DEFB	$E5
003E E5		DEFB	$E5
003F E5		DEFB	$E5
0040 E5		DEFB	$E5
0041 E5		DEFB	$E5
0042 E5		DEFB	$E5
0043 E5		DEFB	$E5
0044 E5		DEFB	$E5
0045 E5		DEFB	$E5
0046 E5		DEFB	$E5
0047 E5		DEFB	$E5
0048 E5		DEFB	$E5
0049 E5		DEFB	$E5
004A E5		DEFB	$E5
004B E5		DEFB	$E5
004C E5		DEFB	$E5
004D E5		DEFB	$E5
004E E5		DEFB	$E5
004F E5		DEFB	$E5
0050 E5		DEFB	$E5
0051 E5		DEFB	$E5
0052 E5		DEFB	$E5
0053 E5		DEFB	$E5
0054 E5		DEFB	$E5
0055 E5		DEFB	$E5
0056 E5		DEFB	$E5
0057 E5		DEFB	$E5
0058 E5		DEFB	$E5
0059 E5		DEFB	$E5
005A E5		DEFB	$E5
005B E5		DEFB	$E5
005C E5		DEFB	$E5
005D E5		DEFB	$E5
005E E5		DEFB	$E5
005F E5		DEFB	$E5
0060 E5		DEFB	$E5
0061 E5		DEFB	$E5
0062 E5		DEFB	$E5
0063 E5		DEFB	$E5
0064 E5		DEFB	$E5
0065 E5		DEFB	$E5
0066 E5		DEFB	$E5
0067 E5		DEFB	$E5
0068 E5		DEFB	$E5
0069 E5		DEFB	$E5
006A E5		DEFB	$E5
006B E5		DEFB	$E5
006C E5		DEFB	$E5
006D E5		DEFB	$E5
006E E5		DEFB	$E5
006F E5		DEFB	$E5
0070 E5		DEFB	$E5
0071 E5		DEFB	$E5
0072 E5		DEFB	$E5
0073 E5		DEFB	$E5
0074 E5		DEFB	$E5
0075 E5		DEFB	$E5
0076 E5		DEFB	$E5
0077 E5		DEFB	$E5
0078 E5		DEFB	$E5
0079 E5		DEFB	$E5
007A E5		DEFB	$E5
007B E5		DEFB	$E5
007C E5		DEFB	$E5
007D E5		DEFB	$E5
007E E5		DEFB	$E5
007F E5		DEFB	$E5
				; ######### From this point on the code is identical to CPM_CHRIS_Loader
0080 EB		EX	DE,HL	; DE=$0000 because, when BOOT ROM CP/M loading routine terminates, HL=$0000
0081 2A9A00	LD	HL,($009A) ; HL=$0400
0084 4B		LD	C,E	; C=$00
0085 44		LD	B,H	; B=$04
0086 EDB8	LDDR		; copy $0400-$0001 to $0000-$FC01; when done BC=$0000, DE=$FC00, HL=$0000
0088 EB		EX	DE,HL	; DE=$0000, HL=$FC00
0089 CBE5	SET	4,L	; HL=$FC10
008B CBFD	SET	7,L	; HL=$FC90
008D E9		JP	(HL)	; jump to $FC90 which is 0090 below --->|
				;					|
008E 00		DEFB	$00	;					|
008F 00		DEFB	$00	;					|
				;					|
0090 1820	JR	$00B2	; <--- <---|<--- <--- <--- <--- <--- <--| <---- CTC0 Interrupt Vector (unused)
				;	   |
0092 09		DEFB	$09	;FC92	   | \ CTC1 Interrupt
0093 FD		DEFB	$FD	;FC93	   | /    Vector
0094 FC		DEFB	$FC	;FC94	   | \ CTC2 Interrupt
0095 FC		DEFB	$FC	;FC95	   | /    Vector
0096 00		DEFB	$00	;FC96	   | \ CTC3 Interrupt (not
0097 20		DEFB	$20	;FC97	   | /    Vector      used) <--- this is multiplier of $100 to give total size of a track both sides
0098 FF		DEFB	$FF	;FC98	   | \ Start (top) address for saving
0099 3F		DEFB	$3F	;FC99	   | / system track #0 data - in reverse !!
009A 00		DEFB	$00	;FC9A	   | \ Here TRACK_READ will save the start (top) address ($1FFF)
009B 04		DEFB	$04	;FC9B	   | / for saving system track #1 data in reverse, after track #0 is already saved
009C 03		DEFB	$03	;FC9C	   | \ 8272 Specify command opcode
009D 03		DEFB	$03	;FC9D	   | / 3 loops for 8272_CMD (2 args required after Specify command opcode)
009E 08		DEFB	$08	;FC9E	   | \ 8272 Sense Interrupt Status command opcode
009F 01		DEFB	$01	;FC9F	   | / 1 loop for 8272_CMD (no args required for SIS cmd)
00A0 04		DEFB	$04	;FCA0	   | \ 8272 Sense Drive Status command opcode
00A1 02		DEFB	$02	;FCA1	   | / 2 loops for 8272_CMD (1 arg required after Sense Drive Status command opcode)
00A2 0F		DEFB	$0F	;FCA2	   | \ 8272 Seek command opcode
00A3 03		DEFB	$03	;FCA3	   | / 3 loops for 8272_CMD (2 args required after Seek command opcode)
00A4 4A		DEFB	$4A	;FCA4	   | \ 8272 Read ID command opcode with MFM
00A5 02		DEFB	$02	;FCA5	   | / 2 loops for 8272_CMD (1 arg required after opcode)
00A6 C6		DEFB	$C6	;	   | \ 8272 Read Data command opcode with MFM and MT(MultiTrack)
00A7 09		DEFB	$09	;	   | / 9 loops for 8272_CMD (8 args required after Read Data command opcode)
00A8 EF		DEFB	$EF	;FCA8	   | arg #1 for 8272 Specify cmd: SRT+HUT (Step Rate Time = 2 ms, Head Unload Time = 240 ms)
00A9 FF		DEFB	$FF	;FCA9  *** | arg #2 for 8272 Specify cmd: HLT+ND (Head Load Time = 254 ms, Non-DMA = 1)			*** This is different from CPM+CHRIS_Loader
00AA 00		DEFB	$00	;FCAA	   | arg #1 for 8272 Seek cmd: (HDS+DS1+DS0) HDS kept on 0 while DS1+DS2 incremented
00AB 00		DEFB	$00	;FCAB	   | C = cylinder number
00AC 00		DEFB	$00	;FCAC	   | H = head number
00AD 00		DEFB	$00	;FCAD	   | R = sector number
00AE 00		DEFB	$00	;FCAE	   | N = bytes/sector
00AF 00		DEFB	$00	;FCAF	   | EOT
00B0 FF		DEFB	$FF	;FCB0	   | GPL
00B1 FF		DEFB	$FF	;FCB1	   | DTL
				;	   |
00B2 F3		DI		; <--- <---| LATER USED FOR 8272 CMD RESULT STORAGE - $FCB2-$FCB8   <---   this is at $FCB2 when executed
00B3 F9		LD	SP,HL	; HL=$FC90, set stack at $FC90			      $FCB2-$FCB8
00B4 ED5E	IM	2	; interrupt mode 2				      $FCB2-$FCB8
00B6 7C		LD	A,H	; A=$FC						      $FCB2-$FCB8
00B7 ED47	LD	I,A	; I=$FC = upper half of CTC interrupt vector address  $FCB2-$FCB8

00B9 7D		LD	A,L	; A=$90 = lower half of CTC interrupt vector address ...
00BA D3E3	OUT	($E3),A	; ... is sent to CTC channel 0 (bit 0 = 0 means Vector)
				; MEANING: Interrupt Vector being used by all 4 channels!!
				; Interrupt Vector = 10010cc0 where cc is the CTC channel requesting the interrupt.
				; So vector for CTC0 = $90, CTC1 = $92, CTC2 = $94, CTC3 = $96
				; The upper half of addr table pointer is $FC which is $00 within this CP/M loader (after relocation, $0000 is at $FC00).
00BC 3EFF	LD	A,$FF	; Control word for CTC0 on next line (Enable Interrupt, Counter Mode, Rising Edge, Time Const. Follows, Reset, Control).
				; MEANING: Reset, Enable Interrupts for Channel 0, a Time Constant follows.
00BE D3E3	OUT	($E3),A	; Write control word $FF to CTC channel 0 
00C0 3E01	LD	A,$01	; Time constant for CTC0 on next line:
				; MEANING: CTC0 generates INT for each byte transferred from 8272 to ┬ÁP
00C2 D3E3	OUT	($E3),A	; Write time constant $01 to CTC channel 0
00C4 3E7B	LD	A,$7B	; Control word for CTC Channel 3 on next line (Disable Interrupt, Counter Mode, Rising Edge, No Time Constant Follows, Reset, Control)
				; MEANING: Reset, Disable Interrupts for Channel 3
00C6 D3FB	OUT	($FB),A	; Send control word to CTC Channel 3

00C8 2A92FC	LD	HL,($FC92) ; HL=$FD09 = interrupt vector for the routine call below (address of CTC1 Interrupt Service Routine)
00CB CD0CFD	CALL	$FD0C	; Call CTC1+2_INIT (deactivates CTC0 int. routine)
00CE CD4FFD	CALL	$FD4F	; Call 8272_READ to read command result bytes from 8272 Data Register (to make sure there's no unfinished command)
00D1 21A8FC	LD	HL,$FCA8 ; addr for the 2 Specify command args
00D4 ED4B9CFC	LD	BC,($FC9C) ; B=$03 (2 args after 8272 cmd opcode), C=$03 (8272 Specify command opcode)
00D8 CD2FFD	CALL	$FD2F	; Call 8272_CMD_HL to send Specify command to 8272
00DB D9		EXX	; #------------------------------# <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <---|
00DC ED4BA0FC	LD	BC,($FCA0) ; B=$02 (1 arg after 8272 cmd opcode), C=$04 (8272 Sense Drive Status command opcode)   |
00E0 CD2CFD	CALL	$FD2C	; Call 8272_CMD to send Sense Drive Status command to 8272				   |
00E3 CD4FFD	CALL	$FD4F	; Call 8272_READ to read command result bytes from 8272 Data Register			   |
00E6 CB6F	BIT	5,A	; test bit 5 of ST3 (status of RDY signal from FDD,should be 1(?) if READY)		   |
00E8 D9		EXX	; #------------------------------#								   |
00E9 2005	JR	NZ,$00F0 ; jump if FDD Ready --> -->|								   |
00EB 34		INC	(HL)	; HL=$FCA8+2=$FCAA after the call to 8272_CMD_HL 8 lines above, ($FCAA)=00 initially=arg #1 for 8272 Seek cmd	** increment drive number **
00EC CB96	RES	2,(HL)	; make sure HDS=0 for 8272 Seek cmd							   |
00EE 18EB	JR	$00DB	; ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> --->|
00F0 CD71FD	CALL	$FD71	; <--- <--- <--- <--- <-----| call TRACK_READ, reads track 00 both sides
00F3 CD71FD	CALL	$FD71	;			      call TRACK_READ, reads track 01 both sides
00F6 E9		JP	(HL)

				; ################ CTC0 Interrupt Service Routine (this reads floppy data bytes) ########
00F7 EDA2	INI		; ----------------------- FCF7 after relocation -------------------------
00F9 FB		EI
00FA ED4D	RETI	

				; ################ CTC2 Interrupt Service Routine #######################
00FC E5		PUSH	HL	; ----------------------- FCFC after relocation -------------------------
00FD 2A92FC	LD	HL,($FC92) ; HL=$FD09
0100 2290FC	LD	($FC90),HL ; ($FC90) = CTC0 Interrupt Service Routine addr = $FD09 = CTC1 Interrupt Service Routine (does nothing) *** this deactivates CTC0 routine ***
0103 21F0FC	LD	HL,$FCF0 ; location $FCF0 used as a flag:
0106 36FF	LD	(HL),$FF ; ($FCF0)=FF right after a track has been completely read
0108 E1		POP	HL
				; ################ CTC1 Interrupt Service Routine (does nothing) ########
0109 FB		EI		; ----------------------- FD09 after relocation -------------------------
010A ED4D	RETI	

				; ############################ CTC1+2_INIT ##############################
010C F3		DI		; ----------------------- FD0C after relocation -------------------------
010D 2290FC	LD	($FC90),HL ; set CTC0 interrupt vector to value in HL ($FD09 = CTC1 Interrupt Service Routine, does nothing) *** this deactivates CTC0 routine ***
0110 3E7F	LD	A,$7F	; Control word for CTC1 below (Disable Interrupt, Counter Mode, Rising Edge, Time Constant Follows, Reset, Control)
				; MEANING: Reset, Disable Interrupts for Channel 1
0112 D3EB	OUT	($EB),A	; Send control word to CTC channel 1
0114 3A96FC	LD	A,($FC96) ; A=$00 = time constant for CTC1 below
				; MEANING: Channel 1 counts every 256 bytes transferred
0117 D3EB	OUT	($EB),A ; Send time constant to CTC channel 1
0119 3EFF	LD	A,$FF	; Control word for CTC2 below (Enable Interrupt, Counter Mode, Rising Edge, Time Constant Follows, Reset, Control)
				; MEANING: Reset, Enable Interrupts for Channel 2
011B D3F3	OUT	($F3),A ; Send control word to CTC channel 2
011D 3A97FC	LD	A,($FC97) ; A=$20 = time constant for CTC2 below
				; MEANING: Channel 2 counts every $20 x $100 = $2000 = 8192 bytes transferred from 8272 (both sides of a system track, each having 1 sector with 4096 bytes)
0120 D3F3	OUT	($F3),A ; Send time constant to CTC channel 2
0122 C9		RET

				; ############################ 8272_POLL ################################
				; ----------------------- FD23 after relocation -------------------------
0123 DBF5	IN	A,($F5)	; read 8272 Status Register <--- <--- <--- <--- <--- <-----|		| this routine polls the 8272 Status Register
0125 CB7F	BIT	7,A	; test bit 7 (RQM) to see if 8272 ready to send or receive |		| until 8272 is ready to send or receive
0127 28FA	JR	Z,$0123	; jump if 8272 not ready ---> ---> ---> ---> ---> ---> --->|		| data to or from the CPU. When ready (RQM=1)
0129 CB77	BIT	6,A	; test bit 6 (DIO) to determine direction of data transfer		| bit 6 is tested (DIO, 0=send/1=receive)
012B C9		RET

				; ############################ 8272_CMD ##################################
				; ----------------------- FD2C after relocation -------------------------
				; BC = parameter to this subroutine: B = loop count for DJNZ $0137, C = command opcode to write to 8272 Data Register
012C 21AAFC	LD	HL,$FCAA ; address of 8272 command parameter bytes following the command opcode
				; ############################ 8272_CMD_HL ###############################
				; ----------------------- FD2F after relocation -------------------------
				; this entry point requires HL = additional parameter as address of 8272 command parameter bytes following the command opcode
012F DBF5	IN	A,($F5)	; read 8272 Status Register <----|
0131 CB67	BIT	4,A	; test bit 4 (FDC Busy)		 |
0133 20FA	JR	NZ,$012F; if FDC Busy jump ---> ---> --->|
0135 1802	JR	$0139	; ---> ---> --->|
0137 4E		LD	C,(HL)	; <---- <--- <--- <--- <--- <---| C = (next) 8272 cmd parameter byte
0138 23		INC	HL	;		|		| increment 8272 cmd parameter pointer
0139 F3		DI		; <--- <--- <---|		|
013A CD23FD	CALL	$FD23	; Call 8272_POLL		|
013D 2022	JR	NZ,$0161; jump to CPM_TO_COBRA if transfer is TO CPU
013F 59		LD	E,C	; E=8272 cmd byte		|  <<< this will leave E'=$02 when 8272_CMD is called from TRACK_READ at $0197 within this binary file
0140 0EFD	LD	C,$FD	; 8272 Data Register port addr	|	since the second command byte of Read ID will be $02 (CP/M boots from drive 2, head 0)
0142 ED59	OUT	(C),E	; write to 8272 Data Register	|		(for later when CP/M starts with BIOS function 00 BOOT !!!!)
0144 10F1	DJNZ	$0137	; ----> ---> ---> ---> ---> --->|  <<< this will leave C'=$02 when 8272_CMD is called from TRACK_READ at $0197 within this binary file
0146 FB		EI		;					since the second command byte of Read ID will be $02 (CP/M boots from drive 2, head 0)
0147 C9		RET	;							(for later when CP/M starts with BIOS function 00 BOOT !!!!)
				; ############################ 8272_CMD_SIS ##############################
				; ----------------------- FD48 after relocation -------------------------
0148 ED4B9EFC	LD	BC,($FC9E) ; C=08=Sense Interrupt Status opcode, B=01=0 args req'd
014C CD2FFD	CALL	$FD2F	; Call 8272_CMD_HL to send Sense Interrupt Status cmd

				; ############################ 8272_READ #################################
				; ----------------------- FD4F after relocation -------------------------
				; Read command result bytes from 8272 Data Register and store them at FCB2-FCB8.
				; Normally max. 7 command result bytes can be read and normal exit is by jump at 0157
				; If after 7 bytes read the transfer direction detected does not change to "CPU -> 8272"
				; then something is wrong and a jump is made to BOOT hw config (JR Z,$016C)
014F 21B2FC	LD	HL,$FCB2
0152 0608	LD	B,$08	; 8 loops next
0154 CD23FD	CALL	$FD23	; Call 8272_POLL<--- <--- <--- <--- <---|
0157 2813	JR	Z,$016C	; Jump if transfer is FROM CPU -----> ---> ---> --->|
0159 36FF	LD	(HL),$FF ; ($FCB2+nn)=FF			|	    |
015B DBFD	IN	A,($FD)	; read 1 byte from 8272 Data Register	|	    |
015D 77		LD	(HL),A	; store byte at ($FCB2+nn)		|	    |
015E 23		INC	HL	;					|	    |
015F 10F3	DJNZ	$0154	; ---> ---> ---> ---> ---> ---> ---> -->|	    |  <<< this should leave B'=$01 for later when CP/M starts with BIOS function 00 BOOT !!!!
0161 F3		DI		; ############## CPM_TO_COBRA ##############	    |		 (7 result bytes are read after Read ID command)
0162 AF		XOR	A	; A=00						    |
0163 6F		LD	L,A	;						    |
0164 67		LD	H,A	; HL=0000					    |
0165 F6C1	OR	$C1	; A=$C1						    |
0167 D3FE	OUT	($FE),A	; write $C1 to port C of 8255			    |
;				; (set border to blue, set signal "SO" to 1, set signal "O5" to 0,
;				;  set signal "O6" to 1 to allow access to video memory in the hw startup config)
0169 ED4F	LD	R,A	; set bit 7 of R to 1 to prepare jump to startup (COBRA BOOT) hw config
016B E9		JP	(HL)	; jump to (HL)=$0000				    |
				;						    |
016C 21B2FC	LD	HL,$FCB2 ; <--- <--- <--- <--- <--- <--- <--- <--- <--- <---|  <<< this leaves HL'=$FCB2 for later when CP/M starts with BIOS function 00 BOOT !!!!
016F 7E		LD	A,(HL)	; Load first command result byte in A
0170 C9		RET

				; ############################ TRACK_READ ################################
				; ----------------------- FD71 after relocation -------------------------
0171 ED4BA2FC	LD	BC,($FCA2) ; B=$03 (2 args after 8272 cmd opcode), C=$0F (8272 Seek command opcode)
0175 CD2CFD	CALL	$FD2C	; Call 8272_CMD to send Seek command to 8272
0178 CD48FD	CALL	$FD48	; Call 8272_CMD_SIS <--- <--- <--- <--- <--- <--- <-|
017B CB6F	BIT	5,A	; Test bit 5 of result ST0, SE byte = Seek End	    |
017D 28F9	JR	Z,$0178	; Jump if Seek not finished ---> ---> ---> ---> --->|
017F E650	AND	$50
0181 20DE	JR	NZ,$0161 ; Jump to CPM_TO_COBRA if HD or US0 are 1
0183 CD48FD	CALL	$FD48	; Call 8272_CMD_SIS <--- <--- <---|
0186 FE80	CP	$80	; Check if Invalid Command issue  | (check if SIS ended abnormally)
0188 20F9	JR	NZ,$0183 ; jump if not ---> ---> ---> --->|
				; *** the above loop goes until SIS becomes Invalid Command because it does not immediately follow a Seek or Recalibrate command
				; *** it is used as No-Op command, to place the FDC in a standby or no operation state.
018A DBF5	IN	A,($F5)	; read 8272 Status Register <--- <--- <--- <-----|
018C E60F	AND	$0F	; Check if any FDD is in Seek Mode (Main Status Register bits 0-3)
018E 20FA	JR	NZ,$018A ; jump if any FDD is in Seek Mode ---> ---> --->|
0190 0603	LD	B,$03	; loop counter - next loop goes 3 times
0192 D9		EXX		; <---- <--- <--- <--- <--- <---|
0193 ED4BA4FC	LD	BC,($FCA4) ; B=$02 (1 arg after 8272 cmd opcode), C=$4A (8272 Read ID command opcode with MFM)
0197 CD2CFD	CALL	$FD2C	; Call 8272_CMD to send Read ID command to 8272
019A CD4FFD	CALL	$FD4F	; Call 8272_READ and save	| Read ID result bytes at $FCB2-$FCB8
019D E6C0	AND	$C0	; Check for Abnormal Termination (bits 6-7 of ST0)
019F D9		EXX		;				|
01A0 2804	JR	Z,$01A6 ; jump if normal termination ------> --->|
01A2 10EE	DJNZ	$0192	; ----> ---> ---> ---> ---> --->| 3 attempts to read a proper ID Address Mark from disk
01A4 18BB	JR	$0161	; Jump to CPM_TO_COBRA			 |
01A6 21B5FC	LD	HL,$FCB5 ; <---- <---- <---- <---- <---- <---- <-|
01A9 11ABFC	LD	DE,$FCAB
01AC 010400	LD	BC,$0004
01AF EDB0	LDIR		; copy the last 4 Read ID result bytes from $FCB2-$FCB8 to $FCAB-$FCAE (C, H, R, N)    *** when done, HL=$FCB9, DE=$FCAF ***
01B1 2B		DEC	HL	; HL=$FCB8
01B2 46		LD	B,(HL)	; B = 4th Read ID result byte: N (bytes/sector) which is 5 (128x2^5=4096) for this stupidly "protected" system
01B3 2B		DEC	HL	; HL=$FCB7
01B4 7E		LD	A,(HL)	; A = 3rd Read ID result byte: R (sector number)
01B5 12		LD	(DE),A	; ($FCAF)=sector number
01B6 C5		PUSH	BC	; *** SAVE BC ***   <---- <---- <---- <---- <---- <---- <---- <----| this loop goes N=5 times or until no error occured while reading
01B7 AF		XOR	A	; A=00								   |
01B8 32F0FC	LD	($FCF0),A ; ($FCF0)=$00		location $FCF0 used as a flag: ($FCF0)=FF right after a track has been completely read
01BB 21F7FC	LD	HL,$FCF7 ; value for set CTC0 interrupt vector to, when CTC1+2_INIT is called next
01BE CD0CFD	CALL	$FD0C	; Call CTC1+2_INIT - sets CTC0 interrupt vector to $FCF7	   |
01C1 23		INC	HL	; HL=$FCF8, ($FCF8)=$A2=part of the opcode for the INI instruction |
01C2 CBDE	SET	3,(HL)	; now ($FCF8)=$AA, so at $FCF7 now we have the opcode $EDAA which is the Z80 instruction IND (instead of INI) - some smart way to hide the fact that system sectors are written in reverse on disk !!!
01C4 ED4BA6FC	LD	BC,($FCA6) ; B=$09, C=$C6 (8272 Read Data command opcode with MFM and MT(MultiTrack))
01C8 CD2CFD	CALL	$FD2C	; Call 8272_CMD to send Read Data command to 8272		   |
01CB 2A98FC	LD	HL,($FC98) ; HL=$3FFF = top address for saving system tracks data (sectors read normally but saving to mem will be done downwards, to $0000)
01CE 76		HALT		; <---- <---- <---- <---- <---- <-----| during this loop both sides of one system track (2 sectors x 4096 bytes each) are read from disk and saved to mem
01CF DBF5	IN	A,($F5)	; read 8272 Status Register	      |				   |
01D1 E620	AND	$20	; test bit 5 (0 means non-DMA execution phase has ended)	   |
01D3 20F9	JR	NZ,$01CE ; jump if not ended ----> ----> ---->|				   |
01D5 229AFC	LD	($FC9A),HL ; save the current sector data saving address for next system track, to ($FC9A-$FC9B)
01D8 2A92FC	LD	HL,($FC92) ; HL=FD09 = interrupt vector for the routine call below (address of CTC1 Interrupt Service Routine)
01DB CD0CFD	CALL	$FD0C	; Call CTC1+2_INIT - sets CTC0 interrupt vector to $FD09 (disables CTC0 Interrupt Service Routine)
01DE CD4FFD	CALL	$FD4F	; Call 8272_READ and save result bytes at FCB2-FCB8		   |
01E1 3AF0FC	LD	A,($FCF0) ; FLAG byte = FF right after a track has been completely read	   |
01E4 B7		OR	A	; test if FLAG byte = 00 (track still being read)		   |
01E5 C1		POP	BC	; *** RESTORE BC ***						   |
01E6 2805	JR	Z,$01ED ; ----> ----> ----> ----> ----> ----> ---->|			   |
01E8 7E		LD	A,(HL)	; A=(FCB2) first Read Data result byte     | which is ST0	   |
01E9 E6D8	AND	$D8	; check error bits in ST0		   |			   |
01EB 2805	JR	Z,$01F2	; jump if no error--> ---->|		   |			   |
01ED 10C7	DJNZ	$01B6	; ----> ----> ----> ----> ----> ----> ---->+----> ----> ----> ---->|
01EF C361FD	JP	$FD61	; jump to CPM_TO_COBRA	   | (if reading errors occured)
01F2 21ABFC	LD	HL,$FCAB ; <----- <---- <---- <----| ($FCAB)=cylinder number (C, 4th Read ID result byte)
01F5 34		INC	(HL)	; increment cylinder number
01F6 2A9AFC	LD	HL,($FC9A) ; HL = the current saving address
01F9 2298FC	LD	($FC98),HL ; Overwrite the initial (top) saving address with the current one
01FC 23		INC	HL	; When this routine is called the second time to read the second system track,
				; at this point the current saving address in HL will be $0000 - 1 = $FFFF.
				; So INC HL will bring it to $0000 since after the second call of this procedure
				; a JP (HL) is executed (see the end of main code) to jumpstart the CP/M system.
01FD C9		RET

01FE 00		DEFB	$00
01FF 00		DEFB	$00
0200 55		DEFB	$55
0201 73		DEFB	$73
0202 65		DEFB	$65
0203 72		DEFB	$72
0204 20		DEFB	$20
0205 24		DEFB	$24
0206 2C		DEFB	$2C
0207 20		DEFB	$20
0208 46		DEFB	$46
0209 69		DEFB	$69
020A 6C		DEFB	$6C
020B 65		DEFB	$65
020C 20		DEFB	$20
020D 6E		DEFB	$6E
020E 6F		DEFB	$6F
020F 74		DEFB	$74
0210 20		DEFB	$20
0211 66		DEFB	$66
0212 6F		DEFB	$6F
0213 75		DEFB	$75
0214 6E		DEFB	$6E
0215 64		DEFB	$64
0216 24		DEFB	$24
0217 20		DEFB	$20
0218 44		DEFB	$44
0219 72		DEFB	$72
021A 69		DEFB	$69
021B 76		DEFB	$76
021C 65		DEFB	$65
021D 3A		DEFB	$3A
021E 20		DEFB	$20
021F 24		DEFB	$24
0220 2C		DEFB	$2C
0221 20		DEFB	$20
0222 55		DEFB	$55
0223 73		DEFB	$73
0224 65		DEFB	$65
0225 72		DEFB	$72
0226 3A		DEFB	$3A
0227 20		DEFB	$20
0228 24		DEFB	$24
0229 20		DEFB	$20
022A 46		DEFB	$46
022B 69		DEFB	$69
022C 6C		DEFB	$6C
022D 65		DEFB	$65
022E 20		DEFB	$20
022F 43		DEFB	$43
0230 6F		DEFB	$6F
0231 75		DEFB	$75
0232 6E		DEFB	$6E
0233 74		DEFB	$74
0234 3A		DEFB	$3A
0235 20		DEFB	$20
0236 24		DEFB	$24
0237 2C		DEFB	$2C
0238 20		DEFB	$20
0239 24		DEFB	$24
023A 46		DEFB	$46
023B 72		DEFB	$72
023C 65		DEFB	$65
023D 65		DEFB	$65
023E 20		DEFB	$20
023F 52		DEFB	$52
0240 2F		DEFB	$2F
0241 57		DEFB	$57
0242 20		DEFB	$20
0243 53		DEFB	$53
0244 70		DEFB	$70
0245 61		DEFB	$61
0246 63		DEFB	$63
0247 65		DEFB	$65
0248 3A		DEFB	$3A
0249 20		DEFB	$20
024A 24		DEFB	$24
024B 46		DEFB	$46
024C 69		DEFB	$69
024D 6C		DEFB	$6C
024E 65		DEFB	$65
024F 20		DEFB	$20
0250 63		DEFB	$63
0251 6C		DEFB	$6C
0252 6F		DEFB	$6F
0253 73		DEFB	$73
0254 65		DEFB	$65
0255 20		DEFB	$20
0256 65		DEFB	$65
0257 72		DEFB	$72
0258 72		DEFB	$72
0259 6F		DEFB	$6F
025A 72		DEFB	$72
025B 24		DEFB	$24
025C 54		DEFB	$54
025D 79		DEFB	$79
025E 70		DEFB	$70
025F 65		DEFB	$65
0260 20		DEFB	$20
0261 43		DEFB	$43
0262 6F		DEFB	$6F
0263 6E		DEFB	$6E
0264 74		DEFB	$74
0265 72		DEFB	$72
0266 6F		DEFB	$6F
0267 6C		DEFB	$6C
0268 2D		DEFB	$2D
0269 43		DEFB	$43
026A 20		DEFB	$20
026B 74		DEFB	$74
026C 6F		DEFB	$6F
026D 20		DEFB	$20
026E 71		DEFB	$71
026F 75		DEFB	$75
0270 69		DEFB	$69
0271 74		DEFB	$74
0272 2C		DEFB	$2C
0273 20		DEFB	$20
0274 61		DEFB	$61
0275 6E		DEFB	$6E
0276 79		DEFB	$79
0277 20		DEFB	$20
0278 6F		DEFB	$6F
0279 74		DEFB	$74
027A 68		DEFB	$68
027B 65		DEFB	$65
027C 72		DEFB	$72
027D 20		DEFB	$20
027E 74		DEFB	$74
027F 6F		DEFB	$6F
0280 20		DEFB	$20
0281 63		DEFB	$63
0282 6F		DEFB	$6F
0283 6E		DEFB	$6E
0284 74		DEFB	$74
0285 69		DEFB	$69
0286 6E		DEFB	$6E
0287 75		DEFB	$75
0288 65		DEFB	$65
0289 3A		DEFB	$3A
028A 20		DEFB	$20
028B 24		DEFB	$24
028C 5C		DEFB	$5C
028D 20		DEFB	$20
028E 20		DEFB	$20
028F 20		DEFB	$20
0290 20		DEFB	$20
0291 24		DEFB	$24
0292 3A		DEFB	$3A
0293 20		DEFB	$20
0294 44		DEFB	$44
0295 72		DEFB	$72
0296 69		DEFB	$69
0297 76		DEFB	$76
0298 65		DEFB	$65
0299 20		DEFB	$20
029A 43		DEFB	$43
029B 68		DEFB	$68
029C 61		DEFB	$61
029D 72		DEFB	$72
029E 61		DEFB	$61
029F 63		DEFB	$63
02A0 74		DEFB	$74
02A1 65		DEFB	$65
02A2 72		DEFB	$72
02A3 69		DEFB	$69
02A4 73		DEFB	$73
02A5 74		DEFB	$74
02A6 69		DEFB	$69
02A7 63		DEFB	$63
02A8 73		DEFB	$73
02A9 5C		DEFB	$5C
02AA 24		DEFB	$24
02AB 3A		DEFB	$3A
02AC 20		DEFB	$20
02AD 31		DEFB	$31
02AE 32		DEFB	$32
02AF 38		DEFB	$38
02B0 20		DEFB	$20
02B1 42		DEFB	$42
02B2 79		DEFB	$79
02B3 74		DEFB	$74
02B4 65		DEFB	$65
02B5 20		DEFB	$20
02B6 52		DEFB	$52
02B7 65		DEFB	$65
02B8 63		DEFB	$63
02B9 6F		DEFB	$6F
02BA 72		DEFB	$72
02BB 64		DEFB	$64
02BC 20		DEFB	$20
02BD 43		DEFB	$43
02BE 61		DEFB	$61
02BF 70		DEFB	$70
02C0 61		DEFB	$61
02C1 63		DEFB	$63
02C2 69		DEFB	$69
02C3 74		DEFB	$74
02C4 79		DEFB	$79
02C5 5C		DEFB	$5C
02C6 24		DEFB	$24
02C7 3A		DEFB	$3A
02C8 20		DEFB	$20
02C9 4B		DEFB	$4B
02CA 69		DEFB	$69
02CB 6C		DEFB	$6C
02CC 6F		DEFB	$6F
02CD 62		DEFB	$62
02CE 79		DEFB	$79
02CF 74		DEFB	$74
02D0 65		DEFB	$65
02D1 20		DEFB	$20
02D2 44		DEFB	$44
02D3 72		DEFB	$72
02D4 69		DEFB	$69
02D5 76		DEFB	$76
02D6 65		DEFB	$65
02D7 20		DEFB	$20
02D8 43		DEFB	$43
02D9 61		DEFB	$61
02DA 70		DEFB	$70
02DB 61		DEFB	$61
02DC 63		DEFB	$63
02DD 69		DEFB	$69
02DE 74		DEFB	$74
02DF 79		DEFB	$79
02E0 5C		DEFB	$5C
02E1 24		DEFB	$24
02E2 3A		DEFB	$3A
02E3 20		DEFB	$20
02E4 33		DEFB	$33
02E5 32		DEFB	$32
02E6 20		DEFB	$20
02E7 42		DEFB	$42
02E8 79		DEFB	$79
02E9 74		DEFB	$74
02EA 65		DEFB	$65
02EB 20		DEFB	$20
02EC 44		DEFB	$44
02ED 69		DEFB	$69
02EE 72		DEFB	$72
02EF 65		DEFB	$65
02F0 63		DEFB	$63
02F1 74		DEFB	$74
02F2 6F		DEFB	$6F
02F3 72		DEFB	$72
02F4 79		DEFB	$79
02F5 20		DEFB	$20
02F6 45		DEFB	$45
02F7 6E		DEFB	$6E
02F8 74		DEFB	$74
02F9 72		DEFB	$72
02FA 69		DEFB	$69
02FB 65		DEFB	$65
02FC 73		DEFB	$73
02FD 5C		DEFB	$5C
02FE 24		DEFB	$24
02FF 3A		DEFB	$3A
0300 20		DEFB	$20
0301 43		DEFB	$43
0302 68		DEFB	$68
0303 65		DEFB	$65
0304 63		DEFB	$63
0305 6B		DEFB	$6B
0306 65		DEFB	$65
0307 64		DEFB	$64
0308 20		DEFB	$20
0309 44		DEFB	$44
030A 69		DEFB	$69
030B 72		DEFB	$72
030C 65		DEFB	$65
030D 63		DEFB	$63
030E 74		DEFB	$74
030F 6F		DEFB	$6F
0310 72		DEFB	$72
0311 79		DEFB	$79
0312 20		DEFB	$20
0313 45		DEFB	$45
0314 6E		DEFB	$6E
0315 74		DEFB	$74
0316 72		DEFB	$72
0317 69		DEFB	$69
0318 65		DEFB	$65
0319 73		DEFB	$73
031A 5C		DEFB	$5C
031B 24		DEFB	$24
031C 3A		DEFB	$3A
031D 20		DEFB	$20
031E 52		DEFB	$52
031F 65		DEFB	$65
0320 63		DEFB	$63
0321 6F		DEFB	$6F
0322 72		DEFB	$72
0323 64		DEFB	$64
0324 73		DEFB	$73
0325 2F		DEFB	$2F
0326 20		DEFB	$20
0327 45		DEFB	$45
0328 78		DEFB	$78
0329 74		DEFB	$74
032A 65		DEFB	$65
032B 6E		DEFB	$6E
032C 74		DEFB	$74
032D 5C		DEFB	$5C
032E 24		DEFB	$24
032F 3A		DEFB	$3A
0330 20		DEFB	$20
0331 52		DEFB	$52
0332 65		DEFB	$65
0333 63		DEFB	$63
0334 6F		DEFB	$6F
0335 72		DEFB	$72
0336 64		DEFB	$64
0337 73		DEFB	$73
0338 2F		DEFB	$2F
0339 20		DEFB	$20
033A 42		DEFB	$42
033B 6C		DEFB	$6C
033C 6F		DEFB	$6F
033D 63		DEFB	$63
033E 6B		DEFB	$6B
033F 5C		DEFB	$5C
0340 24		DEFB	$24
0341 3A		DEFB	$3A
0342 20		DEFB	$20
0343 53		DEFB	$53
0344 65		DEFB	$65
0345 63		DEFB	$63
0346 74		DEFB	$74
0347 6F		DEFB	$6F
0348 72		DEFB	$72
0349 73		DEFB	$73
034A 2F		DEFB	$2F
034B 20		DEFB	$20
034C 54		DEFB	$54
034D 72		DEFB	$72
034E 61		DEFB	$61
034F 63		DEFB	$63
0350 6B		DEFB	$6B
0351 5C		DEFB	$5C
0352 24		DEFB	$24
0353 3A		DEFB	$3A
0354 20		DEFB	$20
0355 52		DEFB	$52
0356 65		DEFB	$65
0357 73		DEFB	$73
0358 65		DEFB	$65
0359 72		DEFB	$72
035A 76		DEFB	$76
035B 65		DEFB	$65
035C 64		DEFB	$64
035D 20		DEFB	$20
035E 54		DEFB	$54
035F 72		DEFB	$72
0360 61		DEFB	$61
0361 63		DEFB	$63
0362 6B		DEFB	$6B
0363 73		DEFB	$73
0364 5C		DEFB	$5C
0365 24		DEFB	$24
0366 70		DEFB	$70
0367 72		DEFB	$72
0368 69		DEFB	$69
0369 6E		DEFB	$6E
036A 74		DEFB	$74
036B 65		DEFB	$65
036C 72		DEFB	$72
036D 5C		DEFB	$5C
036E 24		DEFB	$24
036F 66		DEFB	$66
0370 69		DEFB	$69
0371 6C		DEFB	$6C
0372 65		DEFB	$65
0373 3A		DEFB	$3A
0374 20		DEFB	$20
0375 24		DEFB	$24
0376 5C		DEFB	$5C
0377 4F		DEFB	$4F
0378 75		DEFB	$75
0379 74		DEFB	$74
037A 70		DEFB	$70
037B 75		DEFB	$75
037C 74		DEFB	$74
037D 20		DEFB	$20
037E 64		DEFB	$64
037F 69		DEFB	$69
0380 72		DEFB	$72
0381 65		DEFB	$65
0382 63		DEFB	$63
0383 74		DEFB	$74
0384 65		DEFB	$65
0385 64		DEFB	$64
0386 20		DEFB	$20
0387 74		DEFB	$74
0388 6F		DEFB	$6F
0389 20		DEFB	$20
038A 74		DEFB	$74
038B 68		DEFB	$68
038C 65		DEFB	$65
038D 20		DEFB	$20
038E 24		DEFB	$24
038F 20		DEFB	$20
0390 24		DEFB	$24
0391 20		DEFB	$20
0392 20		DEFB	$20
0393 24		DEFB	$24
0394 52		DEFB	$52
0395 2F		DEFB	$2F
0396 4F		DEFB	$4F
0397 20		DEFB	$20
0398 24		DEFB	$24
0399 52		DEFB	$52
039A 2F		DEFB	$2F
039B 57		DEFB	$57
039C 20		DEFB	$20
039D 24		DEFB	$24
039E 53		DEFB	$53
039F 59		DEFB	$59
03A0 53		DEFB	$53
03A1 20		DEFB	$20
03A2 24		DEFB	$24
03A3 44		DEFB	$44
03A4 49		DEFB	$49
03A5 52		DEFB	$52
03A6 20		DEFB	$20
03A7 24		DEFB	$24
03A8 2C		DEFB	$2C
03A9 20		DEFB	$20
03AA 53		DEFB	$53
03AB 79		DEFB	$79
03AC 73		DEFB	$73
03AD 74		DEFB	$74
03AE 65		DEFB	$65
03AF 6D		DEFB	$6D
03B0 20		DEFB	$20
03B1 46		DEFB	$46
03B2 69		DEFB	$69
03B3 6C		DEFB	$6C
03B4 65		DEFB	$65
03B5 73		DEFB	$73
03B6 20		DEFB	$20
03B7 50		DEFB	$50
03B8 72		DEFB	$72
03B9 65		DEFB	$65
03BA 73		DEFB	$73
03BB 65		DEFB	$65
03BC 6E		DEFB	$6E
03BD 74		DEFB	$74
03BE 24		DEFB	$24
03BF 5C		DEFB	$5C
03C0 49		DEFB	$49
03C1 6E		DEFB	$6E
03C2 76		DEFB	$76
03C3 61		DEFB	$61
03C4 6C		DEFB	$6C
03C5 69		DEFB	$69
03C6 64		DEFB	$64
03C7 20		DEFB	$20
03C8 46		DEFB	$46
03C9 69		DEFB	$69
03CA 6C		DEFB	$6C
03CB 65		DEFB	$65
03CC 20		DEFB	$20
03CD 4E		DEFB	$4E
03CE 61		DEFB	$61
03CF 6D		DEFB	$6D
03D0 65		DEFB	$65
03D1 20		DEFB	$20
03D2 65		DEFB	$65
03D3 72		DEFB	$72
03D4 72		DEFB	$72
03D5 6F		DEFB	$6F
03D6 72		DEFB	$72
03D7 24		DEFB	$24
03D8 5C		DEFB	$5C
03D9 49		DEFB	$49
03DA 6E		DEFB	$6E
03DB 73		DEFB	$73
03DC 75		DEFB	$75
03DD 66		DEFB	$66
03DE 66		DEFB	$66
03DF 69		DEFB	$69
03E0 63		DEFB	$63
03E1 69		DEFB	$69
03E2 65		DEFB	$65
03E3 6E		DEFB	$6E
03E4 74		DEFB	$74
03E5 20		DEFB	$20
03E6 4D		DEFB	$4D
03E7 65		DEFB	$65
03E8 6D		DEFB	$6D
03E9 6F		DEFB	$6F
03EA 72		DEFB	$72
03EB 79		DEFB	$79
03EC 20		DEFB	$20
03ED 65		DEFB	$65
03EE 72		DEFB	$72
03EF 72		DEFB	$72
03F0 6F		DEFB	$6F
03F1 72		DEFB	$72
03F2 24		DEFB	$24
03F3 5C		DEFB	$5C
03F4 2A		DEFB	$2A
03F5 2A		DEFB	$2A
03F6 20		DEFB	$20
03F7 57		DEFB	$57
03F8 41		DEFB	$41
03F9 52		DEFB	$52
03FA 4E		DEFB	$4E
03FB 49		DEFB	$49
03FC 4E		DEFB	$4E
03FD 47		DEFB	$47
03FE 20		DEFB	$20
03FF 2A		DEFB	$2A
0400 1A		LD	A,(DE)		; ####### Useless code from here on most likely
0401 77		LD	(HL),A
0402 23		INC	HL
0403 56		LD	D,(HL)
0404 77		LD	(HL),A
0405 C9		RET	

0406 FB		EI	
0407 3AF8FD	LD	A,($FDF8)
040A E603	AND	$03
040C F630	OR	$30
040E 329D72	LD	($729D),A
0411 CB4F	BIT	1,A
0413 3E00	LD	A,$00
0415 21EAF6	LD	HL,$F6EA
0418 2805	JR	Z,$041F
041A F640	OR	$40
041C 21CAF6	LD	HL,$F6CA
041F 2259F6	LD	($F659),HL
0422 224AFB	LD	($FB4A),HL
0425 2B		DEC	HL
0426 56		LD	D,(HL)
0427 2B		DEC	HL
0428 5E		LD	E,(HL)
0429 ED5340FB	LD	($FB40),DE
042D CD906F	CALL	$6F90
0430 CD3F70	CALL	$703F
0433 C5		PUSH	BC
0434 F3		DI
0435 D9		EXX	
0436 E1		POP	HL
0437 B7		OR	A
0438 ED52	SBC	HL,DE
043A C8		RET	Z

043B E1		POP	HL
043C 2E00	LD	L,$00
043E E9		JP	(HL)
043F 21076E	LD	HL,$6E07
0442 F6FF	OR	$FF
0444 AE		XOR	(HL)
0445 C0		RET	NZ

0446 77		LD	(HL),A
0447 F6FF	OR	$FF
0449 32096E	LD	($6E09),A
044C 3A56F6	LD	A,($F656)
044F F605	OR	$05
0451 2186F9	LD	HL,$F986
0454 CBC6	SET	0,(HL)
0456 1811	JR	$0469
0458 AF		XOR	A
0459 32036E	LD	($6E03),A
045C 32096E	LD	($6E09),A
045F 3A56F6	LD	A,($F656)
0462 F606	OR	$06
0464 2186F9	LD	HL,$F986
0467 CB86	RES	0,(HL)
0469 4F		LD	C,A
046A E607	AND	$07
046C 320A6E	LD	($6E0A),A
046F 060A	LD	B,$0A
0471 C5		PUSH	BC
0472 CD5871	CALL	$7158
0475 AF		XOR	A
0476 325BF6	LD	($F65B),A
0479 CD39F6	CALL	$F639
047C 2185F9	LD	HL,$F985
047F 220000	LD	($0000),HL