10 REM > Cyl1to0
   20 REM Move data from cylinder-1 based to cylinder-0 based
   30 :
   40 size%=(HIMEM-LOMEM-2048)AND&FF00:DIM mem% size%-1:off%=&100
   50 PROCassm:?IDEcommand=&08:REPEATUNTIL?IDEstatus<128:REM Initialise
   60 sector%=1:cylinder%=0:head%=0:dev%=0:count%=1:sz%=0:PROCideSize(64,3)
   70 INPUT"Enter IDE drive to move data: "dev%
   80 PROCid:PRINT"Drive size: &";~tot%;" - ";tot%DIV4096;"M"
   90 INPUT"Press RETURN to start"A$
  100 ptr%=0:REPEATlen%=tot%-ptr%:IFlen%*256>size%:len%=size%DIV256
  110   PRINTCHR$13;"Reading &";~ptr%+off%;:PROCRead(mem%,len%,ptr%+off%,dev%)
  120   PRINTCHR$13;"Writing &";~ptr%;:PROCWrite(mem%,len%,ptr%,dev%)
  130 ptr%=ptr%+len%:UNTILptr%>=tot%:PRINTCHR$13;"Finished"SPC10
  140 END
  150 :
  160 DEFPROCRead(mem%,len%,lau%,dev%):REPEAT
  170   !addr%=mem%:sec%?2=lau%:sec%?1=(lau%AND&FF00)DIV256:sec%?0=((lau%AND&FF0000)DIV65536)OR(dev%*64):?num%=1:num%?1=sz%:A%=USRrd%
  180 mem%=mem%+256:len%=len%-1:lau%=lau%+1:UNTILlen%<1:ENDPROC
  190 :
  200 DEFPROCWrite(mem%,len%,lau%,dev%):REPEAT
  210   !addr%=mem%:sec%?2=lau%:sec%?1=(lau%AND&FF00)DIV256:sec%?0=((lau%AND&FF0000)DIV65536)OR(dev%*64):?num%=1:num%?1=sz%:A%=USRwr%
  220 mem%=mem%+256:len%=len%-1:lau%=lau%+1:UNTILlen%<1:ENDPROC
  230 :
  240 :
  250 DEFFNh0(A%,N%)=RIGHT$("0000000"+STR$~A%,N%)
  260 DEFFNd(A%,N%)=RIGHT$("        "+STR$A%,N%)
  270 :
  280 DEFPROCid:LOCAL A%
  290 FOR A%=0 TO 255 STEP4:mem%!A%=0:mem%!(A%+256)=0:NEXT
  300 !addr%=mem%:Y%=dev%*16:num%?1=sz%:CALL id%
  310 big%=FALSE:IFmem%?&3A=0:big%=TRUE:mem%?&3A=mem%?&39:mem%?&39=0
  320 IFmem%?&101+mem%?&136+mem%?&139=0:mem%?&136=mem%?&3A:mem%?&139=mem%?&36:tot%=(256*mem%?&136+mem%?&36)*mem%?&37*mem%?&38:mem%?&101=(tot%DIV((mem%?3)*(mem%?6)))DIV256
  330 tot%=(256*mem%?&136+mem%?&36)*mem%?&37*mem%?&38
  340 ENDPROC
  350 :
  360 DEFPROCideInit:PROCideSize(64,3):ENDPROC
  370 DEFPROCideSize(spt%,hds%)
  380 ?&FC42=spt%:?&FC43=spt%
  390 ?&FC46=hds%:?&FC47=&91:REM Initialise parameters
  400 ENDPROC
  410 :
  420 DEFPROCassm
  430 mc%=mc%:IFmc%=0:DIMmc% 511
  440 addr%=&80:sec%=&85:num%=&88
  450 IDEdata=&FC40:IDEerror=&FC41:IDEcount=&FC42:IDEsector=&FC43
  460 IDEcylinder=&FC44:IDEhead=&FC46:IDEstatus=&FC47:IDEcommand=&FC47
  470 FORP=0 TO 1
  480   P%=mc%:[OPT P*2
  490   .id%
  500   LDA &FF:BMI idescape
  510   LDA IDEstatus:BMI id%
  520   TYA:AND #16:STA IDEhead   :\ Device
  530   LDA #&EC  :STA IDEcommand :\ &EC=Identify
  540   LDY #0:LDX #1:STX num%
  550   CLC:JMP TransferLoop
  560   .idescape
  570   RTS
  580   :
  590   .WaitForData
  600   LDA &FC47:AND #8:BEQ WaitForData
  610   LDA &FC47:RTS
  620   :
  630   .WaitNotBusy
  640   PHP:JSR L806F                    :\ Get IDE status
  650   AND #&80:BNE WaitNotBusy+1:PLP   :\ Wait for IDE not busy
  660   BIT &CC:RTS
  670   :
  680   .L806F
  690   PHP:LDA &FC47:STA &8D
  700   LDA &FC47:CMP &8D:BNE L806F+1
  710   PLP:RTS
  720   :
  730   .rd%:LDA #&08:STA &84:CLC:BCC CommandStart
  740   .wr%:LDA #&0A:STA &84:SEC:BCS CommandStart
  750   :
  760   .CommandStart                    :\ C=R/W, &8E/F=>block
  770   LDA #&7F:STA &8E:LDA #0:STA &8F  :\ &8E/F=>block
  780   PHP:JSR SetGeometry:PLP
  790   .CommandLoop
  800   LDX #2:.Twice
  810   JSR SetSector:LDY #0             :\ Set sector, count, command
  820   .TransferLoop
  830   JSR WaitForData:AND #&21:BNE TransError
  840   \.TransferLoop
  850   BIT &CD:\BVS TransTube:BCC IORead
  860   .IOWrite
  870   LDA (&80),Y:STA &FC40:LDA num%+1:BEQ TransferByte
  880   INC &81:LDA (&80),Y:STA &FC48:DEC &81:BRA TransferByte
  890   .IORead
  900   LDA &FC40:STA (&80),Y:LDA num%+1:BEQ TransferByte
  910   INC &81:LDA &FC48:STA (&80),Y:DEC &81:BRA TransferByte
  920   :
  930   .TransferByte
  940   LDA &FC47:AND #8:BEQ TransError  :\ Run out of data
  950   INY:BNE TransferLoop:\INC &81     :\ Loop for 256 bytes
  960   LDA &FC47:AND #&21:BNE TransError:\ Error occured
  970   DEX:BNE Twice
  980   INC &87:BNE TransCount           :\ Increment sector
  990   INC &86:BNE TransCount:INC &85
 1000   .TransCount
 1010   DEC &88:BNE CommandLoop          :\ Loop for all sectors
 1020   LDA #0                           :\ Done, no errors
 1030   .TransError
 1040   LDA &FC47:LDX &FC41:RTS
 1050   :
 1060   .SetGeometry
 1070   JSR WaitNotBusy                          :\ Should check device
 1080   LDA #64:STA &FC42:STA &FC43              :\ 64 sectors per track
 1090   LDA sec%:LSR A:LSR A:ORA #3:AND #&13
 1100   STA &FC46:LDA #&91:STA &FC47      :\ 4 heads per cylinder
 1110   RTS
 1120   :
 1130   .SetSector
 1140   PHP:JSR WaitNotBusy                      :\ Save CC/CS Read/Write
 1150   LDY #8:LDA #1:STA &FC42                  :\ One sector
 1160   CLC:LDA (&8E),Y:AND #63:ADC #1:STA &FC43 :\ Set sector b0-b5
 1170   DEY:LDA (&8E),Y:ADC #0:STA &FC44         :\ Set sector b8-b15
 1180   DEY:LDA (&8E),Y:PHA:AND #&3F:ADC #0:STA &FC45 :\ Set sector b16-b20
 1190   PLA:ROL A:ROL A:ROL A:ROL A              :\ Get Drive 0/1
 1200   INY:INY:EOR (&8E),Y:AND #&02:EOR (&8E),Y :\ Merge Drive and Head
 1210   JSR SetDrive:DEY:DEY:DEY:LDA (&8E),Y     :\ Get command &08 or &0A
 1220   .SetCommand
 1230   AND #2:PHA:EOR #2:LSR A:LSR A            :\ Copy ~b1 into Cy
 1240   PLA:ASL A:ASL A:ASL A:ORA #&20           :\ Translate CS->&20 or CC->&30
 1250   STA &FC47:PLP:RTS                        :\ Set command &08 or &0A
 1260   :
 1270   .SetDrive
 1280   ROL A:ROL A:ROL A:AND #&13:STA &FC46:RTS :\ Set device + sector b6-b7
 1290   :
 1300 ]NEXT:ENDPROC