Patch ATALoad to boot from driver-less disks

Unreliable: currently this only works on QEMU
This commit is contained in:
Elliot Nunn 2019-08-23 19:01:56 +08:00
parent a05f8638d7
commit 9351898fb5
4 changed files with 575 additions and 0 deletions

281
ATALoad.a Normal file
View File

@ -0,0 +1,281 @@
; Asm ATALoad.a -o ATALoad.a.o; DumpObj ATALoad.a.o > ATALoad.dmp
; The python script does the rest.
; This is messy and brittle. I got very, very sick of it!
MAIN
MACHINE MC68030
lea $10(sp),a0 ; re-push the 12 bytes of arguments onto the stack
move.l -(a0),-(sp)
move.l -(a0),-(sp)
move.l -(a0),-(sp)
bsr.s OriginalFunc ; ... and call the function
add.l #$C,sp ; pop those copied arguments, we don't need them
cmp.l #$FFFFDB93,d0 ; ATANoDriverErr -> try our method
beq.s NewFunc
cmp.l #$FFFFDB92,d0 ; ATANoDDMErr -> try our method
beq.s NewFunc
rts ; don't try our method
OriginalFunc
string asis
dc.b 'Nsrt' ; placeholder for script to insert the clobbered LINK instruction
bra *+2+'ID' ; placeholder for script to jump to remainder of original function
var_regs equ -$4FA
ataPB equ -$4DA ; to
ataPBQType equ -$4D6
ataPBVers equ -$4D4
ataPBReserved2 equ -$4CE
ataPBFunctionCode equ -$4C8
ataPBIOSpeed equ -$4C7
ataPBFlags equ -$4C6
ataPBDeviceID equ -$4C2
ataPBTimeOut equ -$4BE
ataPBState equ -$4B2
; common part of PB ends at offset $30 = -$4AA
; this part below is a bit tricky...
ataPB34 equ -$4A6 ; 34
ataPB38 equ -$4A2 ; 38
ataPB3C equ -$49E ; 3c
ataPB40 equ -$49A ; 40
; -492...-48A = "task file"
ataPBTaskFile_ataTFCount equ -$491
ataPBTaskFile_ataTFSDH equ -$48C
ataPBTaskFile_ataTFCommand equ -$48B
; entire PB ends at offset $30 = -$4AA
; max possible PB size ends at $B8 = -$422
var_bstruct_0 equ -$422
var_bstruct_2 equ -$420
var_bstruct_4 equ -$41E
var_bstruct_6 equ -$41C
var_ddmidx equ -$41A
var_drvrcnt equ -$418
var_arg2 equ -$40E
var_ddmptr equ -$40C
var_buf1 equ -$408
var_buf2 equ -$208
var_flags equ -8
var_4 equ -4
arg_dev equ 8
arg_ddtype equ $C ; a long
arg_romdrvr equ $10
NewFunc
link a6,#-$4DA
movem.l d3-d7/a2-a4,-(sp)
; Wipe the stack frame to be safe
lea -$4DA(A6),A0
@lup clr.w (A0)+
cmp.l A0,A6
bne.s @lup
; Check that we are asked for an ATA driver
cmp.l #$00000701,arg_ddtype(a6) ; kDriverTypeMacATA
bne itr_fail
; Load the actual working driver
move.w #$FFFF,$B9E ; temp ROMMapInsert
move.l #'DRVR',-(SP)
move.w #53,-(SP) ; .ATADisk
dc.w $A9A0
movea.l (SP)+,A2
tst.l A2
beq itr_fail
movea.l (A2),A2
; Set pointers to the 512-byte scratch buffer and the param block
lea var_buf1(a6),a3
lea ataPB(a6),a4
; Set bit 31 ("RAM based driver at run time") in the d5 passed to DRVR
move.l #0,var_flags(a6)
tst.b arg_romdrvr+3(a6)
bne.s is_romdrvr
ori.b #$80,var_flags(a6) ; set the flag
is_romdrvr:
; Get the "IDENTIFY DEVICE" block with CHS information
move.l #0, $00(a4) ; ataPBLink
move.w #0, $04(a4) ; ataPBQType
move.b #2, $06(a4) ; --> ataPBVers
move.b #0, $13(a4) ; --> ataPBIOSpeed
move.w arg_dev+2(a6),d1
ext.l d1
move.l d1, $18(a4) ; --> ataPBDeviceID
move.l #0, $08(a4) ; ? ataPBReserved2
move.l #20000,$1C(a4) ; --> ataPBTimeOut
move.b #$13, $12(a4) ; --> ataPBFunctionCode = kATAMgrDriveIdentify
move.w #$2000,$14(a4) ; --> ataPBFlags = mATAFlagIORead
move.w #0, $28(a4) ; ? ataPBState
move.l a3, $38(a4) ; ataPBBuffer
sub.l #2,sp
move.l a4,-(sp)
dc.w $AAF1 ; ATAManager
move.w (sp)+,d0
ext.l d0
bne itr_return
; Parse the "IDENTIFY DEVICE" block
move.w 2(a3),var_bstruct_0(a6) ; typically 1041
move.w 6(a3),var_bstruct_2(a6) ; typically 0010
move.w $C(a3),var_bstruct_4(a6) ; typically 003f
move.w var_bstruct_2(a6),d0 ; can't safely get rid of these for some reason!
mulu.w var_bstruct_4(a6),d0
move.w d0,var_bstruct_6(a6)
; Send "Init drive parameters"
move.b #$1, $12(a4) ; --> ataPBFunctionCode = IO (not in headers)
move.w #0, $14(a4) ; --> ataPBFlags
move.w #0, $28(a4) ; ? ataPBState
move.b #$91, $48+$7(a4) ; ataPBTaskFile.ataTFCommand = kATAcmdInitDrive
move.l arg_dev(a6),d0 ; (leaving bit $40 as zero for CHS)
lsr.l #4,d0
and.l #$10,d0 ; master/slave bit
or.l #$A0,d0 ; sector size ? 512
move.w var_bstruct_2(a6),d1
sub.w #1,d1
or.w d1,d0 ; head number
move.b d0, $48+$6(a4) ; ataPBTaskFile.ataTFSDH
move.b var_bstruct_4+1(a6),$48+$1(a4); ataPBTaskFile.ataTFCount
sub.l #2,sp
move.l a4,-(sp)
dc.w $AAF1 ; ATAManager
move.w (sp)+,d0
; Loop over all partitions, ask the driver to pick a bootable one
move.w #$2000,ataPBFlags(a6)
move.l #$200,ataPB34(a6)
move.b #$20,ataPBTaskFile_ataTFCommand(a6)
move.l #1,d5 ; Initially check only one partition, increase this number later
moveq #0,d6 ; Partition index counter
tellDriverAboutPartitionLoop:
move.l d6,d0
addq.l #1,d6
cmp.l d0,d5
bcs.s itr_fail
move.l a3,ataPB38(a6)
move.l #$200,ataPB3C(a6)
move.b #1,ataPBTaskFile_ataTFCount(a6)
pea var_bstruct_0(a6)
move.l d6,-(sp)
pea ataPB(a6)
bsr paramblk_helper_function
subq.l #2,sp
pea ataPB(a6)
dc.w $AAF1 ;;;;;;;;;;;;;;;;;;;;;;;;; kATAcmdRead again (get next PM entry)
move.w (sp)+,d7
lea $C(sp),sp
moveq #0,d0
move.w (a3),d0
cmpi.l #'PM',d0
bne.s tellDriverAboutPartitionLoop
move.l 4(a3),d5 ; update the *real* number of partitions, so we don't end early
move.l var_flags(a6),-(sp) ; var_flags, obviously
move.w var_arg2(a6),d0
ext.l d0
move.l d0,-(sp) ; arg_dev+2 extended to a long, pretty much always zero
move.l a3,-(sp) ; pointer to this partition map entry
move.l a2,-(sp) ; pointer to driver
bsr *+2+'BT' ; BOOT function
move.l d0,d4
lea $10(sp),sp
move.w d4,d7 ; -1 means try a different partition, 0 means succes, otherwise error
cmpi.w #$FFFF,d7
beq.s tellDriverAboutPartitionLoop
tst.w d7
bne.s itr_fail
move.l d4,d0 ; the final pathway for success
bra.s itr_return
itr_fail:
move.l #$FFFFDB93,d0 ; ATANoDriverErr
itr_return:
movem.l var_regs(a6),d3-d7/a2-a4
unlk a6
rts
paramblk_helper_function:
link a6,#0
movem.l d6-d7/a3-a4,-(sp)
move.l $C(a6),d7
movea.l $10(a6),a3
movea.l $8(a6),a4
move.l $18(a4),d0
lsr.l #8,d0
moveq #1,d6
and.l d0,d6
clr.w $28(a4)
moveq #0,d0
move.w 6(a3),d0
move.l d7,d1
divu.l d0,d1
move.w d1,$4C(a4)
moveq #0,d0
move.w 4(a3),d0
move.l d7,d1
divu.l d0,d1
moveq #0,d0
move.w 2(a3),d0
tst.l d0
tdivs.l d0,d2:d1
moveq #$F,d0
and.l d2,d0
move.b d0,$4E(a4)
move.l d6,d0
lsl.l #4,d0
or.b d0,$4E(a4)
ori.b #$A0,$4E(a4)
moveq #0,d0
move.w 4(a3),d0
move.l d7,d1
tdivu.l d0,d2:d1
addq.b #1,d2
move.b d2,$4A(a4)
movem.l -$10(a6),d6-d7/a3-a4
unlk a6
rts
string c
mystring dc.b 'log from ATALoad ^n'
PrintHex ; A0 is already set to a number...
MOVE.L #4, D1 ; r4 arg (1: byte, 2: 2byte, else: 4byte)
MOVE.L #97, D0 ; call NKPrintHex
DC.W $FE1F
LEA mystring,A0
MOVE.L #96, D0 ; call NKXprintf
DC.W $FE1F
RTS ; stack is safe!
END

