add go code to convert dumps; update images
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
dumps/hgr
|
BIN
dumps/archon-ii.hgr.bin
Normal file
BIN
dumps/archon.hgr.bin
Normal file
BIN
dumps/bards-tale.hgr.bin
Normal file
102
dumps/hgr.go
Normal file
@ -0,0 +1,102 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func xyAddr(x int, y int) int {
|
||||
offset := (y & 7)
|
||||
row := (y / 8) & 7
|
||||
group := y / 64
|
||||
yAddr := 0x28*group + 0x80*row + 0x400*offset
|
||||
return yAddr + x/7
|
||||
}
|
||||
|
||||
func addrXy(addr int) (int, int, bool) {
|
||||
if addr < 0 || addr > 0x1fff {
|
||||
return 0, 0, false
|
||||
}
|
||||
if addr%0x80 >= (0x28 * 3) {
|
||||
return 0, 0, false
|
||||
}
|
||||
|
||||
x := ((addr % 0x80) % 0x28) * 7
|
||||
|
||||
group := (addr % 0x80) / 0x28
|
||||
offset := addr / 0x400
|
||||
row := (addr - 0x28*group - 0x400*offset) / 0x80
|
||||
|
||||
y := group*64 + row*8 + offset
|
||||
|
||||
return x, y, true
|
||||
}
|
||||
|
||||
func run(args []string) error {
|
||||
if len(args) != 2 {
|
||||
return errors.New("usage: hgr input output")
|
||||
}
|
||||
|
||||
input, err := ioutil.ReadFile(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(input) != 0x2000 {
|
||||
return fmt.Errorf("expected to read 0x4000 bytes from file %q; read 0x%04x", args[0], len(input))
|
||||
}
|
||||
|
||||
palette := color.Palette{color.Black, color.White}
|
||||
paletted := image.NewPaletted(image.Rect(0, 0, 560, 192), palette)
|
||||
_ = paletted
|
||||
|
||||
for addr, val := range input {
|
||||
x, y, ok := addrXy(addr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
x0 := x * 2
|
||||
if val&0x80 > 0 {
|
||||
x0 += 1
|
||||
}
|
||||
for b := 0; b < 7; b++ {
|
||||
c := color.Black
|
||||
if val&(1<<uint(b)) > 0 {
|
||||
c = color.White
|
||||
}
|
||||
paletted.Set(x0+2*b, y, c)
|
||||
paletted.Set(x0+2*b+1, y, c)
|
||||
}
|
||||
}
|
||||
|
||||
f, err := os.Create(args[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := (&png.Encoder{CompressionLevel: png.BestCompression}).Encode(f, paletted); err != nil {
|
||||
f.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = input
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := run(os.Args[1:])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
1
dumps/lode-runner.hgr.bin
Normal file
BIN
dumps/rescue-raiders-pic.hgr.bin
Normal file
BIN
dumps/rescue-raiders-words.hgr.bin
Normal file
BIN
dumps/rescue-raiders-words.png
Normal file
After Width: | Height: | Size: 51 B |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 5.2 KiB |
BIN
images/bards-tale.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
images/dazzledraw-flower.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
images/rescue-raiders-pic.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
images/rescue-raiders-words.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
36
index.html
@ -187,12 +187,16 @@
|
||||
|
||||
async function setupScreenView() {
|
||||
const images = [
|
||||
["images/airheart-560x192.png", "Airheart", true ],
|
||||
["images/battle-chess.png", "Battle Chess", true ],
|
||||
["images/archon.png", "Archon", false],
|
||||
["images/archon-ii.png", "Archon II", true ],
|
||||
["images/lode-runner.png", "Lode Runner", true ],
|
||||
["images/marty-reader.png", "Marty's Family Reader", true ],
|
||||
["images/airheart-560x192.png", "Airheart", true ],
|
||||
["images/battle-chess.png", "Battle Chess", true ],
|
||||
["images/archon.png", "Archon", false],
|
||||
["images/archon-ii.png", "Archon II", false],
|
||||
["images/lode-runner.png", "Lode Runner", false],
|
||||
["images/marty-reader.png", "Marty's Family Reader", true ],
|
||||
["images/bards-tale.png", "Bard's Tale", false],
|
||||
["images/dazzledraw-flower.png", "DazzleDraw flower", true ],
|
||||
["images/rescue-raiders-pic.png", "Rescue Raiders (a)", false],
|
||||
["images/rescue-raiders-words.png", "Rescue Raiders (b)", false],
|
||||
];
|
||||
|
||||
const image1 = await screenEmu.loadImage("images/airheart-560x192.png");
|
||||
@ -205,8 +209,8 @@
|
||||
const imsel = document.getElementById('input-image');
|
||||
|
||||
for (let i = 0; i < images.length; i++) {
|
||||
const image = await screenEmu.loadImage(images[i][0]);
|
||||
images[i].push(image);
|
||||
const image = await screenEmu.loadImage(images[i][0]);
|
||||
images[i].push(image);
|
||||
const option = document.createElement("option");
|
||||
option.text = images[i][1];
|
||||
option.value = i;
|
||||
@ -222,13 +226,13 @@
|
||||
sv.displayConfiguration = displayConfig;
|
||||
|
||||
update = () => {
|
||||
updateDisplayConfig(displayConfig);
|
||||
sv.displayConfiguration = displayConfig;
|
||||
sv.vsync();
|
||||
updateDisplayConfig(displayConfig);
|
||||
sv.displayConfiguration = displayConfig;
|
||||
sv.vsync();
|
||||
}
|
||||
|
||||
for (const elem of document.getElementsByClassName('update')) {
|
||||
elem.onchange = update;
|
||||
elem.onchange = update;
|
||||
}
|
||||
|
||||
updateImage = () => {
|
||||
@ -245,10 +249,10 @@
|
||||
imsel.onchange = updateImage;
|
||||
|
||||
document.getElementById('reset').onclick = () => {
|
||||
setTimeout(() => {
|
||||
update();
|
||||
updateImage();
|
||||
}, 0);
|
||||
setTimeout(() => {
|
||||
update();
|
||||
updateImage();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// sv.freeOpenGL();
|
||||
|