proposal2.txt etc.
This commit is contained in:
parent
c7515aab22
commit
c8a29324e3
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# currently only extracts text metadata
|
||||
|
||||
import sys
|
||||
|
||||
def error(msg):
|
||||
print(msg)
|
||||
sys.exit(1)
|
||||
|
||||
def parsestr(data, start):
|
||||
end = start + data[start:].find(b'\0')
|
||||
return end + 1, data[start:end].decode('ascii')
|
||||
|
||||
def parsefields(data, pos0):
|
||||
pos1, name = parsestr(data, pos0)
|
||||
pos2, version = parsestr(data, pos1)
|
||||
pos3, author = parsestr(data, pos2)
|
||||
pos4, desc = parsestr(data, pos3)
|
||||
return {'name': name, 'version': version, 'author': author, 'desc': desc}
|
||||
|
||||
def parse(data, pos0):
|
||||
if len(data[pos0:]) < 6:
|
||||
raise Exception('not enough data!')
|
||||
a,b,c,d,e,f = data[pos0:pos0+6]
|
||||
if a != 0xa0 or d != 0x80 or f != 0x37:
|
||||
return None
|
||||
else:
|
||||
return (e, b, c)
|
||||
|
||||
def toaddr(x, y):
|
||||
return x * 256 + y - 256
|
||||
|
||||
def main():
|
||||
if len(sys.argv[1:]) != 1:
|
||||
print('usage: %s ROMFILE' % sys.argv[0])
|
||||
sys.exit(1)
|
||||
|
||||
f = open(sys.argv[1], 'rb')
|
||||
data = f.read()
|
||||
f.close()
|
||||
|
||||
if len(data) < 6:
|
||||
return error("file too small: %d bytes" % len(data))
|
||||
|
||||
(kind, x, y) = parse(data, 0)
|
||||
if kind != 0xf0:
|
||||
head = ''.join(['%02x' % n for n in data[0:6]])
|
||||
return error("file should start with 'a0____804037' but got %r" % head)
|
||||
|
||||
icon_type = None
|
||||
icon_data = None
|
||||
|
||||
i = 6
|
||||
while True:
|
||||
res = parse(data, i)
|
||||
if res is None:
|
||||
break
|
||||
i += 6
|
||||
kind, x, y = res
|
||||
xy = '%02x%02x' % (x, y)
|
||||
if kind == 0xf2:
|
||||
fields = parsefields(data, toaddr(x, y))
|
||||
print('fields: %r' % fields)
|
||||
elif kind == 0xf4:
|
||||
icon_type = x * 256 - y
|
||||
print('icon type: %s' % xy)
|
||||
elif kind == 0xf6:
|
||||
# TODO: extract icon data as BMP or similar
|
||||
print('icon data at %s' % xy)
|
||||
elif kind == 0xf8:
|
||||
print('maximum memory address is %s' % xy)
|
||||
elif kind == 0xfa:
|
||||
# TODO: parse manifest structure
|
||||
print('manifest data at %s' % xy)
|
||||
else:
|
||||
print('unknown field: %02x (%s)' % (kind, xy))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -6,7 +6,8 @@ for NAME in about.txt asma.rom math32.tal test-math32.tal test-math32.py \
|
|||
rainbow.tal drums.tal drums2.tal bfloat16.tal \
|
||||
fix16.tal test-fix16.tal test-fix16.py \
|
||||
tal-mode1.png tal.nanorc petscii.chr petscii.png petscii.html \
|
||||
tal-mode1.png tal.nanorc proposal.txt;
|
||||
tal-mode1.png tal.nanorc \
|
||||
proposal.txt proposal2.txt extract-v2;
|
||||
do
|
||||
echo "-> $NAME"
|
||||
cp $NAME /var/www/plastic-idolatry.com/html/erik/nxu
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
UXN ROM METADATA PROPOSAL v2 (wip)
|
||||
|
||||
by d6
|
||||
|
||||
TL;DR SUMMARY
|
||||
|
||||
i'm proposing a standardized "prelude" to uxn roms which can be used by
|
||||
emulators but also by external programs to understand what a rom is and what
|
||||
it can do.
|
||||
|
||||
METADATA DEVICE
|
||||
|
||||
PORT WIDTH NAME DESCRIPTION
|
||||
f0 2 bytes version rom data/metadata version
|
||||
f2 2 bytes fields address of text metadata fields
|
||||
f4 2 bytes icon-type icon depth, transparency, and size
|
||||
f6 2 bytes icon-data address of icon data
|
||||
f8 2 bytes max-addr maximum memory address used
|
||||
fa 2 bytes manifest potato manifest
|
||||
fc 2 bytes unused
|
||||
fe 2 bytes unused
|
||||
|
||||
some requirements:
|
||||
|
||||
- metadata writes must come before other writes
|
||||
+ writes must be: LIT2 ?? ?? LIT f? DEO2 (i.e. 6 bytes)
|
||||
+ writes to System/r, g, and b are treated as metadata
|
||||
these are optional but provide hinting about icon rendering
|
||||
they must have the form LIT2 ?? ?? LIT .System/r DEO2
|
||||
- version (f0) must come first
|
||||
- after that, metadata writes can have any order
|
||||
- this means roms with metadata have 6-48 bytes of header
|
||||
+ duplicate metadata writes will be ignored
|
||||
+ addresses in the zero page (i.e. 0000) are ignored
|
||||
|
||||
this means that metadata parsers can read the header
|
||||
in groups of six bytes. for example:
|
||||
|
||||
- a0 WX YZ 80 f0 37 ( uxn version WXYZ )
|
||||
- a0 WX YZ 80 f2 37 ( metadata text fields start at address WXYZ )
|
||||
- a0 WX YZ 80 f4 37 ( icon depth, transparency, and size defined by WXYZ )
|
||||
- a0 WX YZ 80 f6 37 ( icon data starts at address WXYZ )
|
||||
- a0 WX YZ 80 f8 37 ( rom won't read/write addresses > WXYZ )
|
||||
- a0 WX YZ 80 fa 37 ( rom menu data starts at address WXYZ )
|
||||
|
||||
FIELD DESCRIPTIONS
|
||||
|
||||
VERSION (f0)
|
||||
|
||||
this is just a two byte value. my idea is to have a fixed first byte
|
||||
for uxn (e.g. "u") and then use version numbers starting from 00,
|
||||
which we would increase anytime we change the behavior of the VM
|
||||
(either devices or opcodes). this would make it possible for emulators
|
||||
to give good error messages when roms can't be supported.
|
||||
|
||||
the first byte is present so that if someone later decides to fork uxn
|
||||
they can choose a different letter. at that point how they use version
|
||||
numbers is up to them (they could either do their own thing or follow
|
||||
the uxn versions) but again it would make it easier to understand what
|
||||
is going on.
|
||||
|
||||
FIELDS (f2)
|
||||
|
||||
this field is the address of the following four text fields:
|
||||
|
||||
- name
|
||||
- version
|
||||
- author
|
||||
- description
|
||||
|
||||
the strings are each null-terminated, so the address should point to
|
||||
the start of the name. fields can be empty. there is no fixed limit on
|
||||
size but especially the first three fields should ideally fit on one
|
||||
line of text.
|
||||
|
||||
ICON TYPE (f4)
|
||||
|
||||
icon depth, transparency, and size as specified by two bytes.
|
||||
|
||||
bit 16: color 1 transparency (0x8000 transparent, 0x0000 opaque)
|
||||
bits 15-10: unused
|
||||
bit 9: color depth (0x0100 2-bit color, 0x0000 1-bit color)
|
||||
bits 5-8: icon width in tiles (0x10 = 1 tile, 0x20 = 2 tiles, etc.)
|
||||
bits 1-4: icon height in tiles (0x01 = 1 tile, 0x02 = 2 tiles, etc.)
|
||||
|
||||
examples:
|
||||
- 0x0000: no icon (0x0 icon size)
|
||||
- 0x0011: 8x8 icons with 1-bit color and no transparency
|
||||
- 0x8122: 16x16 icons with 2-bit color and transparency
|
||||
- 0x8033: 24x24 icons with 2-bit color and no transparency
|
||||
|
||||
ICON DATA (f6)
|
||||
|
||||
this is a list of absolute addresses for tile data. its length is
|
||||
determined by the dimensions specified in ICON TYPE. for example, if
|
||||
icon type is 0x0022 (16x16 icon) then there would be 8 bytes
|
||||
representing the addresses of 4 tiles.
|
||||
|
||||
MAX ADDR (f8)
|
||||
|
||||
this optional field lets a rom specificy the maximum address it will
|
||||
read from or write to. currently it is purely informational but in the
|
||||
future emulators could enforce this limit. it might also be useful for
|
||||
an operating system running on varvara which is trying to
|
||||
load/store/swap memory for multiple roms.
|
||||
|
||||
MANIFEST (fa)
|
||||
|
||||
this is the manifest data as specified by potato.
|
||||
|
||||
see http://wiki.xxiivv.com/site/manifest.html
|
Loading…
Reference in New Issue