goapple2/videoscan/convert.go

95 lines
1.8 KiB
Go

// convert.go contains routines to convert from character ROMs to text and back.
package videoscan
import (
"fmt"
"strings"
)
var chars = []rune{'.', '#'}
func reverseByte(in byte) byte {
hi := in & 0x80
var out byte
for i := 0; i < 7; i++ {
out = out << 1
out = out | in&1
in = in >> 1
}
out |= hi
return out
}
func BytesToText(rom []byte, reverse bool) []byte {
result := []byte{}
for i, b := range rom {
if reverse {
b = reverseByte(b)
}
if i > 0 && i%8 == 0 {
result = append(result, '\n')
}
if b >= 0x80 {
result = append(result, 'i')
} else {
result = append(result, 'n')
}
result = append(result, ' ')
for i := 0; i < 7; i++ {
result = append(result, byte(chars[b&1]))
b = b >> 1
}
result = append(result, '\n')
}
return result
}
func TextToBytes(text []byte, reverse bool) ([]byte, error) {
result := []byte{}
lines := strings.Split(string(text), "\n")
for i, l := range lines {
l = strings.TrimSpace(l)
lines[i] = l
if i != 0 && i%9 == 8 {
if l != "" {
return nil, fmt.Errorf("line %d: expected empty line, got '%s'", i+1, l)
}
continue
}
if len(l) != 9 {
return nil, fmt.Errorf("line %d: expected 9 characters, got %d: '%s'", i+1, len(l), l)
}
var hi byte
switch l[0] {
case 'i':
hi = 0x80
case 'n':
default:
return nil, fmt.Errorf("line %d: should start with 'n' or 'i'; got '%s'", i+1, l[0])
}
if l[1] != ' ' {
return nil, fmt.Errorf("line %d: second char should be space; got '%s'", i+1, l[1])
}
var b byte
var bit byte = 1
for _, c := range l[2:] {
switch c {
case chars[0]: // do nothing
case chars[1]:
b |= bit
default:
return nil, fmt.Errorf("line %d: expected character: '%s'", i+1, c)
}
bit <<= 1
}
b |= hi
if reverse {
b = reverseByte(b)
}
result = append(result, b)
}
return result, nil
}