;------------------------------------------------------------------------------;
; LORDS OF MIDNIGHT 1985 BEYOND PAL DISK VERSION LOADER DISASSEMBLY			   ; 
; COMMODORE 64 (PART 1) AND 1541 DISK DRIVE CODE (PART 2).					   ;
; DISASSEMBLY AND COMMENTS BY MR.MOUSE/XENTAX/GENESIS PROJECT, 2023			   ;
; HTTP://C64.XENTAX.COM														   ;
; 																			   ;
; Use Notepad++ for preferred viewing. 										   ;
;------------------------------------------------------------------------------;
; 																			   ;
; PART 1 - COMMODORE 64 LOADER CODE.		 								   ;
; $0308-$0584, execution at $0334											   ;
; 																			   ;
;------------------------------------------------------------------------------;
0308   34                   ???                		; execution address lo byte 
0309   03                   ???                		; execution address hi byte 
030a   86 ae                stx $ae					; junk until $0334, except $0316
030c   00                   brk
030d   00                   brk
030e   00                   brk
030f   00                   brk
0310   4c 48 b2             jmp $b248
0313   00                   brk
0314   31 ea                and ($ea),y
0316   66 fe                ror $fe					; $0316 is the XOR value to decrypt the loader code below with: $66
0318   c1 fe                cmp ($fe,x)
031a   4a                   lsr a
031b   f3                   ???                
031c   91 f2                sta ($f2),y
031e   0e f2 50             asl $50f2
0321   f2                   ???                
0322   33                   ???                
0323   f3                   ???                
0324   57                   ???                
0325   f1 34                sbc ($34),y
0327   03                   ???                
0328   ea                   nop
0329   f6 3e                inc $3e,x
032b   f1 2f                sbc ($2f),y
032d   f3                   ???                
032e   4d 4c a5             eor $a54c
0331   f4                   ???                
0332   ed f5 
; --------------------------------------------------PROGRAM START
0334   a9 0b				lda #$0b				; turn off screen
0336   8d 11 d0             sta $d011
0339   ad 15 d0             lda $d015				; get sprite state
033c   85 a3                sta $a3
033e   a9 00                lda #$00				; set sprites to 0
0340   8d 15 d0             sta $d015
0343   4e 53 03             lsr $0353				; unhide the EOR line below 
0346   2e 54 03             rol $0354
0349   6e 55 03             ror $0355
034c   a2 03                ldx #$03				; start decrypting the loader code by XORing every byte from $0365 onwards (3 pages, so 768 bytes in total) with the value in $0316: $66
034e   a0 00                ldy #$00				; reset byte counter 
0350   b9 65 03   l0350     lda $0365,y				; get XORed byte 
0353   4d 16 03				eor $0316          		; was 9a 0b 06 (to hide the eor routine), XOR it with $66 to get the original value back 
0356   99 65 03				sta $0365,y				; store the decrypted byte back at its location
0359   c8                   iny						; increase byte counter 
035a   d0 f4                bne l0350				; do a full page of 256, if not done do next byte 
035c   ee 52 03				inc $0352				; increase hi byte of source location
035f   ee 58 03				inc $0358				; increase hi byte of destination location 
0362   ca					dex						; decrease page counter 
0363   d0 eb				bne $0350				; if not done with 3 pages, do next page 
;---------------------------------------------------;
; de-xored part :, code continues here right away after dexored 
;---------------------------------------------------;
0365   a9 08                lda #$08			
0367   20 0c ed             jsr $ed0c				; command devices on the serial bus to LISTEN (device 8)
036a   a9 f2                lda #$f2			
036c   20 b9 ed             jsr $edb9				; send secondary address after LISTEN (f2)
036f   a9 23                lda #$23
0371   20 dd ed             jsr $eddd				; output a byte to the serial bus (23)
0374   a9 32                lda #$32
0376   20 dd ed             jsr $eddd				; output a byte to the serial bus (32)
0379   20 fe ed             jsr $edfe				; command serial bus to UNLISTEN
037c   a9 08                lda #$08
037e   20 0c ed             jsr $ed0c				; command devices on the serial bus to LISTEN (device 8)
0381   a9 6f                lda #$6f
0383   20 b9 ed             jsr $edb9				; send secondary address after LISTEN (6f)
0386   a0 00                ldy #$00
0388   b9 9a 03   l0388     lda $039a,y				; send command line "B-E 2 0 14 0" execute at $0500
038b   20 dd ed             jsr $eddd				; So tell the drive to load block (sector) 0 at track 14 into its buffer 2 ($0500) and execute from top
038e   c8                   iny						
038f   c0 0c                cpy #$0c
0391   d0 f5                bne l0388				; all bytes of the string below sent? if not send the next byte 
0393   20 fe ed             jsr $edfe				; command serial bus to UNLISTEN
0396   78                   sei						; disable interrupts
0397   4c 89 04             jmp l0489				; start the loader loop 
;---------------------------------------------------String: "B-E 2 0 14 0"
039a   42                   ???                
039b   2d 45 20             and $2045
039e   32                   ???                
039f   20 30 20             jsr $2030
03a2   31 34                and ($34),y
03a4   20 30 
;---------------------------------------------------GET BYTE 
0400   a9 27      l0400     lda #$27				; set ATN high, clock out high, data out to low (pull it true, set data line to active) 
0402   8d 00 dd             sta $dd00
0405   2c 00 dd   l0405     bit $dd00				; wait for clock-out on 1541 side to go inactive (bit to 1 on DD00 clock-in side, inverted logic)
0408   50 fb                bvc l0405
040a   a9 03                lda #$03				; release all ATN, Clock out, Data out , the 1541 side waits for the data line to become inactive , so setting data-out to 0 will do that
040c   8d 00 dd             sta $dd00
040f   a2 07                ldx #$07				; 2
0411   ca         l0411     dex						; 7*5 (2 + branch) = 35
0412   10 fd                bpl l0411				; 3 when taken , together 40 cycles waiting (=40*0,9852 = 39,408 microseconds)
0414   a2 03                ldx #$03				; plus two more cycles = 	41,37 microseconds delay before starting to read the data on the line , the 1541 puts data on the lines already after 25 microseconds
0416   ad 00 dd   l0416     lda $dd00				; get the bits 
0419   0a                   asl a
041a   08                   php
041b   0a                   asl a
041c   26 bd                rol $bd
041e   28                   plp
041f   26 bd                rol $bd
0421   ca                   dex
0422   10 f2                bpl l0416				; first run takes 32 cycles = 31,526, subsequent ones take 30 cycles = 29,556 microseconds, last 29 cycles = 28,57 microseconds
0424   a9 17                lda #$17				; set bit 4, clock-out to low (active clock line) , set data out to inactive (high 5V) and ATN also to inactive 
0426   8d 00 dd             sta $dd00
0429   a5 bd                lda $bd
042b   60                   rts
;---------------------------------------------------256 BYTES PART loading (two chuncks of 128 bytes)
042c   a9 02      l042c     lda #$02				; set ff to 2
042e   85 ff                sta $ff
0430   20 43 04   l0430     jsr l0443				; get data from 1541 (128 bytes for temp buffer and then copied to actual memory location in fb/fc), THE SECOND HALF OF THE FULL 256 BYTE PAGE IS COMING IN FIRST and stored to $0680-$06ff, then copied to 
0433   a9 80                lda #$80				; update fb/fc pointer, do it + 128 bytes 
0435   18                   clc
0436   65 fb                adc $fb
0438   85 fb                sta $fb
043a   90 02                bcc l043e				; hi byte need updating? 
043c   e6 fc                inc $fc
043e   c6 ff      l043e     dec $ff					; decrease 128-chunk counter 
0440   d0 ee                bne l0430				; not done yet, get next chunk , which is the FIRST HALF of the 256 byte page, that will be stored temporarily at $0600-067f
0442   60                   rts						; return
;---------------------------------------------------GET 128 BYTES PAGE 
0443   a0 80      l0443     ldy #$80				; set y to 128 bytes 
0445   a9 27                lda #$27				; set ATN high, clock out high, data out to low (pull it true, set data line to active) 
0447   8d 00 dd             sta $dd00
044a   2c 00 dd   l044a     bit $dd00				; wait for clock-out on 1541 side to go inactive (bit to 1 on DD00 clock-in side, inverted logic)
044d   50 fb                bvc l044a
044f   a9 03                lda #$03
0451   8d 00 dd             sta $dd00				; release all ATN, Clock out, Data out , the 1541 side waits for the data line to become inactive , so setting data-out to 0 will do that
0454   a2 0a                ldx #$0a				; waste cycles 10*5-1 = 49 cycles 
0456   ca         l0456     dex
0457   d0 fd                bne l0456
0459   a2 04      l0459     ldx #$04				; get 4 times 2 bits 
045b   ad 00 dd   l045b     lda $dd00				; get the bits and get the byte in bd 
045e   2a                   rol a					; move bit 7 (1800: 1) to bit 0, bit 6 (1800: 3) to carry 
045f   2a                   rol a
0460   66 bd                ror $bd					; rotate bit 6 (1800: 3) into bit 7 of bd 
0462   6a                   ror a					; rotate bit 7 (1800: 1) in carry 
0463   66 bd                ror $bd					; rotate carry (bit 7) to bit 7 of bd, shifting (bit 6) one position to the right, so sequence (from 1800) 13XXXXXX
0465   8e 20 d0             stx $d020				; visual effect on border 
0468   ca                   dex
0469   d0 f0                bne l045b				; get 8 bits in total 
046b   b5 bd                lda $bd,x				; since x is 0 get the byte in bd 
046d   91 c3                sta ($c3),y				; store that in temp buffer $0600,y
046f   c8                   iny						; y+1
0470   d0 e7                bne l0459				; all 128 bytes gotten? if not get next 
0472   a9 17                lda #$17				
0474   8d 00 dd             sta $dd00				; set bit 4, clock-out to low (active clock line) , set data out to inactive (high 5V) and ATN also to inactive 
0477   a2 80                ldx #$80				; now copy the 128 bytes 
0479   a0 00                ldy #$00				; from the temp buffer to the offset pointed to by fb/fc , the current offset of the data loaded 
047b   bd 00 06   l047b     lda $0600,x
047e   91 fb                sta ($fb),y
0480   45 02                eor $02					; calculate a checksum of it 
0482   85 02                sta $02					
0484   c8                   iny
0485   e8                   inx
0486   d0 f3                bne l047b				; all gotten and checksum calculated 
0488   60                   rts						; return 
;---------------------------------------------------LOADER LOOP START 
0489   2c 00 dd   l0489     bit $dd00				; D AND .A --> Z , bit 7 -> N, bit 6 -> V
048c   70 fb                bvs l0489				; wait until clock in goes low 
048e   a9 17                lda #$17				; set atn to high, set clock out to low (pull it true), data out to high 
0490   8d 00 dd             sta $dd00
0493   ad 20 d0             lda $d020
0496   48                   pha
0497   a9 00                lda #$00				; prepare temp buffer in $0600
0499   a2 06                ldx #$06
049b   85 c3                sta $c3
049d   86 c4                stx $c4
049f   20 00 04             jsr l0400				; get number of larger memory parts to load 
04a2   85 be                sta $be					; number of larger memory parts to load 
04a4   20 00 04   l04a4     jsr l0400
04a7   85 fb                sta $fb					; starting offset in fb/fc of parts to load 
04a9   20 00 04             jsr l0400
04ac   85 fc                sta $fc
04ae   20 00 04             jsr l0400
04b1   85 fd                sta $fd					; counter of memory size to load in fd/fe
04b3   20 00 04             jsr l0400
04b6   85 fe                sta $fe
04b8   20 00 04             jsr l0400				; get checksum and store in 02
04bb   85 02                sta $02
04bd   a5 fe      l04bd     lda $fe					; check hi byte for more memory to load 
04bf   d0 20                bne l04e1				; yes, go load it 
04c1   a5 fd                lda $fd					; hi byte 0, still lo byte higher than 0?
04c3   f0 2d                beq l04f2				; if not, done loading part 
04c5   85 b4                sta $b4					; store rest to load in b4 
04c7   a0 00                ldy #$00				; set y to 0 
04c9   20 00 04             jsr l0400				; get a confirmatory byte 
04cc   f0 03                beq l04d1				; if 0 then go on and load the number of byte left in b4 
04ce   4c 59 05             jmp l0559				; if the byte was not 0 we have an errot, goto 0559
04d1   20 00 04   l04d1     jsr l0400				; get byte 
04d4   91 fb                sta ($fb),y				; store at intended memory location
04d6   45 02                eor $02					; calculate XOR checksum , this should end being 0 when done loading the part 
04d8   85 02                sta $02					; store new checksum
04da   c8                   iny						; iny 
04db   c4 b4                cpy $b4					; reached number of bytes to get ?
04dd   d0 f2                bne l04d1				; if not get next byte 
04df   f0 11                beq l04f2				; yes done, check the checksum
;---------------------------------------------------
04e1   20 00 04   l04e1     jsr l0400				; get confirmatory 0 from 1541
04e4   d0 73                bne l0559				; if not zero, we have a problem, go to 0559
04e6   20 2c 04             jsr l042c				; get 256 in two parts of 128 bytes to copy to last memory location in fb/fc
04e9   a5 fe                lda $fe					; hi byte of CHUNK_SIZE 0? 
04eb   f0 05                beq l04f2				; if yes, check the checksum 
04ed   c6 fe                dec $fe					; decrease CHUNK_SIZE_HI
04ef   4c bd 04             jmp l04bd				; jump 04bd , be careful-> if fe is 0 after the dec this will lead to loading the lo byte rest 
;---------------------------------------------------
04f2   a5 02      l04f2     lda $02					; check the checksum, this should be 0 
04f4   d0 63                bne l0559				; if not, we have issues. 
04f6   c6 be                dec $be					; decrease CHUNKS counter 
04f8   d0 aa                bne l04a4				; not zero? then more parts to load, get info for next part and load it! 
;---------------------------------------------------START GAME
04fa   68                   pla						; nothing more to load. Get A back from stack
04fb   8d 20 d0             sta $d020				; store that in border colour 
04fe   20 00 04             jsr l0400				; get hi byte of game starting location 
0501   48                   pha						; push on stack 
0502   20 00 04             jsr l0400				; get lo byte of game starting location 
0505   48                   pha						; push that on stack 
0506   a5 a3                lda $a3					; reset $d015
0508   8d 15 d0             sta $d015
050b   a9 07                lda #$07				; reset $dd00, inactivate data line, clock line and atn line 
050d   8d 00 dd             sta $dd00
0510   a9 1b                lda #$1b				; show screen 
0512   8d 11 d0             sta $d011
0515   a0 36                ldy #$36				; copy the screen clear code below to $0200
0517   b9 23 05   l0517     lda $0523,y
051a   99 00 02             sta $0200,y
051d   88                   dey
051e   10 f7                bpl l0517
0520   4c 00 02             jmp $0200				; then jump to the routine to clear the screen and set basic to start the game 
0523   a9 20                lda #$20				; copy spaces to the screen memory 
0525   a0 00                ldy #$00
0527   99 34 03   l0527     sta $0334,y
052a   99 34 04             sta $0434,y
052d   99 34 05             sta $0534,y
0530   99 34 06             sta $0634,y
0533   c8                   iny
0534   d0 f1                bne l0527
0536   a9 e4                lda #$e4				; Execution address of BASIC instruction executor routine back to default a7e4
0538   8d 08 03             sta $0308
053b   a9 a7                lda #$a7
053d   8d 09 03             sta $0309
0540   a9 ca                lda #$ca				; Execution address of CHROUT, general purpose data output routine back to default f1ca
0542   8d 26 03             sta $0326
0545   a9 f1                lda #$f1
0547   8d 27 03             sta $0327
054a   84 9d                sty $9d					; surpress system error messages 
054c   84 c6                sty $c6					; clear keyboard buffer 
054e   58                   cli
054f   60                   rts						; return (will lead to jump to game start (stacked address +1) 
0550   20 33 a5             jsr $a533
0553   20 59 a6             jsr $a659
0556   4c ae a7             jmp $a7ae
;---------------------------------------------------ERROR LOADING, SHOW ERROR AND HANG
0559   68         l0559     pla						; get a back
055a   8d 20 d0             sta $d020				; restore border colour 
055d   a0 1a                ldy #$1a				; copy error process routine below to $0200 and run it 
055f   b9 6b 05   l055f     lda $056b,y
0562   99 00 02             sta $0200,y
0565   88                   dey
0566   10 f7                bpl l055f
0568   4c 00 02             jmp $0200
056b   a9 93                lda #$93				; Clear screen by sending the Clear character to e716 kernal print routine 
056d   20 16 e7             jsr $e716
0570   a9 1b                lda #$1b				; enable screen 
0572   8d 11 d0             sta $d011
0575   58                   cli						; clear interrupts 
0576   a0 00                ldy #$00				; print '  error'
0578   b9 69 a3   l0578     lda $a369,y
057b   f0 06                beq l0583
057d   20 16 e7             jsr $e716
0580   c8                   iny
0581   d0 f5                bne l0578
0583   f0 fe      l0583     beq l0583				; and hang 
;------------------------------------------------------------------------------;
; 																			   ;
; PART 2 - 1541 DISK LOADER CODE.		 								   	   ;
; $0500-$05ff, execution at $0500											   ;
; $0300-$048d, entry point at $0300				   							   ;
; 																			   ;
;------------------------------------------------------------------------------;
0500   4c 12 05             jmp l0512
;---------------------------------------------------;CLEAR BUFFERS $0300 and $0400 (destroy the loader) and Reinitialize the drive 
0503   a0 00                ldy #$00
0505   99 00 03   l0505     sta $0300,y
0508   99 00 04             sta $0400,y
050b   c8                   iny
050c   d0 f7                bne l0505
050e   58                   cli						; enable interrupts
050f   4c 42 d0             jmp $d042				; reinitialize the drive 
;---------------------------------------------------;LOAD THE LOADER
0512   a9 0e      l0512     lda #$0e				; Use buffer #4 ($0700+), find T/S in $0E/F, so set track to $0e , sector 3, So track 14 sector 3
0514   85 0e                sta $0e					; This will load a sector that has a wrong checksum in the datablock on purpose. 
0516   a9 03                lda #$03
0518   85 0f                sta $0f
051a   a9 80                lda #$80				; then put job code READ SECTOR $80 in buffer 4 job cue. 
051c   85 04                sta $04
051e   a5 04      l051e     lda $04					; wait until done 
0520   30 fc                bmi l051e
0522   85 c1                sta $c1					; this will lead to a checksum error, $05, which is stored in c1 
0524   a9 0e                lda #$0e				; set sector to 14 as well 
0526   85 0f                sta $0f					; This will load another sector that has a wrong checksum in the datablock
0528   a9 80                lda #$80				; set block read command 
052a   85 04                sta $04
052c   a5 04      l052c     lda $04
052e   30 fc                bmi l052c				; wait until done 
0530   25 c1                and $c1					; and the checksum error code $05 gotten with the one in $c1, which of course will keep c1 at $05, this is the XOR seed for decryption. 
0532   85 c1                sta $c1					; store it 
;---------------------------------------------------READ CODE PAGES FROM TRACK 36 AND DECODE THEM 
0534   a9 24                lda #$24				; set track for buffer 0 to 36
0536   85 06                sta $06
0538   a9 0b                lda #$0b				; and sector to b (11)
053a   85 07                sta $07
053c   a9 b0                lda #$b0				; 10110000 binary command code , and drive 0 (this 1541), command code (without bit 7) $30, FIND SECTOR 
053e   85 00                sta $00					; so command to find the sector 11 in track 36 
0540   a5 00      l0540     lda $00					; wait until command done 
0542   30 fc                bmi l0540
0544   78                   sei						; no interrupts
0545   a9 03                lda #$03				; set currently active buffer pointer to $0300
0547   85 31                sta $31
0549   20 00 fe             jsr $fe00				; Disable write mode
054c   20 72 05             jsr l0572				; read the block and decode it to $0300
054f   a9 01                lda #$01				; get sector 1 now 
0551   85 07                sta $07
0553   a9 04                lda #$04				; buffer to $0400
0555   85 31                sta $31
0557   20 72 05             jsr l0572				; get the block and decode it to $0400
055a   a0 00                ldy #$00				; now decode all of $0300-$04ff after xoring with the value previously gotten in $c1 
055c   b9 00 03   l055c     lda $0300,y
055f   45 c1                eor $c1
0561   99 00 03             sta $0300,y
0564   b9 00 04             lda $0400,y
0567   45 c1                eor $c1
0569   99 00 04             sta $0400,y
056c   c8                   iny
056d   d0 ed                bne l055c
056f   4c 00 03             jmp $0300				; execute the new code 
;---------------------------------------------------;GET SECTOR BASED ON FINDING A SPECIFIC GCR HEADER 
0572   ad 00 1c   l0572     lda $1c00
0575   09 0c                ora #$0c
0577   29 9f                and #$9f
0579   8d 00 1c             sta $1c00				; 10001100, motor on, drive led on/off, density select 0 0, sync detect on?
057c   a9 ee                lda #$ee				; 11101110 Attach Byte Ready to oVerflow flag. Head control Bit 5 is Write?
057e   8d 0c 1c             sta $1c0c
0581   20 a9 05             jsr l05a9				; generate GCR header to look for and once found start reading the sector GCR in $0300 + $01ba-01ff
0584   50 fe      l0584     bvc l0584				; wait for byte available from reading 
0586   b8                   clv
0587   ad 01 1c             lda $1c01				; get byte read 
058a   91 30                sta ($30),y				; store at 30/31, y=0 at start 
058c   c8                   iny						; y+1
058d   d0 f5                bne l0584				; if not 256, do next 
058f   a0 ba                ldy #$ba				; okay all first 256 done, now the rest of the GCR bytes 
0591   50 fe      l0591     bvc l0591				; wait for byte ready 
0593   b8                   clv
0594   ad 01 1c             lda $1c01				; get the byte 
0597   99 00 01             sta $0100,y				; store at 01ba and further, (y is $ba at start)
059a   c8                   iny						; y+1
059b   d0 f4                bne l0591				; until all are done 
059d   20 e0 f8             jsr $f8e0				; convert GCR data in $0300-03ff + $01ba-01ff to 256 normal bytes 
05a0   20 e9 f5             jsr $f5e9				; CHKBLK ($F5E9) to calculate the data blk checksum, store it in CHKSUM, and JSR to BINGCR ($F78F) to convert the dummy data block into its GCR write image.
05a3   a9 ec                lda #$ec				; detach Byte Ready to Overflow flag 
05a5   8d 0c 1c             sta $1c0c
05a8   60                   rts						; done getting sector 
;--------------------------------------------------
05a9   20 af 05   l05a9     jsr l05af				; generate GCR header block to locate and then locate it 
05ac   4c e8 05             jmp l05e8
;---------------------------------------------------; generate GCR of header block to find
05af   a5 12      l05af     lda $12					; Unit #0 expected sector header ID. 'M'
05b1   85 16                sta $16
05b3   a5 13                lda $13					; Unit #0 expected sector header ID. 'T' (MidnightT)
05b5   85 17                sta $17
05b7   a5 06                lda $06					; Buffer #0 track 
05b9   85 18                sta $18
05bb   a5 07                lda $07					; Buffer #0 sector 
05bd   85 19                sta $19
05bf   a9 00                lda #$00				; generate checksum by xoring 0 with the id and track and sector bytes 
05c1   45 16                eor $16
05c3   45 17                eor $17
05c5   45 18                eor $18
05c7   45 19                eor $19
05c9   85 1a                sta $1a					; generated checksum in $1a , First sector (11) this is $36, Second sector (1) this is $3c
05cb   20 34 f9             jsr $f934				; convert header block to GCR at $24-$2d
05ce   a2 5a                ldx #$5a				; check counter 
;---------------------------------------------------;
05d0   20 e8 05   l05d0     jsr l05e8				; Wait for SYNC mark 
05d3   50 fe      l05d3     bvc l05d3				; wait for byte available 
05d5   b8                   clv
05d6   ad 01 1c             lda $1c01
05d9   d9 24 00             cmp $0024,y				; compare with generated header block 
05dc   d0 06                bne l05e4
05de   c8                   iny
05df   c0 08                cpy #$08
05e1   d0 f0                bne l05d3
05e3   60                   rts						; return if all are equal 
05e4   ca         l05e4     dex						; decrease check routine counter 
05e5   d0 e9                bne l05d0				; not equal then do next 
05e7   60                   rts
;---------------------------------------------------;Wait for SYNC mark (from KERNAL)
; A SYNC mark is 10 or more consecutive l's bits written onto the disk. It is used to identify the start of a block of information recorded on disk.
; The first character following a SYNC mark is used to determine whether this is a header block ($08) or a data block ($07).
05e8   a9 d0      l05e8     lda #$d0				; Store $D0 in TIMER1 ($1805) to allow a maximum wait of 20 milliseconds for a sync before timing out.
05ea   8d 05 18             sta $1805
05ed   a9 03                lda #$03				; Load .A with $03 (the error code for a NO SYNC FOUND error)
05ef   2c 05 18   l05ef     bit $1805				; Test bit 7 of TIMER1 ($1805) to check for a time-out. 
05f2   10 f0                bpl l05e4				; timed out Wait for SYNC, check if we can do another wait 
05f4   2c 00 1c             bit $1c00				; Test bit 7 of DSKCNT ($1C00) to check for a sync. 
05f7   30 f6                bmi l05ef				; If no sync, branch back to 05ef to wait some more.
05f9   ad 01 1c             lda $1c01				; Load .A from DATA2 to reset the PA latch, then clear the 6502' s overflow flag, and Y, then rts
05fc   b8                   clv
05fd   a0 00                ldy #$00
05ff   60                   rts
                            .end
;---------------------------------------------------;
; DECODED 1541 LOADER FROM $0300-$0500				;
;---------------------------------------------------;
0300   4c 89 03             jmp l0389				; entry point 
;---------------------------------------------------;SEND BYTE 
0303   49 ff      l0303     eor #$ff				; invert all bits of the byte to send, since the c64 does not have a NOT gate for the incoming clock and data lines
0305   85 c1                sta $c1					; store in C1 to use in the sending 
0307   a9 01                lda #$01				; $1800 will be ANDed with $01 below. As long as that is 0 (wait for data-out to become active on c64 side)
0309   2c 00 18   l0309     bit $1800				; the data-in line is low
030c   f0 fb                beq l0309				; wait until data-in line goes high 
030e   a2 00                ldx #$00				; signal data out inactive (high - 5V) and clock out inactive (high 5V), the c64 side waits for clock-in to go to 1 
0310   8e 00 18             stx $1800
0313   2c 00 18   l0313     bit $1800				; wait until c64 signals data-in line goes low 
0316   d0 fb                bne l0313
0318   a2 03                ldx #$03				; okay , c64 signaled ready to receive. Let's go. We have about 40 microseconds to send the first bits (when the c64 is ready)
031a   a9 00      l031a     lda #$00				; set bits to 0 for new byte 	
031c   06 c1                asl $c1					; shift c1 left 
031e   2a                   rol a					; rotate any bit into carry from the left into .A
031f   0a                   asl a					; and shift it one more to the left 
0320   06 c1                asl $c1					; get the next bit in carry if present 
0322   2a                   rol a					; rotate that one in .A from the left as well
0323   0a                   asl a					; and shift all bits once more to the left. So now the two bit states are ready to be sent in bit 1 and 3 of $1800 (data out, clock out)
													; this takes 22 cycles = 22 microseconds in the first run + 3 cycles of the sta = 25 cycles/microseconds in total. That is 28 cycles for each next 2 bits 
0324   8d 00 18             sta $1800				; send the bits , at the last cycle of 4. 
0327   ca                   dex						; x-1 
0328   10 f0                bpl l031a				; if x>=0 we are not done sending 8 bits yet 
032a   e8         l032a     inx						; delay now with 4 + 7*4-1 =31 cycles 
032b   e0 03                cpx #$03
032d   d0 fb                bne l032a
032f   a9 08                lda #$08				; set clock-out to active (0 V) , seen as 0 at C64 side , but also set as active by c64 
0331   8d 00 18             sta $1800
0334   60                   rts						; return 
;---------------------------------------------------;SEND 256 BYTES IN TWO TIMES 128 BYTES, SECOND LOADED HALF FIRST, THEN FIRST LOADED HALF (THEY WERE SAVED FLIPPED ON THE DISK)
0335   a0 80      l0335     ldy #$80				; set y offset to $80 
0337   a2 00                ldx #$00				; set x counter to 0
0339   bd 00 06   l0339     lda $0600,x				; copy first half of $0600
033c   99 00 05             sta $0500,y				; to second half of $0500
033f   e8                   inx						; X+1
0340   c8                   iny						; Y+1
0341   d0 f6                bne l0339				; until 128 bytes are copied 
0343   a9 05                lda #$05				; set to buffer $0500
0345   85 c3                sta $c3
0347   20 4e 23             jsr $234e				; to 034e?, x is still $80 
034a   a9 06                lda #$06				; set buffer to $0600 and do the same (x is now 0)
034c   85 c3                sta $c3
;---------------------------------------------------;SEND 128 BYTES
034e   a0 80                ldy #$80				; 128 bytes 
0350   a9 01                lda #$01				; $1800 will be ANDed with $01 below. As long as that is 0 (wait for data-out to become active on c64 side)
0352   2c 00 18   l0352     bit $1800				; wait for C64 
0355   f0 fb                beq l0352				; if not active data-out yet, wait 
0357   a2 00                ldx #$00				; 
0359   8e 00 18             stx $1800				; signal data out inactive (high - 5V) and clock out inactive (high 5V), the c64 side waits for clock-in to go to 1 
035c   2c 00 18   l035c     bit $1800				; wait until c64 signals data-in line goes inactive
035f   d0 fb                bne l035c
0361   ea                   nop						; waste 2 cycles 
0362   a2 04      l0362     ldx #$04				; set x to 4 (4x2 bits)
0364   b1 c2                lda ($c2),y				; get byte to send from buffer 
0366   85 c1                sta $c1					; store at c1 
0368   ea                   nop						; waste 2 cycles 
0369   a9 00      l0369     lda #$00				; prepare byte to send , this will end up as inverted (as if EORed with FF) at the C64 end 
036b   66 c1                ror $c1					; ror c1 
036d   2a                   rol a					; rotate any carry in a 
036e   2a                   rol a					; and shift it one more left 
036f   66 c1                ror $c1					; rotate c1 to the right 
0371   2a                   rol a					; rotate carry bit state in 
0372   2a                   rol a					; shift it once more , so ultimately bit 0 becomes bit 3 to send, bit 1 becomes bit 1 to send. XXXXXX10 --> XXXX0X1X, that becomes 10XXXXXX at C64 end 
0373   8d 00 18             sta $1800				; send over the bits 1 and 3 
0376   ca                   dex						; x-1
0377   d0 f0                bne l0369				; still positive? then do next two bits 
0379   ea                   nop						; waste 2 cycles
037a   c8                   iny						; y=y+1
037b   d0 e5                bne l0362				; all 128 bytes done? 
037d   c8         l037d     iny						; waste cycles (first y becomes 1), this routine 3 times (2 cycles for this line)
037e   ea                   nop						; 2 more 
037f   c0 03                cpy #$03				; 2 more 
0381   d0 fa                bne l037d				; 3 more upon branch , total 26 cycles wasted 
0383   a9 08                lda #$08				; 
0385   8d 00 18             sta $1800				; set clock-out to active (0 V) , seen as 0 at C64 side , but also set as active by c64 
0388   60                   rts						; return 
;--------------------------------------------------- SEND CHUNKS TO C64 
0389   a9 08      l0389     lda #$08				; clock out active (pulled low to 0V), rest inactive, device number 00
038b   8d 00 18             sta $1800
038e   a9 00                lda #$00				; set offset of next byte in buffer 1 to 0 
0390   85 c2                sta $c2
0392   a9 0e                lda #$0e				; set track for buffer $0700 and $0600 to 14 
0394   85 0e                sta $0e
0396   85 0c                sta $0c			
0398   a9 04                lda #$04				; set sector for $0700 to 4
039a   85 0f                sta $0f
039c   a2 01                ldx #$01				; set read job for buffer number 4 (3+1) ($0700) --> GET THE CHUNK INFORMATION TABLE in $0700
039e   20 30 04             jsr l0430				; load sector and interleave buffer $0600 
03a1   ad 00 07             lda $0700				; get first gotten byte , number of chunks to load (CHUNK_COUNTER)
03a4   20 03 03             jsr l0303				; get ready to send that, and then send when C64 is ready 
03a7   a9 01                lda #$01				; set y counter to 1
03a9   85 c8                sta $c8					
03ab   a9 0f                lda #$0f				; get sector in 0d to $0f 
03ad   85 0d                sta $0d					; set sector for buffer $0600 to that 
;---------------------------------------------------;CHUNK LOAD 
03af   a4 c8      l03af     ldy $c8					; set y to counter 
03b1   b9 00 07             lda $0700,y				; C64_OFFSET_LO lo byte of memory location in the C64 to load the chunk to 	
03b4   20 03 03             jsr l0303				; send that byte over when the C64 is ready 
03b7   c8                   iny						; y+1
03b8   b9 00 07             lda $0700,y				; C64_OFFSET_HI hi byte of memory location in the c64 to load the chunk to
03bb   20 03 03             jsr l0303				; send that byte over when the C64 is ready 
03be   c8                   iny						; y+1
03bf   b9 00 07             lda $0700,y				; CHUNK_SIZE_LO, lo byte of the size of the chunk to load 
03c2   85 c4                sta $c4					; store in C4 as well for internal check 
03c4   20 03 03             jsr l0303				; send the byte to C64
03c7   c8                   iny						; y+1
03c8   b9 00 07             lda $0700,y				; CHUNK_SIZE_HI, hi byte of the size of the chunk to load
03cb   85 c5                sta $c5					; store in C5 as well for internal check
03cd   20 03 03             jsr l0303				; send the byte to C64
03d0   c8                   iny						; y+1
03d1   b9 00 07             lda $0700,y				; CHECKSUM_EOR, checksum for C64 side. Will be used as seed for continuous EOR with each new byte, to end in 0 when correct. 
03d4   20 03 03             jsr l0303				; send the byte to C64
03d7   c8                   iny						; y+1
03d8   84 c8                sty $c8					; store counter in C8
03da   a2 00      l03da     ldx #$00				; set x to 0 to point to buffer $0600 for next loading and sending session
03dc   20 30 04             jsr l0430				; load next sector 
03df   a9 00                lda #$00				; signal 0, all okay, to C64 
03e1   20 03 03             jsr l0303				; send the OK signal to C64
03e4   a5 c5                lda $c5					; check CHUNK_SIZE_HI 
03e6   d0 1a                bne l0402				; if not 0 there is more to send over
03e8   a5 c4                lda $c4					; hi byte is 0, what about CHUNK_SIZE_LO? 
03ea   f0 28                beq l0414				; also zero, no more bytes to send over 
03ec   85 c9                sta $c9					; still some left, set C9 to that and send them over 
03ee   a0 00                ldy #$00				; counter y to 0
03f0   a9 06                lda #$06				; set buffer to $0600
03f2   85 c3                sta $c3					; hi byte 
03f4   b1 c2      l03f4     lda ($c2),y				; get byte to send over 
03f6   49 ff                eor #$ff				; ! EOR that, will be EORed back by the send byte routine ! 
03f8   20 03 03             jsr l0303				; send the byte to the c64
03fb   c8                   iny						; y+1
03fc   c4 c9                cpy $c9					; are we done?
03fe   d0 f4                bne l03f4				; nope, send over the next byte 
0400   f0 12                beq l0414				; yep, check for more chunks 
;--------------------------------------------------	; SEND 256 BYTES (IN TWO TIMES 128, EACH FULL PAGE IS STORED ON DISK SECOND HALF FIRST, FIRST HALF LAST)
0402   20 35 03   l0402     jsr l0335				; SEND 256 bytes 
0405   a5 c5                lda $c5					; Check CHUNK_SIZE_HI, more pages to do ?
0407   f0 0b                beq l0414				; No, no more pages, then go to 0414 to see if there are more chunks to do 
0409   c6 c5                dec $c5					; decrease CHUNK_SIZE_HI
040b   a5 c5                lda $c5					; load it in .A
040d   05 c4                ora $c4					; or it with c4
040f   f0 03                beq l0414				; if 0 then done loading everything (unique case when a chunk is exactly a multiple of 256 bytes)
0411   4c da 03             jmp l03da				; there are more bytes, so go do those 
;---------------------------------------------------
0414   ce 00 07   l0414     dec $0700				; decrease CHUNK_COUNTER 
0417   d0 96                bne l03af				; More CHUNKS to load ? go do next 
0419   a4 c8                ldy $c8					; get the offset in buffer $0700
041b   b9 00 07             lda $0700,y				; get game start offset HI byte 
041e   20 03 23             jsr $2303				; send it to the C64
0421   c8                   iny						; y+1
0422   b9 00 07             lda $0700,y				; get game start offset LO byte 
0425   20 03 23             jsr $2303				; send it to the C64
0428   a9 00                lda #$00				; 
042a   8d 00 18             sta $1800				; signal data out inactive (high 5V) and clock out inactive (high 5V), the c64 side will do the same  
042d   4c 03 05             jmp $0503				; Destroy the loader code and reinitialize the drive 
;---------------------------------------------------;LOAD NEXT SECTOR
0430   a9 02      l0430     lda #$02				; set c7 to 2
0432   85 c7                sta $c7
0434   a9 03      l0434     lda #$03				; set c6 to 3
0436   85 c6                sta $c6
0438   a9 80      l0438     lda #$80				; load .a with 80 (job code for Read block)
043a   20 71 04             jsr l0471				; go do read block, x is buffer number, relative to $03
043d   90 3d                bcc l047c				; .A error was below 2, so all ok, interleave to next sector and return 
043f   c6 c6                dec $c6
0441   d0 f5                bne l0438
0443   c6 c7                dec $c7
0445   f0 0d                beq l0454				; no more attempts, we consider there to be a drive / read error
0447   a9 c0                lda #$c0				; BUMP, move drive header to track 1 
0449   20 71 04             jsr l0471
044c   a9 b0                lda #$b0				; Seek again the provided track and sector 
044e   20 71 04             jsr l0471
0451   4c 34 04             jmp l0434				; retry loading the sector 
;---------------------------------------------------DRIVE/READ ERROR
0454   a9 ff      l0454     lda #$ff				; error, signal that to the C64 by sending FF
0456   20 03 03             jsr l0303		
0459   a2 3c                ldx #$3c				; delay for drive LED flashing on and off 
045b   a0 00                ldy #$00
045d   ea         l045d     nop
045e   88                   dey
045f   d0 fc                bne l045d
0461   ca                   dex
0462   d0 f9                bne l045d
0464   ad 00 1c             lda $1c00				; set DRIVE LED on/off through XOR
0467   49 08                eor #$08
0469   29 fb                and #$fb
046b   8d 00 1c             sta $1c00
046e   4c 59 24             jmp $2459				; and continue flashing 
;---------------------------------------------------DO JOB CODE in .A in Buffer 3 + x
0471   95 03      l0471     sta $03,x
0473   58                   cli
0474   b5 03      l0474     lda $03,x				; wait until job done 
0476   30 fc                bmi l0474
0478   78                   sei
0479   c9 02                cmp #$02				; compare outcome with error code 2
047b   60                   rts						; and return 
;---------------------------------------------------INTERLEAVE SECTORS
047c   a5 0d      l047c     lda $0d					; get current sector number 
047e   18                   clc
047f   69 0b                adc #$0b				; add 11
0481   c9 15                cmp #$15				; compare with 21
0483   90 06                bcc l048b				; .a is lower than 21, set $0d and leave 
0485   e9 15                sbc #$15				; .a is higher than 21, subtract 21
0487   d0 02                bne l048b				; was it not zero? then skip decreasing the track number 
0489   c6 0c                dec $0c					; sector hit zero, decrease track number
048b   85 0d      l048b     sta $0d					; store sector 
048d   60                   rts
;---------------------------------------------------
