97 lines
2.1 KiB
Python
Executable File
97 lines
2.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import math
|
|
|
|
pageSize = 128
|
|
sectorsPerTrack = 256
|
|
blockSize = 16384
|
|
maxDirs = 128
|
|
dirBlocks = 1
|
|
|
|
out = open('.build/disk.img', 'wb')
|
|
|
|
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
|
|
def addFile(filename, n, t):
|
|
global fileCounter
|
|
|
|
if fileCounter > maxDirs:
|
|
raise RuntimeError("Max dir entries has been reached")
|
|
|
|
fileCounter += 1
|
|
|
|
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()
|
|
|
|
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 (assume no extend for now)
|
|
out.write(bytearray(2))
|
|
|
|
# Reserved byte
|
|
out.write(bytearray(1))
|
|
|
|
# Number of records (Again assuming no extends <128)
|
|
out.write(math.ceil(len(b)/128).to_bytes(1, byteorder='little'))
|
|
|
|
# We are assuming one block per file for now, so we can use fileCounter
|
|
out.write(fileCounter.to_bytes(2, byteorder='little'))
|
|
|
|
seekBlock(fileCounter)
|
|
out.write(b)
|
|
|
|
|
|
addBootloader('.build/loader.bin')
|
|
addOS('.build/cpm22.bin', '.build/bios.bin')
|
|
|
|
initDirs()
|
|
|
|
addFile(".build/MONITOR.COM", "MONITOR", "COM")
|
|
addFile("bin/STAT.COM", "STAT", "COM")
|