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 \
|
rainbow.tal drums.tal drums2.tal bfloat16.tal \
|
||||||
fix16.tal test-fix16.tal test-fix16.py \
|
fix16.tal test-fix16.tal test-fix16.py \
|
||||||
tal-mode1.png tal.nanorc petscii.chr petscii.png petscii.html \
|
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
|
do
|
||||||
echo "-> $NAME"
|
echo "-> $NAME"
|
||||||
cp $NAME /var/www/plastic-idolatry.com/html/erik/nxu
|
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