mirror of
https://github.com/elliotnunn/NetBoot.git
synced 2024-12-14 09:29:55 +00:00
Works!
This commit is contained in:
parent
34e139a963
commit
e06a86901a
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,6 +2,7 @@
|
||||
edit.rom
|
||||
.DS_Store
|
||||
BootstrapFloppy/System.rdump
|
||||
Bootstrap.bin
|
||||
BootstrapFloppy.dsk
|
||||
BootServer.INIT*
|
||||
*.bin
|
||||
payload
|
||||
|
@ -18,25 +18,31 @@ DrvrBase
|
||||
DrvrOpen
|
||||
; TODO: Move this somewhere that it can respond to AppleTalk going up/down
|
||||
|
||||
; Don't care about the caller PB, so use A0 for our AppleTalk PB instead
|
||||
move.l A0,-(SP)
|
||||
lea PB,A0
|
||||
; Don't care about the caller PB, so use A0 as a scratch register
|
||||
movem.l A0-A1,-(SP)
|
||||
|
||||
; Modify the socket listener code for quick access to driver globals
|
||||
lea editLeaDCE+2,A0
|
||||
move.l A1,(A0)
|
||||
|
||||
; Open .MPP
|
||||
; TODO: check globals on old ROMs before trying
|
||||
lea PB,A0
|
||||
clr.b $1B(A0) ; IOPermssn = whatever is allowed
|
||||
lea MPPString,A1 ; IOFileName = .MPP
|
||||
move.l A1,$12(A0)
|
||||
lea MPPString,A2 ; IOFileName = .MPP
|
||||
move.l A2,$12(A0)
|
||||
dc.w $A000 ; _Open
|
||||
bne.s openFail
|
||||
move.w $18(A0),$16(A1) ; save MPP refnum in dctlStorage
|
||||
|
||||
; Open a DDP socket: "POpenSkt" via direct call to .MPP
|
||||
move.w #248,$1A(A0) ; csCode = openSkt
|
||||
clr.b $1C(A0) ; socket = auto-assign
|
||||
lea SocketListener,A1
|
||||
move.l A1,$1E(A0) ; listener
|
||||
lea SocketListener,A2
|
||||
move.l A2,$1E(A0) ; listener
|
||||
dc.w $A004 ; _Control
|
||||
bne.s openFail
|
||||
move.b $1C(A0),$14(A1) ; save socket number in dCtlStorage
|
||||
|
||||
; Prepare a Name Table Entry for NBP
|
||||
; TODO: replace with static Name Table Entry struct below
|
||||
@ -53,14 +59,14 @@ DrvrOpen
|
||||
move.w #253,$1A(A0) ; csCode = registerName
|
||||
move.b #7,$1C(A0) ; interval = ~1sec
|
||||
move.b #5,$1D(A0) ; count = 5
|
||||
lea NTE,A1
|
||||
move.l A1,$1E(A0) ; entityPtr = our NTE
|
||||
move.b #0,$22(A0) ; verifyFlag = don't
|
||||
lea NTE,A2
|
||||
move.l A2,$1E(A0) ; entityPtr = our NTE
|
||||
move.b #1,$22(A0) ; verifyFlag = do
|
||||
dc.w $A004 ; _Control
|
||||
|
||||
openFail
|
||||
move.w $10(A0),D0 ; Just return whatever error we got
|
||||
move.l (SP)+,A0
|
||||
movem.l (SP)+,A0-A1
|
||||
move.w D0,$10(A0)
|
||||
rts
|
||||
|
||||
@ -73,36 +79,252 @@ DrvrClose
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
DrvrControl
|
||||
move.w #-18,$10(A0) ; ioResult
|
||||
bra DrvrFinish
|
||||
cmp.w #65,$1A(A0)
|
||||
beq.s accRun
|
||||
move.w #-17,$10(A0) ; ioResult = controlErr
|
||||
rts
|
||||
|
||||
accRun
|
||||
move.w #0,$10(A0) ; ioResult = noErr (never need to return an error)
|
||||
|
||||
; figure out the packet
|
||||
lea ReceivedPacket,A2
|
||||
move.w (A2)+,D0 ; length
|
||||
|
||||
cmp.b #1,(A2)
|
||||
beq ReplyToUserRecordRequest
|
||||
cmp.b #3,(A2)
|
||||
beq ReplyToImageRequest
|
||||
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
PushReturnAddress
|
||||
clr.l -(SP)
|
||||
clr.l -(SP)
|
||||
clr.l -(SP)
|
||||
clr.l -(SP)
|
||||
clr.w -(SP)
|
||||
|
||||
move.l ReturnAddress,D0
|
||||
move.b #10,1+15(SP)
|
||||
move.b D0,1+13(SP)
|
||||
asr.w #4,D0
|
||||
asr.w #4,D0
|
||||
move.b D0,1+11(SP)
|
||||
swap D0
|
||||
move.w D0,1+7(SP)
|
||||
|
||||
move.l 18(SP),-(SP)
|
||||
rts
|
||||
|
||||
|
||||
ReplyToUserRecordRequest ; A0=iopb A1=dce A2=pkt
|
||||
bclr.b #5,4(A1) ; clear dNeedTime: done with this packet
|
||||
|
||||
move.l SP,A3
|
||||
|
||||
move.w #586/2-1,D0 ; Push the whole packet
|
||||
clrloop clr.w -(SP)
|
||||
dbra D0,clrloop
|
||||
move.w #$0201,(SP) ; user record reply v1
|
||||
move.w 2(A2),2(SP) ; copy osID
|
||||
move.l 4(A2),4(SP) ; copy userData (timestamp)
|
||||
move.w #512,8(SP) ; blockSize
|
||||
move.w #0,10(SP) ; imageID
|
||||
move.w #0,12(SP) ; result (error code)
|
||||
move.l #(EndOfPayload-StartOfPayload+511)>>9,14(SP)
|
||||
move.l SP,A4
|
||||
|
||||
; This code should be deduplicated
|
||||
bsr PushReturnAddress
|
||||
lea 1(SP),A5 ; the "odd" base of the address struct
|
||||
|
||||
move.w #0,-(SP) ; Push the WriteDataStructure
|
||||
move.l A4,-(SP)
|
||||
move.w #586,-(SP)
|
||||
move.l A5,-(SP) ; the first odd address of the WDS
|
||||
move.w #16,-(SP)
|
||||
move.l SP,A4
|
||||
|
||||
bsr WriteDDP
|
||||
move.l A3,SP
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; The money shot
|
||||
; Send as many packets as we can in six ticks
|
||||
; Also be fairly canny with the bitmap
|
||||
|
||||
; Internally: D7=ticks D6=whichblock D5=scratch
|
||||
|
||||
ReplyToImageRequest ; A0=iopb A1=dce A2=pkt D0=pktlen
|
||||
moveq #0,D4
|
||||
move.w D0,D4
|
||||
subq #8,D4
|
||||
asl.l #3,D4
|
||||
cmp.w #(EndOfPayload-StartOfPayload+511)>>9,D4
|
||||
blo.s dontsubtract
|
||||
move.l #(EndOfPayload-StartOfPayload+511)>>9,D4
|
||||
dontsubtract
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
move.l $16A,D7 ; Ticks
|
||||
moveq.l #-1,D6 ; Block counter
|
||||
blockloop addq.l #1,D6
|
||||
cmp.w D4,D6
|
||||
bhs endsend
|
||||
|
||||
move.w D6,D5
|
||||
asr.w #3,D5
|
||||
bclr.b D6,8(A2,D5.W)
|
||||
beq.s blockloop
|
||||
|
||||
|
||||
; okay, so I am committed to sending this packet
|
||||
|
||||
|
||||
|
||||
|
||||
move.l SP,A3
|
||||
|
||||
|
||||
|
||||
; This code should be deduplicated
|
||||
bsr PushReturnAddress
|
||||
lea 1(SP),A5 ; the "odd" base of the address struct
|
||||
|
||||
|
||||
|
||||
move.w D6,-(SP) ; blocknum (first chunk of packet)
|
||||
move.w 2(A2),-(SP) ; image ID
|
||||
move.w #$0401,-(SP) ; image data v1
|
||||
move.l SP,A4
|
||||
|
||||
move.w #0,-(SP) ; Push the WriteDataStructure
|
||||
|
||||
|
||||
|
||||
|
||||
lea StartOfPayload,A0
|
||||
moveq #0,D5
|
||||
move.w D6,D5
|
||||
lsl.l #4,D5
|
||||
lsl.l #5,D5
|
||||
add.l D5,A0
|
||||
move.l A0,-(SP)
|
||||
|
||||
|
||||
|
||||
|
||||
move.w #512,-(SP)
|
||||
move.l A4,-(SP)
|
||||
move.w #6,-(SP)
|
||||
move.l A5,-(SP) ; the first odd address of the WDS
|
||||
move.w #16,-(SP)
|
||||
move.l SP,A4
|
||||
|
||||
bsr WriteDDP
|
||||
|
||||
move.l A3,SP
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; check whether we need to yield time
|
||||
move.l $16A,D5
|
||||
sub.l D7,D5
|
||||
cmp.l #6,D5
|
||||
bhi.s defersend
|
||||
bra blockloop
|
||||
|
||||
|
||||
|
||||
endsend
|
||||
bclr.b #5,4(A1) ; clear dNeedTime: done with this packet
|
||||
defersend
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
WriteDDP ; pass in the WDS as a4
|
||||
move.l A0,-(SP)
|
||||
lea -$32(SP),SP
|
||||
move.l SP,A0
|
||||
|
||||
move.w $16(A1),$18(A0) ; IORefNum = dctlStorage.low
|
||||
move.w #246,$1A(A0) ; csCode = writeDDP
|
||||
clr.l $C(A0) ; IOCompletion = NULL
|
||||
move.b $14(A1),$1C(A0) ; get socket number from dCtlStorage
|
||||
move.b #1,$1D(A0) ; set checksumFlag
|
||||
move.l A4,$1E(A0) ; wdsPointer to our WriteDataStructure
|
||||
dc.w $A004 ; _Control
|
||||
|
||||
lea $32(SP),SP
|
||||
move.l (SP)+,A0
|
||||
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
DrvrStatus
|
||||
move.w #-18,$10(A0) ; ioResult
|
||||
bra DrvrFinish
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Elliot: this can probably be cleaned up, because all our calls are synchronous
|
||||
DrvrFinish
|
||||
move.w 6(A0),D1 ; iopb.ioTrap
|
||||
btst #9,D1 ; noQueueBit
|
||||
bne.s DrvrNoIoDone
|
||||
move.l $8FC,-(SP) ; jIODone
|
||||
DrvrNoIoDone
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
SocketListener
|
||||
dc.w $A9FF
|
||||
; A0 Reserved for internal use by the .MPP driver. You must preserve this register until after the ReadRest routine has completed execution.
|
||||
; A1 Reserved for internal use by the .MPP driver. You must preserve this register until after the ReadRest routine has completed execution.
|
||||
; A2 Pointer to the .MPP driver's local variables. Elliot says: the frame and packet header ("RHA") are at offset 1 from A2 (keeps the 2-byte fields aligned)
|
||||
; A3 Pointer to the first byte in the RHA past the DDP header bytes (the first byte after the DDP protocol type field).
|
||||
; A4 Pointer to the ReadPacket routine. The ReadRest routine starts 2 bytes after the start of the ReadPacket routine.
|
||||
; A5 Free for your use before and until your socket listener calls the ReadRest routine.
|
||||
; D0 Lower byte is the destination socket number of the packet.
|
||||
; D1 Word indicating the number of bytes in the DDP packet left to be read (that is, the number of bytes following the DDP header).
|
||||
; D2 Free for your use.
|
||||
; D3 Free for your use.
|
||||
|
||||
; Parse the packet at accRun time
|
||||
editLeaDCE lea $12345678,A5 ; live-edited to point to DCE
|
||||
bset.b #5,4(A5) ; raise dNeedTime in dCtlFlags
|
||||
|
||||
; Parse the "return address" from the header
|
||||
cmp.b #1,1+2(A2) ; test DDP header type
|
||||
bne.s longhdr
|
||||
|
||||
shorthdr moveq.l #0,D2 ; network number = 0
|
||||
move.w 1+1(A2),D2 ; node number
|
||||
move.b 1+6(A2),D2 ; socket numder
|
||||
bra.s doneWithHeader
|
||||
longhdr move.w 1+9(A2),D2 ; network number
|
||||
swap D2
|
||||
move.b 1+12(A2),D2 ; node number
|
||||
asl.w #4,D2
|
||||
asl.w #4,D2
|
||||
move.b 1+14(A2),D2 ; socket number
|
||||
doneWithHeader
|
||||
|
||||
; Save the return address in a standard format
|
||||
lea ReturnAddress,A5
|
||||
move.l D2,(A5)
|
||||
|
||||
; Save the return address and packet body
|
||||
lea ReceivedPacket,A3
|
||||
move.w D1,D3 ; odd that I need to use this register?
|
||||
move.w D3,(A3)+
|
||||
jmp 2(A4) ; ReadRest (to A3)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
MPPString dc.b 4, ".MPP", 0
|
||||
|
||||
@ -111,6 +333,9 @@ TypStr dc.b 10, "BootServer", 0
|
||||
ZonStr dc.b 1, "*"
|
||||
|
||||
|
||||
ReturnAddress dc.l 0
|
||||
ReceivedPacket dcb.b 2+586
|
||||
|
||||
|
||||
; Names table entry for NBP
|
||||
PB
|
||||
@ -198,3 +423,8 @@ MoveAstring
|
||||
DC.W $A22E ; _BlockMoveData
|
||||
RTS
|
||||
|
||||
|
||||
align 9
|
||||
StartOfPayload
|
||||
incbin "../payload"
|
||||
EndOfPayload
|
||||
|
@ -13,13 +13,18 @@ myDRefNum equ ~myUnitNum
|
||||
dc.w $A9FF ; _Debugger
|
||||
noGetResErr
|
||||
|
||||
move.l A4,A0
|
||||
dc.w $A025 ; _GetHandleSize
|
||||
sub.l D0,$10C ; BufPtr
|
||||
|
||||
move.l (A4),A0
|
||||
move.l $10C,A1
|
||||
dc.w $A02E ; _BlockMove
|
||||
|
||||
move.l A4,-(SP)
|
||||
dc.w $A992 ; _DetachResource
|
||||
|
||||
move.l A4,A0
|
||||
dc.w $A029 ; _HLock
|
||||
|
||||
move.l (A4),A4
|
||||
move.l $10C,A4
|
||||
|
||||
; Install the driver in the unit table
|
||||
move.l A4,A0
|
||||
|
@ -52,15 +52,16 @@ while 1:
|
||||
elif llap_proto_type == 2:
|
||||
# ddp, long (what should we do with this extra information?)
|
||||
if len(data) < 13: continue
|
||||
ddp_len, ddp_cksum, ddp_dest_net, ddp_src_net, ddp_dest_node, ddp_src_node, ddp_dest_socket, ddp_src_socket = struct.unpack_from('>4H5B', data)
|
||||
ddp_len, ddp_cksum, ddp_dest_net, ddp_src_net, ddp_dest_node, ddp_src_node, ddp_dest_socket, ddp_src_socket, ddp_proto_type = struct.unpack_from('>4H5B', data)
|
||||
ddp_hop_count = (ddp_len >> 10) & 0xF
|
||||
ddp_len &= 0x3FF
|
||||
data = data[13:ddp_len]
|
||||
print(ddp_src_net, ddp_dest_net)
|
||||
else:
|
||||
# llap control packet -- can probably ignore!
|
||||
continue
|
||||
|
||||
print(f'datagram {llap_src_node}:{ddp_src_socket}->{llap_dest_node}:{ddp_dest_socket}')
|
||||
print(f'datagram {llap_proto_type} {llap_src_node}:{ddp_src_socket}->{llap_dest_node}:{ddp_dest_socket}')
|
||||
|
||||
if ddp_proto_type == 2: # NBP
|
||||
if len(data) < 2: continue
|
||||
@ -85,15 +86,23 @@ while 1:
|
||||
print(f' net:node:sock={t[0]}:{t[1]}:{t[2]} enum={t[3]} object:type@zone={t[4]}:{t[5]}@{t[6]}')
|
||||
|
||||
elif ddp_proto_type == 10: # ATBOOT
|
||||
if len(data) < 2: continue
|
||||
if len(data) < 2:
|
||||
print('malformed short packet %r' % data.hex())
|
||||
continue
|
||||
boot_type, boot_vers = struct.unpack_from('>BB', data)
|
||||
data = data[2:]
|
||||
|
||||
if boot_type == 1:
|
||||
print(' ATBOOT "syn"')
|
||||
if boot_type == 2:
|
||||
print(' ATBOOT "ack"')
|
||||
print(' ATBOOT "syn"', data.hex())
|
||||
elif boot_type == 2:
|
||||
print(' ATBOOT "ack"', data.hex())
|
||||
elif boot_type == 3:
|
||||
print(' ATBOOT image request')
|
||||
print(' ATBOOT image request', data.hex())
|
||||
elif boot_type == 4:
|
||||
print(' ATBOOT image reply')
|
||||
print(' ATBOOT image reply', data.hex())
|
||||
else:
|
||||
print(' ' + data.hex())
|
||||
|
||||
else:
|
||||
print('Totally unknown DDP type', ddp_proto_type)
|
||||
print(' ' + data.hex())
|
||||
|
24
Makefile
24
Makefile
@ -17,21 +17,16 @@ image: systools607.dsk.a Makefile
|
||||
Mini\ vMac\ Classic.app/Co*/Ma*/* xo.rom /tmp/system6.dsk
|
||||
|
||||
|
||||
systools607.dsk.a: systools607.dsk
|
||||
python3 -c 'for b in open("systools607.dsk","rb").read(): print(" dc.b $$%02X" % b)' >systools607.dsk.a
|
||||
|
||||
|
||||
Bootstrap.bin: Bootstrap.a
|
||||
vasm-1/vasmm68k_mot -quiet -Fbin -pic -o $@ $<
|
||||
|
||||
|
||||
BootstrapFloppy/System.rdump: Bootstrap.bin
|
||||
rfx cp $< $@//boot/1
|
||||
|
||||
BootstrapFloppy.dsk: BootstrapFloppy/System.rdump
|
||||
MakeHFS -n 'NetBoot Enabler' -i BootstrapFloppy -s 1440k -d now $@
|
||||
|
||||
testflop: BootstrapFloppy.dsk
|
||||
testclient: BootstrapFloppy.dsk
|
||||
Mini\ vMac\ Classic.app/Co*/Ma*/* xo.rom $<
|
||||
|
||||
|
||||
@ -40,7 +35,17 @@ testflop: BootstrapFloppy.dsk
|
||||
|
||||
|
||||
|
||||
BootServer.INIT: FORCE
|
||||
BootWrapper.bin: BootWrapper.a
|
||||
vasm-1/vasmm68k_mot -quiet -Fbin -pic -o $@ $<
|
||||
|
||||
payload: BootWrapper.bin
|
||||
#echo ' dcb.w 10000, $$A9FF' >/tmp/xasm
|
||||
#vasm-1/vasmm68k_mot -quiet -Fbin -pic -o /tmp/yasm /tmp/xasm
|
||||
#cat /tmp/yasm >payload
|
||||
cat BootWrapper.bin systools607.dsk >payload
|
||||
python3 snefru_hash.py payload
|
||||
|
||||
BootServer.INIT: payload FORCE
|
||||
./buildapp.bash BootServer
|
||||
|
||||
testserver: BootServer.INIT
|
||||
@ -49,9 +54,12 @@ testserver: BootServer.INIT
|
||||
DumpHFS systools607.dsk /tmp/bootserv
|
||||
cp MacsBug\ 6.2.2/* /tmp/bootserv/System\ Folder
|
||||
cp BootServer.INIT* /tmp/bootserv/System\ Folder
|
||||
MakeHFS -i /tmp/bootserv -s 1440k bootserv.tmp
|
||||
MakeHFS -i /tmp/bootserv -s 10m bootserv.tmp
|
||||
Mini\ vMac\ Classic.app/Co*/Ma*/* xo.rom bootserv.tmp
|
||||
|
||||
pyserver: payload FORCE
|
||||
./NetBoot.py payload
|
||||
|
||||
|
||||
|
||||
|
||||
|
41
NetBoot.py
41
NetBoot.py
@ -19,32 +19,8 @@ my_unique_ltoudp_id = b'El' + (os.getpid() & 0xFFFF).to_bytes(2, 'big')
|
||||
|
||||
|
||||
|
||||
disk_image = open(path.join(path.dirname(path.abspath(__file__)), 'systools607.dsk'), 'rb').read()
|
||||
|
||||
# Strip the Disk Copy header
|
||||
if disk_image[0x54:0x56] == b'LK' or disk_image[0x454:0x456] == b'BD':
|
||||
disk_image = disk_image[0x54:]
|
||||
print('Stripped Disk Copy header from image')
|
||||
|
||||
|
||||
|
||||
def assemble(the_code):
|
||||
with open('/tmp/vasm.bootblocks', 'w') as f:
|
||||
f.write(the_code)
|
||||
|
||||
try:
|
||||
os.remove('/tmp/vasm.bootblocks.bin')
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
assembler = path.join(path.dirname(path.abspath(__file__)), 'vasm-1/vasmm68k_mot')
|
||||
os.system(f'{assembler} -quiet -Fbin -pic -o /tmp/vasm.bootblocks.bin /tmp/vasm.bootblocks')
|
||||
|
||||
with open('/tmp/vasm.bootblocks.bin', 'rb') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
|
||||
import sys
|
||||
image = open(sys.argv[1], 'rb').read()
|
||||
|
||||
# typedef short (*j_code)( short command, # SP+4 (sign-extend to long)
|
||||
# DGlobals *g, # SP+8
|
||||
@ -53,19 +29,6 @@ def assemble(the_code):
|
||||
|
||||
# We return our OSErr in d0, and leave the 16 bytes of arguments on the stack for the caller to clean
|
||||
|
||||
image = assemble(open(path.join(path.dirname(path.abspath(__file__)), 'BootServer/PROC128.a')).read()) + disk_image
|
||||
|
||||
|
||||
|
||||
|
||||
image = bytearray(image)
|
||||
|
||||
while len(image) % 512 != 512 - 64: image.append(0)
|
||||
the_hash = snefru(image)
|
||||
while len(image) % 512 != 512 - 16: image.append(0)
|
||||
image.extend(the_hash)
|
||||
print('Sig:', ''.join(('%02X' % b) for b in image[-16:]))
|
||||
|
||||
|
||||
ANY = "0.0.0.0"
|
||||
MCAST_ADDR = "239.192.76.84"
|
||||
|
@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
|
||||
|
||||
make BootstrapFloppy.dsk
|
||||
|
||||
Mini\ vMac\ Classic.app/Contents/MacOS/minivmac xo.rom BootstrapFloppy.dsk && kill %1
|
@ -354,8 +354,21 @@ def snefru(inbytes):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import binascii
|
||||
the_plain = b''.join(n.to_bytes(4, 'big') for n in range(32*1024//4))
|
||||
the_hash = snefru(the_plain)
|
||||
import sys
|
||||
for p in sys.argv[1:]:
|
||||
try:
|
||||
x = open(p, 'rb').read()
|
||||
|
||||
print(binascii.hexlify(the_hash))
|
||||
if len(x) % 512 == 0:
|
||||
maybe_already = snefru(x[:-64])
|
||||
if x[-16:] == maybe_already: continue
|
||||
|
||||
while len(x) % 512 != 512 - 64: x += b'\0'
|
||||
the_hash = snefru(x)
|
||||
while len(x) % 512 != 512 - 16: x += b'\0'
|
||||
x += the_hash
|
||||
|
||||
open(p, 'wb').write(x)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
838400
systools607.dsk.a
838400
systools607.dsk.a
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user