CosmOS pre-alpha and launchable application versions of old programs.
This commit is contained in:
@@ -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
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user