Initial commit
This commit is contained in:
commit
2d6428446e
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
samples/
|
44
README.md
Normal file
44
README.md
Normal file
@ -0,0 +1,44 @@
|
||||
# Intro
|
||||
|
||||
Mobitec flip-disc displays use MC27C1001 EPROM-s to store the
|
||||
firmware (?) and fonts.
|
||||
In the `firmware/` directory you can find two ROM dumps.
|
||||
|
||||
# Useful commands
|
||||
|
||||
To extract font sections:
|
||||
|
||||
```
|
||||
dd if=mobitec-1682-r7-bib-01979-r3.bin of=mobitec-1682-r7-bib-01979-r3-fonts.bin skip=64 bs=1024
|
||||
dd if=mobitec-01682-r7-bib-01369-r9.bin of=mobitec-01682-r7-bib-01369-r9-fonts.bin skip=64 bs=1024
|
||||
```
|
||||
|
||||
For diffing font sections:
|
||||
|
||||
```
|
||||
dhex mobitec-1682-r7-bib-01979-r3-fonts.bin mobitec-01682-r7-bib-01369-r9-fonts.bin
|
||||
```
|
||||
|
||||
# Dump structure
|
||||
|
||||
The firmware seems to be located in the first 7KiB and the font data
|
||||
starts at 0x10000 offset.
|
||||
|
||||
The font beginning marker seem to consist of a character from `a` to `z`
|
||||
followed by at least 60 null characters.
|
||||
They don't seem aligned or indexed in any way so easiest is just to scan
|
||||
for known markers.
|
||||
|
||||
After the beginning marker you can find the lookup table which maps
|
||||
printable ASCII characters to a glyph address.
|
||||
The lookup table is 190 bytes (95x 16-bit addresses) which correspond
|
||||
to ASCII characters 32 up to 126.
|
||||
Not all fonts include all characters, missing glyphs are represented by address 0.
|
||||
Note that the glyph address is relative to the beginning of font structure,
|
||||
beginning marker inclusive.
|
||||
|
||||
At the glyph address first width and height of the glyph are found represented
|
||||
by two 8-bit integers. The actual bitmap data follows in 8x8 pixel tiles
|
||||
packed together as 8 bytes.
|
||||
|
||||
|
122
extract-fonts.py
Normal file
122
extract-fonts.py
Normal file
@ -0,0 +1,122 @@
|
||||
import json
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
"""
|
||||
dd if=mobitec-1682-r7-bib-01979-r3.bin of=mobitec-1682-r7-bib-01979-r3-fonts.bin skip=64 bs=1024
|
||||
dd if=mobitec-01682-r7-bib-01369-r9.bin of=mobitec-01682-r7-bib-01369-r9-fonts.bin skip=64 bs=1024
|
||||
dhex mobitec-1682-r7-bib-01979-r3-fonts.bin mobitec-01682-r7-bib-01369-r9-fonts.bin
|
||||
"""
|
||||
|
||||
src = "mobitec-1682-r7-bib-01979-r3"
|
||||
src = "mobitec-01682-r7-bib-01369-r9"
|
||||
|
||||
with open("firmware/%s.bin" % src, "rb") as fh:
|
||||
buf = fh.read()[65536:]
|
||||
|
||||
|
||||
def scan_fonts(buf):
|
||||
"""
|
||||
Font start markers seem to be ascii character a..z followed by at least 60 nulls
|
||||
"""
|
||||
font_index = buf[0]
|
||||
assert font_index == 0x61
|
||||
prev = 0
|
||||
done = False
|
||||
while not done:
|
||||
needle = b"%c" % (font_index + 1)
|
||||
needle += 50 * b"\x00"
|
||||
try:
|
||||
font_offset = buf.index(needle)
|
||||
except ValueError:
|
||||
break
|
||||
font_body = buf[prev:]
|
||||
done = True
|
||||
else:
|
||||
font_body = buf[prev:font_offset]
|
||||
if done:
|
||||
break
|
||||
font_marker_length = len(needle)
|
||||
font_body = font_body[font_marker_length:]
|
||||
while font_body.startswith(b"\x00"):
|
||||
font_body = font_body[1:]
|
||||
font_marker_length += 1
|
||||
yield font_index, font_body, font_marker_length
|
||||
prev = font_offset
|
||||
font_index += 1
|
||||
|
||||
|
||||
meta = []
|
||||
for font_index, font_body, font_marker_length in scan_fonts(buf):
|
||||
print()
|
||||
print("Parsing font %02x" % font_index)
|
||||
|
||||
# Looks like yet another marker
|
||||
assert font_body[0] == 3
|
||||
assert font_body[1] == 1
|
||||
|
||||
# Look up table consists of 95 16-bit integers
|
||||
glyph_offsets = np.frombuffer(font_body[2:192], dtype=np.uint16)
|
||||
prev = 0
|
||||
slices = []
|
||||
errors = set()
|
||||
|
||||
for index, glyph_offset in enumerate(glyph_offsets):
|
||||
if glyph_offset != 0:
|
||||
glyph_offset -= font_marker_length
|
||||
print("Found %d undecoded bytes between lookup table and first glyph" % len(font_body[192:192 + glyph_offset]))
|
||||
break
|
||||
|
||||
characters_present = ""
|
||||
|
||||
for index, glyph_offset in enumerate(glyph_offsets):
|
||||
if glyph_offset == 0:
|
||||
characters_present += "_"
|
||||
# No glyph
|
||||
meta.append(None)
|
||||
continue
|
||||
else:
|
||||
# The index goes from space (32) up to ~ (126)
|
||||
character = chr(index + 32)
|
||||
characters_present += "+"
|
||||
|
||||
# Glyphs are relative to the font marker start
|
||||
glyph_offset -= font_marker_length
|
||||
|
||||
try:
|
||||
height, width = font_body[glyph_offset], font_body[glyph_offset + 1]
|
||||
except IndexError:
|
||||
print("Failed to look up glyph for %s", repr(character))
|
||||
else:
|
||||
jah = np.frombuffer((font_body[glyph_offset + 2:])[::-1], dtype=np.uint8)[::-1]
|
||||
a = np.unpackbits(jah, axis=0)
|
||||
try:
|
||||
img = a[:width * 16].reshape((width, 16, 1))
|
||||
img = np.hstack([img[:, 8:, :], img[:, :8, :]])
|
||||
meta.append({
|
||||
"width": width,
|
||||
"height": height,
|
||||
"bitmap": img.tolist()
|
||||
})
|
||||
img = 255 * img
|
||||
|
||||
slices.append(img)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
blank_image = np.zeros((1, 16, 1), np.uint8)
|
||||
blank_image[::] = 0
|
||||
slices.append(blank_image)
|
||||
|
||||
if glyph_offset <= prev:
|
||||
print("Glyph offsets not ordered")
|
||||
prev = glyph_offset
|
||||
print("Glyphs present:", characters_present)
|
||||
img = np.vstack(slices)
|
||||
|
||||
img = np.flip(np.swapaxes(img, 1, 0), 0)
|
||||
s = img.shape * np.array(5)
|
||||
img = cv2.resize(img, dsize=(s[1], s[0]), interpolation=cv2.INTER_NEAREST)
|
||||
cv2.imwrite("samples/%s-%02x.png" % (src, font_index), img)
|
||||
with open("samples/%s-%02x.json" % (src, font_index), "w") as fh:
|
||||
fh.write(json.dumps({"glyphs": meta}))
|
BIN
firmware/mobitec-01682-r7-bib-01369-r9.bin
Normal file
BIN
firmware/mobitec-01682-r7-bib-01369-r9.bin
Normal file
Binary file not shown.
BIN
firmware/mobitec-1682-r7-bib-01979-r3.bin
Normal file
BIN
firmware/mobitec-1682-r7-bib-01979-r3.bin
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user