CosmOS pre-alpha and launchable application versions of old programs.

This commit is contained in:
Anachronaut
2026-08-17 15:31:49 -04:00
parent eff6902bcf
commit 91c9d49d1b
66 changed files with 5612 additions and 160 deletions
-46
View File
@@ -1,46 +0,0 @@
// sbex.h
// The SplitBit loadable program format, version one.
//
// A program that is not the one the machine booted from has to say where it wants to
// live, because nothing relocates it. This is a header saying that, in front of the
// bytes themselves. It is the same idea as the load address on the front of a C64 .PRG,
// with room for the machine to ask a few more questions later.
//
// Two things read this: whatever builds one on the host, and the loader running on
// SplitBit. As with the filesystem, nothing is shared between them but the specification.
//
// All multi byte numbers are most significant byte first.
//
// 0 4 "SBEX"
// 4 1 Version
// 5 1 Reserved
// 6 2 Where the code goes in Program Memory
// 8 2 Where to start running, an address in Program Memory
// 10 2 How many bytes of code there are
// 12 2 Where the data goes in Data Memory
// 14 2 How many bytes of data there are
// 16 The code, then the data
//
// Sixteen bytes, so the code begins at a round offset and finding it is one step rather
// than an arithmetic. Nothing here relocates anything: the addresses are where the
// program was built to live, and putting it anywhere else would leave every branch and
// every SETD inside it pointing at the wrong place.
//
// Written by Anachronaut
#ifndef SBEX_H
#define SBEX_H
#define SBEX_MAGIC "SBEX"
#define SBEX_MAGIC_BYTES 4
#define SBEX_VERSION 1
#define SBEX_HEADER_BYTES 16
#define SBEX_VERSION_AT 4
#define SBEX_CODE_AT 6
#define SBEX_ENTRY_AT 8
#define SBEX_CODE_LEN_AT 10
#define SBEX_DATA_AT 12
#define SBEX_DATA_LEN_AT 14
#endif // SBEX_H
-58
View File
@@ -1,58 +0,0 @@
#!/usr/bin/env python3
"""Wraps an assembled SplitBit binary into a loadable program.
The assembler emits a boot image: a Program Segment that loads at zero and a Data Segment
that does the same. A program meant to be loaded somewhere else has to say where it goes,
which is what the SBEX header in front of it is for.
A program says where it lives by reserving the front of each segment, so the addresses
given here have to match the reserves in its source. Nothing checks that for you, and
nothing relocates anything if you get it wrong.
"""
import struct
import sys
def segments(raw):
at = 4 + 1 + 4 # magic, version, feature flags
assert raw[:4] == b"SPBT", "not a SplitBit binary"
assert raw[at:at + 3] == b"PRG"
plen = struct.unpack(">H", raw[at + 3:at + 5])[0]
program = raw[at + 5:at + 5 + plen]
at = at + 5 + plen
assert raw[at:at + 3] == b"DAT"
dlen = struct.unpack(">H", raw[at + 3:at + 5])[0]
return program, raw[at + 5:at + 5 + dlen]
def main():
if len(sys.argv) != 6:
sys.exit("usage: wrap.py <binary> <output> <code address> <data address> <entry>")
binary, output = sys.argv[1], sys.argv[2]
codeAt, dataAt, entry = (int(a, 0) for a in sys.argv[3:6])
program, data = segments(open(binary, "rb").read())
# Everything below the address a segment is placed at is the padding the reserve put
# there, and is not part of the program.
code = program[codeAt:]
values = data[dataAt:]
header = bytearray(16)
header[0:4] = b"SBEX"
header[4] = 1
struct.pack_into(">H", header, 6, codeAt)
struct.pack_into(">H", header, 8, entry)
struct.pack_into(">H", header, 10, len(code))
struct.pack_into(">H", header, 12, dataAt)
struct.pack_into(">H", header, 14, len(values))
with open(output, "wb") as out:
out.write(header)
out.write(code)
out.write(values)
print("%s: %d bytes of code at 0x%04X, %d of data at 0x%04X, entry 0x%04X"
% (output, len(code), codeAt, len(values), dataAt, entry))
main()