194
ATALoad.dmp Normal file
View File

@ -0,0 +1,194 @@
First: Flags=0 Version=2
Dictionary: Flags $00 FirstId 1
1: #0001
2: Main
Pad
Module: Flags=$10=(Main Local Code) Module="#0001"(1) Segment="Main"(2)
Content: Flags $08
Contents offset $0000 size $0236
00000000: 41EF 0010 'A...' LEA $0010(A7),A0
00000004: 2F20 '/ ' MOVE.L -(A0),-(A7)
00000006: 2F20 '/ ' MOVE.L -(A0),-(A7)
00000008: 2F20 '/ ' MOVE.L -(A0),-(A7)
0000000A: 6116 'a.' BSR.S *+$0018 ; 00000022
0000000C: DEFC 000C '....' ADDA.W #$000C,A7
00000010: 0C80 FFFF DB93 '......' CMPI.L #$FFFFDB93,D0
00000016: 6712 'g.' BEQ.S *+$0014 ; 0000002A
00000018: 0C80 FFFF DB92 '......' CMPI.L #$FFFFDB92,D0
0000001E: 670A 'g.' BEQ.S *+$000C ; 0000002A
00000020: 4E75 'Nu' RTS
00000022: 4E73 'Ns' RTE
00000024: 7274 'rt' MOVEQ #$74,D1 ; 't'
00000026: 6000 4944 '`.ID' BRA *+$4946 ; 0000496C
0000002A: 4E56 FB26 'NV.&' LINK A6,#$FB26
0000002E: 48E7 1F38 'H..8' MOVEM.L D3-D7/A2-A4,-(A7)
00000032: 41EE FB26 'A..&' LEA -$04DA(A6),A0
00000036: 4258 'BX' CLR.W (A0)+
00000038: BDC8 '..' CMPA.L A0,A6
0000003A: 66FA 'f.' BNE.S *-$0004 ; 00000036
0000003C: 0CAE 0000 0701 '......' CMPI.L #$00000701,$000C(A6)
000C
00000044: 6600 0164 'f..d' BNE *+$0166 ; 000001AA
00000048: 31FC FFFF 0B9E '1.....' MOVE.W #$FFFF,$0B9E
0000004E: 2F3C 4452 5652 '/<DRVR' MOVE.L #$44525652,-(A7) ; 'DRVR'
00000054: 3F3C 0035 '?<.5' MOVE.W #$0035,-(A7)
00000058: A9A0 '..' _GetResource ; A9A0
0000005A: 245F '$_' MOVEA.L (A7)+,A2
0000005C: 4A8A 'J.' TST.L A2
0000005E: 6700 014A 'g..J' BEQ *+$014C ; 000001AA
00000062: 2452 '$R' MOVEA.L (A2),A2
00000064: 47EE FBF8 'G...' LEA -$0408(A6),A3
00000068: 49EE FB26 'I..&' LEA -$04DA(A6),A4
0000006C: 42AE FFF8 'B...' CLR.L -$0008(A6)
00000070: 4A2E 0013 'J...' TST.B $0013(A6)
00000074: 6606 'f.' BNE.S *+$0008 ; 0000007C
00000076: 002E 0080 FFF8 '......' ORI.B #$80,-$0008(A6)
0000007C: 4294 'B.' CLR.L (A4)
0000007E: 426C 0004 'Bl..' CLR.W $0004(A4)
00000082: 197C 0002 0006 '.|....' MOVE.B #$02,$0006(A4)
00000088: 422C 0013 'B,..' CLR.B $0013(A4)
0000008C: 322E 000A '2...' MOVE.W $000A(A6),D1
00000090: 48C1 'H.' EXT.L D1
00000092: 2941 0018 ')A..' MOVE.L D1,$0018(A4)
00000096: 42AC 0008 'B...' CLR.L $0008(A4)
0000009A: 297C 0000 4E20 ')|..N ' MOVE.L #$00004E20,$001C(A4)
001C
000000A2: 197C 0013 0012 '.|....' MOVE.B #$13,$0012(A4)
000000A8: 397C 2000 0014 '9| ...' MOVE.W #$2000,$0014(A4)
000000AE: 426C 0028 'Bl.(' CLR.W $0028(A4)
000000B2: 294B 0038 ')K.8' MOVE.L A3,$0038(A4)
000000B6: 558F 'U.' SUBQ.L #$2,A7
000000B8: 2F0C '/.' MOVE.L A4,-(A7)
000000BA: AAF1 '..' DC.W $AAF1 ; TB 02F1
000000BC: 301F '0.' MOVE.W (A7)+,D0
000000BE: 48C0 'H.' EXT.L D0
000000C0: 6600 00EE 'f...' BNE *+$00F0 ; 000001B0
000000C4: 3D6B 0002 FBDE '=k....' MOVE.W $0002(A3),-$0422(A6)
000000CA: 3D6B 0006 FBE0 '=k....' MOVE.W $0006(A3),-$0420(A6)
000000D0: 3D6B 000C FBE2 '=k....' MOVE.W $000C(A3),-$041E(A6)
000000D6: 302E FBE0 '0...' MOVE.W -$0420(A6),D0
000000DA: C0EE FBE2 '....' MULU.W -$041E(A6),D0
000000DE: 3D40 FBE4 '=@..' MOVE.W D0,-$041C(A6)
000000E2: 197C 0001 0012 '.|....' MOVE.B #$01,$0012(A4)
000000E8: 426C 0014 'Bl..' CLR.W $0014(A4)
000000EC: 426C 0028 'Bl.(' CLR.W $0028(A4)
000000F0: 197C 0091 004F '.|...O' MOVE.B #$91,$004F(A4)
000000F6: 202E 0008 ' ...' MOVE.L $0008(A6),D0
000000FA: E888 '..' LSR.L #$4,D0
000000FC: 0280 0000 0010 '......' ANDI.L #$00000010,D0
00000102: 0080 0000 00A0 '......' ORI.L #$000000A0,D0
00000108: 322E FBE0 '2...' MOVE.W -$0420(A6),D1
0000010C: 5341 'SA' SUBQ.W #$1,D1
0000010E: 8041 '.A' OR.W D1,D0
00000110: 1940 004E '.@.N' MOVE.B D0,$004E(A4)
00000114: 196E FBE3 0049 '.n...I' MOVE.B -$041D(A6),$0049(A4)
0000011A: 558F 'U.' SUBQ.L #$2,A7
0000011C: 2F0C '/.' MOVE.L A4,-(A7)
0000011E: AAF1 '..' DC.W $AAF1 ; TB 02F1
00000120: 301F '0.' MOVE.W (A7)+,D0
00000122: 3D7C 2000 FB3A '=| ..:' MOVE.W #$2000,-$04C6(A6)
00000128: 2D7C 0000 0200 '-|....' MOVE.L #$00000200,-$04A6(A6)
FB5A
00000130: 1D7C 0020 FB75 '.|. .u' MOVE.B #$20,-$048B(A6) ; ' '
00000136: 7A01 'z.' MOVEQ #$01,D5
00000138: 7C00 '|.' MOVEQ #$00,D6
0000013A: 2006 ' .' MOVE.L D6,D0
0000013C: 5286 'R.' ADDQ.L #$1,D6
0000013E: BA80 '..' CMP.L D0,D5
00000140: 6568 'eh' BCS.S *+$006A ; 000001AA
00000142: 2D4B FB5E '-K.^' MOVE.L A3,-$04A2(A6)
00000146: 2D7C 0000 0200 '-|....' MOVE.L #$00000200,-$049E(A6)
FB62
0000014E: 1D7C 0001 FB6F '.|...o' MOVE.B #$01,-$0491(A6)
00000154: 486E FBDE 'Hn..' PEA -$0422(A6)
00000158: 2F06 '/.' MOVE.L D6,-(A7)
0000015A: 486E FB26 'Hn.&' PEA -$04DA(A6)
0000015E: 6100 005A 'a..Z' BSR *+$005C ; 000001BA
00000162: 558F 'U.' SUBQ.L #$2,A7
00000164: 486E FB26 'Hn.&' PEA -$04DA(A6)
00000168: AAF1 '..' DC.W $AAF1 ; TB 02F1
0000016A: 3E1F '>.' MOVE.W (A7)+,D7
0000016C: 4FEF 000C 'O...' LEA $000C(A7),A7
00000170: 7000 'p.' MOVEQ #$00,D0
00000172: 3013 '0.' MOVE.W (A3),D0
00000174: 0C80 0000 504D '....PM' CMPI.L #$0000504D,D0
0000017A: 66BE 'f.' BNE.S *-$0040 ; 0000013A
0000017C: 2A2B 0004 '*+..' MOVE.L $0004(A3),D5
00000180: 2F2E FFF8 '/...' MOVE.L -$0008(A6),-(A7)
00000184: 302E FBF2 '0...' MOVE.W -$040E(A6),D0
00000188: 48C0 'H.' EXT.L D0
0000018A: 2F00 '/.' MOVE.L D0,-(A7)
0000018C: 2F0B '/.' MOVE.L A3,-(A7)
0000018E: 2F0A '/.' MOVE.L A2,-(A7)
00000190: 6100 4254 'a.BT' BSR *+$4256 ; 000043E6
00000194: 2800 '(.' MOVE.L D0,D4
00000196: 4FEF 0010 'O...' LEA $0010(A7),A7
0000019A: 3E04 '>.' MOVE.W D4,D7
0000019C: 0C47 FFFF '.G..' CMPI.W #$FFFF,D7
000001A0: 6798 'g.' BEQ.S *-$0066 ; 0000013A
000001A2: 4A47 'JG' TST.W D7
000001A4: 6604 'f.' BNE.S *+$0006 ; 000001AA
000001A6: 2004 ' .' MOVE.L D4,D0
000001A8: 6006 '`.' BRA.S *+$0008 ; 000001B0
000001AA: 203C FFFF DB93 ' <....' MOVE.L #$FFFFDB93,D0
000001B0: 4CEE 1CF8 FB06 'L.....' MOVEM.L -$04FA(A6),D3-D7/A2-A4
000001B6: 4E5E 'N^' UNLK A6
000001B8: 4E75 'Nu' RTS
000001BA: 4E56 0000 'NV..' LINK A6,#$0000
000001BE: 48E7 0318 'H...' MOVEM.L D6/D7/A3/A4,-(A7)
000001C2: 2E2E 000C '....' MOVE.L $000C(A6),D7
000001C6: 266E 0010 '&n..' MOVEA.L $0010(A6),A3
000001CA: 286E 0008 '(n..' MOVEA.L $0008(A6),A4
000001CE: 202C 0018 ' ,..' MOVE.L $0018(A4),D0
000001D2: E088 '..' LSR.L #$8,D0
000001D4: 7C01 '|.' MOVEQ #$01,D6
000001D6: CC80 '..' AND.L D0,D6
000001D8: 426C 0028 'Bl.(' CLR.W $0028(A4)
000001DC: 7000 'p.' MOVEQ #$00,D0
000001DE: 302B 0006 '0+..' MOVE.W $0006(A3),D0
000001E2: 2207 '".' MOVE.L D7,D1
000001E4: 4C40 1001 'L@..' DIVU.L D0,D1
000001E8: 3941 004C '9A.L' MOVE.W D1,$004C(A4)
000001EC: 7000 'p.' MOVEQ #$00,D0
000001EE: 302B 0004 '0+..' MOVE.W $0004(A3),D0
000001F2: 2207 '".' MOVE.L D7,D1
000001F4: 4C40 1001 'L@..' DIVU.L D0,D1
000001F8: 7000 'p.' MOVEQ #$00,D0
000001FA: 302B 0002 '0+..' MOVE.W $0002(A3),D0
000001FE: 4A80 'J.' TST.L D0
00000200: 4C40 1802 'L@..' TDIVS.L D0,D2:D1
00000204: 700F 'p.' MOVEQ #$0F,D0
00000206: C082 '..' AND.L D2,D0
00000208: 1940 004E '.@.N' MOVE.B D0,$004E(A4)
0000020C: 2006 ' .' MOVE.L D6,D0
0000020E: E988 '..' LSL.L #$4,D0
00000210: 812C 004E '.,.N' OR.B D0,$004E(A4)
00000214: 002C 00A0 004E '.,...N' ORI.B #$A0,$004E(A4)
0000021A: 7000 'p.' MOVEQ #$00,D0
0000021C: 302B 0004 '0+..' MOVE.W $0004(A3),D0
00000220: 2207 '".' MOVE.L D7,D1
00000222: 4C40 1002 'L@..' TDIVU.L D0,D2:D1
00000226: 5202 'R.' ADDQ.B #$1,D2
00000228: 1942 004A '.B.J' MOVE.B D2,$004A(A4)
0000022C: 4CEE 18C0 FFF0 'L.....' MOVEM.L -$0010(A6),D6/D7/A3/A4
00000232: 4E5E 'N^' UNLK A6
00000234: 4E75 'Nu' RTS
Size: Flags $00 ModuleSize 566
Last
Record Summary
Type Count
0 Pad 1
1 First 1
2 Last 1
4 Dictionary 1
5 Module 1
7 ModSize 1
8 Content 1

