Split tool from setup repository
This commit is contained in:
commit
ee0b39f2f3
122
create-disk.py
Executable file
122
create-disk.py
Executable file
|
@ -0,0 +1,122 @@
|
|||
#!/usr/bin/env python3
|
||||
import math
|
||||
|
||||
pageSize = 128
|
||||
sectorsPerTrack = 256
|
||||
blockSize = 16384
|
||||
pagesPerBlock = 128
|
||||
maxDirs = 128
|
||||
dirBlocks = 1
|
||||
|
||||
|
||||
def addBootloader(name):
|
||||
loader = open(name, 'rb')
|
||||
b = loader.read()
|
||||
|
||||
if len(b) > pageSize:
|
||||
raise RuntimeError("Bootloader binary cannot be larger than one page")
|
||||
|
||||
out.seek(0)
|
||||
out.write(b)
|
||||
|
||||
def addOS(cpmName, biosName):
|
||||
cpm = open(cpmName, 'rb')
|
||||
bios = open(biosName, 'rb')
|
||||
|
||||
b = cpm.read()
|
||||
out.seek(pageSize)
|
||||
out.write(b)
|
||||
|
||||
b = bios.read()
|
||||
out.seek(pageSize + 0x1600)
|
||||
out.write(b)
|
||||
|
||||
def seekBlock(i):
|
||||
# Blocks start at track 1, sector 0
|
||||
out.seek(pageSize*sectorsPerTrack + i*blockSize)
|
||||
|
||||
def initDirs():
|
||||
seekBlock(0)
|
||||
out.write(bytearray(([0xe5] + [0x00] * 31) * maxDirs))
|
||||
|
||||
fileCounter = 0
|
||||
allocationCounter = 1
|
||||
def addFile(filename, n, t):
|
||||
global fileCounter
|
||||
global allocationCounter
|
||||
|
||||
if fileCounter > maxDirs:
|
||||
raise RuntimeError("Max dir entries has been reached")
|
||||
|
||||
if len(n) > 8:
|
||||
raise RuntimeError("Filename cannot be longer than 8")
|
||||
|
||||
if len(t) > 3:
|
||||
raise RuntimeError("Filetype cannot be longer than 3")
|
||||
|
||||
f = open(filename, 'rb')
|
||||
b = f.read()
|
||||
|
||||
total_records = math.ceil(len(b)/pageSize)
|
||||
records = (total_records - 1) % pagesPerBlock + 1
|
||||
extends = math.ceil(total_records/pagesPerBlock)
|
||||
|
||||
if extends >= 8:
|
||||
RuntimeError("File is to big to be stored in one entry, multple entries are not implemented")
|
||||
|
||||
seekBlock(0)
|
||||
out.seek(32*fileCounter, 1)
|
||||
|
||||
# Write user (assume 0 for now)
|
||||
out.write(bytearray(1))
|
||||
|
||||
# Write the name
|
||||
out.write(n.upper().encode("ascii"))
|
||||
out.write((" " * (8-len(n))).encode("ascii"))
|
||||
|
||||
# Write the type
|
||||
out.write(t.upper().encode("ascii"))
|
||||
out.write((" " * (3-len(t))).encode("ascii"))
|
||||
|
||||
# Write extend
|
||||
# @todo This is actually wrong, as the order is EX S1 S2 with S1 being unused, however we never deal with files that big
|
||||
out.write((extends-1).to_bytes(1, byteorder='little'))
|
||||
|
||||
# Reserved byte
|
||||
out.write(bytearray(2))
|
||||
|
||||
# Number of records
|
||||
|
||||
out.write(records.to_bytes(1, byteorder='little'))
|
||||
|
||||
allocationCounterOld = allocationCounter
|
||||
# We are assuming one block per file for now, so we can use fileCounter
|
||||
for i in range(extends):
|
||||
out.write(allocationCounter.to_bytes(2, byteorder='little'))
|
||||
allocationCounter += 1
|
||||
|
||||
seekBlock(allocationCounterOld)
|
||||
out.write(b)
|
||||
|
||||
fileCounter += 1
|
||||
|
||||
|
||||
def main():
|
||||
# @todo Load the config from a file that we specify instead of hardcoding everything
|
||||
# We can probably keep the os part hardcoded as that is not something we really need to change between different projects
|
||||
global out
|
||||
out = open('../tools/disk.img', 'wb')
|
||||
|
||||
addBootloader('../cpm/.build/loader.bin')
|
||||
addOS('../cpm/.build/cpm22.bin', '../cpm/.build/bios.bin')
|
||||
|
||||
initDirs()
|
||||
|
||||
addFile("../cpm/.build/MONITOR.COM", "MONITOR", "COM")
|
||||
addFile("../cpm/bin/STAT.COM", "STAT", "COM")
|
||||
addFile("../cpm/bin/MBASIC.COM", "MBASIC", "COM")
|
||||
addFile("../cpm/bin/s.com", "S", "COM")
|
||||
# addFile("../xed/.build/XED.COM", "XED", "COM")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Reference in New Issue
Block a user