BIN
DRVR_53_ATADisk Normal file

Binary file not shown.

100
ataboot.py Executable file
View File

@ -0,0 +1,100 @@
#!/usr/bin/env python3
import patch_common
from os import path
import os
import struct
import shutil
import re
import binascii
src, cleanup = patch_common.get_src(desc='''
Enable booting from ATA disks without an Apple_Driver_ATA partition. This is
done by patching the ROM-based .ATALoad DRVR to fall back on the ROM-based
.ATADisk DRVR when initially scanning a disk. The .ATADisk is added to the ROM
if missing. The disk still needs an Apple Partition Map.
''')
# long BOOT(void *DRVR, void *PartMapEntry, long flags)
# C calling convention: args pushed in reverse order and not popped by function, return value in d0
def find_BOOT(code):
for i in range(0, len(code), 2):
if code[i:i+4] == b'BOOT': # MOVE.L 'BOOT',D0 --or-- MOVE.L 'BOOT',-(SP)
for j in reversed(range(0, i, 2)):
# Count backwards and look for the target of *any* JSR, which is the start of the func
for k in range(0, len(code), 2):
if code[k:k+2] == b'\x4E\xBA': # JSR opcode
if k+2 + struct.unpack('>h', code[k+2:k+4])[0] == j:
return j
raise ValueError('Function BOOT not found')
def find_InitDevice(code):
for i in range(0, len(code), 2):
# checking Driver Descriptor Map magic number (there are two but this one always first)
if code[i:i+2] == b'ER':
for j in reversed(range(0, i, 2)):
if code[j:j+2] == b'NV': # LINK A6,#$xxxx
return j
raise ValueError('Function InitDevice not found')
def patch_ataload(code):
code = bytearray(code)
new = len(code) # boundary between old and new code
# Parse the DumpObj'd file
with open(path.join(path.dirname(__file__), 'ATALoad.dmp')) as f:
for l in f:
m = re.match(r'^[0-9A-F]{8}: ([0-9A-F ]+)', l) or re.match('^ {13}([0-9A-F][0-9A-F ]*)', l)
if m:
code.extend(binascii.unhexlify(m.group(1).replace(' ', '')))
InitDevice = find_InitDevice(code[:new])
BOOT = find_BOOT(code[:new])
print('ATALoad patch: InitDevice=0x%X, NewInitDevice=0x%X, BOOT=0x%X' % (InitDevice, new, BOOT))
# "Link" the new code into the old
for i in range(new, len(code), 2):
if code[i:i+4] == b'Nsrt':
code[i:i+4] = code[InitDevice:InitDevice+4] # copy the first LINK from the original function
code[InitDevice:InitDevice+2] = b'\x60\x00' # BRA.W opcode, to...
code[InitDevice+2:InitDevice+4] = struct.pack('>h', new - (InitDevice+2)) # ...the start of the new code
if code[i:i+2] == b'ID': # reference to original InitDevice, skipping the mangled 4-byte LINK
code[i:i+2] = struct.pack('>h', (InitDevice+4) - i)
if code[i:i+2] == b'BT': # reference to BOOT function
code[i:i+2] = struct.pack('>h', BOOT - i)
return bytes(code)
for (parent, folders, files) in os.walk(src):
folders.sort(); files.sort() # make it kinda deterministic
for filename in files:
full = path.join(src, parent, filename)
if filename == 'Romfile':
ataload = path.join(src, parent, 'Rsrc', 'DRVR_-20175_ATALoad')
atadisk = path.join(src, parent, 'Rsrc', 'DRVR_53_ATADisk')
if path.exists(ataload):
code = open(ataload, 'rb').read()
code = patch_ataload(code)
open(ataload, 'wb').write(code)
if not path.exists(atadisk):
with open(full, 'a') as f: # append to Romfile
f.write('\ntype=DRVR id=53 name=.ATADisk src=Rsrc/DRVR_53_ATADisk # inserted by ataboot.py\n')
print('ATALoad patch: using .ATADisk DRVR from Drive Setup 2.1')
shutil.copy(path.join(path.dirname(__file__), 'DRVR_53_ATADisk'), atadisk)
cleanup()