1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-11-24 12:31:25 +00:00

removed tools/, moved to new repo sehugg/8bit-tools

This commit is contained in:
Steven Hugg 2020-07-12 10:22:41 -05:00
parent 4480e217f6
commit 5fe9ec29a5
57 changed files with 2 additions and 19070 deletions

View File

@ -34,5 +34,3 @@ tsweb:
astrolibre.b64.txt: astrolibre.rom
lzg -9 $< | base64 -w 0 > $@
astdump:
clang -Xclang -ast-dump -fsyntax-only tools/galois.c

View File

@ -1,53 +0,0 @@
all: binaries
%.lzg: %
lzg -9 $< $@
binaries: scr2floyd scr2floyd_percept galois
%-pf.hex: %-pf.pbm p4_to_pfbytes.py
python p4_to_pfbytes.py $< > $@
%-48.hex: %-48.pbm p4_to_48pix.py
python p4_to_48pix.py $< > $@
%-pf.pbm: %.jpg
convert $< -resize 40x192\! -colorspace Gray -dither FloydSteinberg $@
%-48.pbm: %.jpg
convert $< -resize 48x192\! -colorspace Gray -dither FloydSteinberg $@
%.tga: %.png
convert $< -resize 192 $<.gif
convert $<.gif +dither -type palette -depth 4 -compress RLE -colors 8 -flip $@
convert $@ $@.png
%.pcx: %.png
convert $< -format raw -type palette -compress none -colors 15 +dither $@
%.rle.pcx: %.png
convert $< -format raw -type palette -compress rle -colors 15 +dither $@
%.4.pcx: %.png
convert $< -format raw -type palette -compress none -colors 4 +dither $@
ship1.pbm: ship1.png
convert ship1.png -negate -flop ship1.pbm
%.h:
cat $* | hexdump -v -e '"\n" 128/1 "0x%02x,"'
%.prom:
cat $* | hexdump -v -e '" \n defb " 32/1 "$$%02x,"' | cut -c 2-134
%.s:
cat $* | hexdump -v -e '" \n .byte " 32/1 "$$%02x,"' | cut -c 2-135
%.rot.pbm: %.pbm
convert $< -transpose -bordercolor white -border 4x4 $@
baddies-horiz.rot.pbm: baddies-horiz.png
convert $< +dither -brightness-contrast 50x50 -fill black -transpose -negate $@
convert $@ foo.png
lfsr.out: lfsrcalc.py
pypy lfsrcalc.py | sort -n > lfsr.out

View File

@ -1,24 +1,3 @@
These files have been moved to:
This directory contains 8bitworkshop tools for bitmap and
music conversion.
Requires ImageMagick (convert) and Python 2.x.
MIDI tools require Mido (pip install mido).
On Ubuntu:
$ sudo apt update
$ sudo apt install python python-pip imagemagick curl
$ sudo pip install mido
To use the tools, go to the appropriate directory and
look at the Makefile for each:
vcs/ Atari 2600/VCS
mw8080/ Midway 8080
scramble/ Galaxian/Scramble
vicdual/ VIC Dual
williams/ Williams
fonts/ Example fonts
images/ Example images
https://github.com/sehugg/8bit-tools

View File

@ -1,15 +0,0 @@
#!/usr/bin/python
import sys
out = sys.stdout
chr = open(sys.argv[1],'rb').read()
out.write('const unsigned char ARRAY[%d] = {\n' % len(chr))
for i in range(0,len(chr)):
out.write('0x%02x, ' % ord(chr[i]))
if (i & 7) == 7:
out.write('\n')
out.write('\n};\n')

View File

@ -1,15 +0,0 @@
import sys,re
inf = sys.stdin
outf = open('a.out','wb')
l = inf.readline()
while l:
l = l.strip()
if l[-1] == ',':
l = l[0:-1]
toks = re.split('[,\s]+', l)
toks = list(filter(lambda x: x[0:2]=='0x', toks))
arr = [int(x,0) for x in toks]
outf.write(bytes(arr))
l = inf.readline()

View File

@ -1,16 +0,0 @@
import os,sys,codecs
for root, dirs, files in os.walk("./presets"):
for fn in files:
path = root + '/' + fn
if fn[-1] == '~':
continue
try:
with open(path,'r') as f:
data = f.read()
if data[0] != '\n':
print((path,'no initial newline'))
except:
print((path,sys.exc_info()[0]))

View File

@ -1,14 +0,0 @@
#!/bin/sh
./scr2floyd_percept $1.tga
lzg -9 $1.CHR > $1.CHR.lzg
lzg -9 $1.CLR > $1.CLR.lzg
rm -f $1.s
echo "\t.area _CODE" >> $1.s
echo "\t.globl _msx_mode2_pattern_lzg" >> $1.s
echo "\t.globl _msx_mode2_color_lzg" >> $1.s
echo "\n_msx_mode2_pattern_lzg:" >> $1.s
cat $1.CHR.lzg | hexdump -v -e '"\n.db " 16/1 ",0x%02x"' | sed "s/n.db,/ .db /" | tail -n +3 >> $1.s
echo "\n_msx_mode2_color_lzg:" >> $1.s
cat $1.CLR.lzg | hexdump -v -e '"\n.db " 16/1 ",0x%02x"' | sed "s/n.db,/ .db /" | tail -n +3 >> $1.s

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +0,0 @@
/* test of 16-bit Galois LFSR */
#include "stdio.h"
int main()
{
int n = 100;
unsigned short x = 1;
for (int i=0; i<n; i++) {
int c = x&1;
x >>= 1;
if (c) x ^= 0xd400; // 0b1101010000000000
printf("%4x\n", x);
}
for (int i=0; i<n; i++) {
int c = x&0x8000;
x <<= 1;
if (c) x ^= 0xa801;
printf("%4x\n", x);
}
return 0;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,30 +0,0 @@
#!/usr/bin/python
MAXBITS=16
print("Period,nbits,feedback,mask")
for n in range(1,MAXBITS):
mask = (1<<n)-1
hibit = (1<<(n-1))
for i in range(0,1<<n):
for invert in [0,1]:
x = 1
seq = []
seen = set()
while x and not x in seen:
seq.append(x)
seen.add(x)
feedback = x & hibit
x = ((x << 1) & mask)
if invert:
if not feedback:
x ^= i
else:
if feedback:
x ^= i
if x:
seqindex = seq.index(x)
seqlen = len(seq) - seqindex
if seqlen>1:
print((seqlen, "#(%d,%d'%s,%d)" % (n,n,bin(i)[1:],invert), seqindex))

View File

@ -1,42 +0,0 @@
"use strict";
var BEST={}
var MAXBITS=17
//MAXBITS=12
for (var n=1; n<MAXBITS; n++) {
var mask = (1<<n)-1;
var hibit = (1<<(n-1));
for (var i=0; i < (1<<n); i++) {
for (var invert=0; invert<2; invert++) {
var x = 1;
var seq = [];
var seen = new Map();
while (x && !seen.get(x)) {
seq.push(x);
seen.set(x, true);
var feedback = (x & hibit) != 0;
x = ((x << 1) & mask);
if (invert && !feedback) x ^= i;
if (!invert && feedback) x ^= i;
}
if (x) {
var seqindex = seq.indexOf(x);
var seqlen = seq.length - seqindex;
if (seqlen > 1 && x == 1) {
if (!BEST[seqlen] || n < BEST[seqlen].n) {
BEST[seqlen] = {n:n, i:i, invert:invert};
//console.log(seqlen + "\t" + n + "\t" + i.toString(2) + "\t" + x.toString(2));
}
}
}
}
}
}
for (var seqlen in BEST) {
var b = BEST[seqlen];
console.log(seqlen+" &\t@"+b.n+"'b"+b.i.toString(2)+","+b.invert+"@ \\\\");
}

View File

@ -1,182 +0,0 @@
#!/usr/bin/python
import sys, string, math, argparse
import mido
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--start', type=int, default=21, help="first MIDI note")
parser.add_argument('-n', '--num', type=int, default=21+63, help="number of notes")
parser.add_argument('-v', '--voices', type=int, default=3, help="number of voices")
parser.add_argument('-T', '--transpose', type=int, default=0, help="transpose by half-steps")
parser.add_argument('-t', '--tempo', type=int, default=48, help="tempo")
parser.add_argument('-o', '--one', action="store_true", help="one voice per channel")
parser.add_argument('-z', '--compress', action="store_true", help="compress song (experimental)")
parser.add_argument('-H', '--hex', action="store_true", help="hex output")
parser.add_argument('midifile', help="MIDI file")
parser.add_argument('midichannels', nargs='?', help="comma-separated list of MIDI channels, or -")
args = parser.parse_args()
min_note = args.start
max_note = min_note + args.num
max_voices = args.voices
one_voice_per_channel = args.one
tempo = args.tempo
compress = args.compress
transpose = args.transpose
coutput = not args.hex
# for 2600
#max_voices = 2
#coutput = 0
# for 2600 wavetable
#max_voices = 4
#one_voice_per_channel = 0
fn = args.midifile
mid = mido.MidiFile(fn)
def hex1(n):
return '%02x'%n
def hex2(n):
return '0x%02x'%n
def only_notes(s):
for ch in s:
if ord(ch) == 0xff:
return False
return True
def find_common_substrings(s):
results = {}
for l in range(64, 6, -1):
for i in range(0,len(s)-l*2):
match = s[i:i+l]
if not only_notes(match):
continue
count = 0
j = i+l
while j < len(s):
p = s.find(match, j)
if p > 0:
count += 1
j = p+l
else:
break
if count:
n = count*(l-1)-1
if not results.get(i) or n > results[i][0]:
results[i] = (n,l)
return results
def get_best_substring(ss):
best = (0,0,0)
for k,v in list(ss.items()):
if v[0] > best[2]:
best = (k,v[1],v[0])
return best
def offset2str(ofs):
return chr(ofs & 0xff) + chr((ofs >> 8) & 0xff)
#return chr(0xc0 | (ofs & 0x3f)) + chr(0xc0 | ((ofs >> 6) & 0x3f))
g_code = 0xc1
g_subs = []
def replace_substrings(s, bss):
global g_code
i,l,n = bss
count = (n+1)/(l-1)
match = s[i:i+l]
print((i,l,n,count,repr(match)))
r = s[0:i]
while i<len(s):
r += chr(g_code)
p = s.find(match,i+l)
if p < 0:
p = len(s)
r += s[i+l:p]
i = p
g_subs.append(match + chr(0xff))
g_code += 1
print((len(s), len(r)+n+l))
assert len(s) == len(r)+n+l
return r
def channels_for_track(track):
channels = set()
for msg in track:
if msg.type == 'note_on':
channels.add(msg.channel)
return list(channels)
if not args.midichannels:
print(mid)
print((mid.length, 'seconds'))
for i, track in enumerate(mid.tracks):
print(('Track {}: {} ({}) {}'.format(i, track.name, len(track), channels_for_track(track))))
#for msg in track:
# print(msg)
else:
gtime = 0
curtime = 0
nnotes = 0
nvoices = 0
curchans = 0
channels = [int(x) for x in args.midichannels.split(',')]
print ('')
print(("// %s %s" % (mid, channels)))
output = []
for msg in mid:
gtime += msg.time * tempo
if msg.type == 'note_on' and msg.channel in channels:
note = msg.note + transpose
vel = msg.velocity
t = int(math.ceil(gtime))
if vel > 0:
while curtime < t:
dt = min(63, t-curtime)
curtime += dt
if nnotes > 0:
nvoices = 0
curchans = 0
output.append(dt+128)
if note >= min_note and note <= max_note and nvoices < max_voices:
if not (one_voice_per_channel and (curchans & (1<<msg.channel))):
n = note - min_note
output.append(n)
nnotes += 1
nvoices += 1
curchans |= 1<<msg.channel
output.append(0xff)
if coutput:
print((','.join([hex2(x) for x in output])))
else:
bighex = ''.join([hex1(x) for x in output])
for i in range(0,len(bighex)+32,32):
print(('\thex', bighex[i:i+32]))
if compress:
# replace common substrings
bout = ''.join(chr(i) for i in output)
for iter in range(0,32):
ss = find_common_substrings(bout)
bss = get_best_substring(ss)
print(bss)
if bss[1] == 0:
break
bout = replace_substrings(bout, bss)
print((repr(bout)))
# build substring table
ofs = (len(g_subs)+1)*2
zout = offset2str(ofs)
ofs += len(bout)
for ss in g_subs:
ofs += len(ss)
zout += offset2str(ofs)
# output strings
zout += bout
for ss in g_subs:
zout += ss
# print output
print((','.join([hex2(ord(x)) for x in zout])))
print(("// compressed %d -> %d bytes" % (len(output), len(zout))))

View File

@ -1,48 +0,0 @@
#!/usr/bin/python
import sys, string, math, argparse
parser = argparse.ArgumentParser()
parser.add_argument('-l', '--length', type=int, default=64, help="length of note table")
parser.add_argument('-u', '--upper', type=int, default=49, help="upper note # to test")
parser.add_argument('-f', '--freq', type=float, default=3579545/32.0, help="base frequency (Hz)")
parser.add_argument('-b', '--bias', type=float, default=0, help="divisor bias")
parser.add_argument('-m', '--maxbits', type=float, default=12, help="max. # of bits")
args = parser.parse_args()
test_notes = args.upper
final_notes = args.length
basehz = args.freq
bias = args.bias
maxval = (1<<int(args.maxbits))-1
results = []
for a440 in range(4300,4500):
error = 0
for note in range(1,test_notes):
notehz = a440 / 10.0 * math.pow(2.0, (note - 49) / 12.0);
period = int(round(basehz / notehz))
while period > maxval:
period /= 2
tonehz = basehz / period
error += abs(notehz-tonehz)
#print a440,note,notehz,notehz-tonehz,period
#if a440 == 4405:
# print '%d,%f,%d' % (note,tonehz-notehz,period)
results.append((error, a440))
results.sort()
best_error, best_a440 = results[0]
best_a440 /= 10.0
print('//', args)
print('//', best_a440, best_error, test_notes)
print("const int note_table[%d] = {" % final_notes)
for note in range(0,final_notes):
notehz = best_a440 * math.pow(2.0, (note - 49) / 12.0);
period = int(round(basehz / notehz)) - bias
while period > maxval:
period /= 2
print('%d,' % period, end='')
print("};")

View File

@ -1,91 +0,0 @@
#!/usr/bin/python
import sys, string, math, argparse
parser = argparse.ArgumentParser()
parser.add_argument('-l', '--length', type=int, default=64, help="length of note table")
parser.add_argument('-u', '--upper', type=int, default=49, help="upper note # to test")
args = parser.parse_args()
test_notes = args.upper
final_notes = args.length
basehz = 15720.0 #4
basehz2 = 5240.0 #12
basehz3 = 1014.2 #6
s = 8
bittable = [
0b00000000,
0b00000001,
0b00010001,
0b01001001,
0b01010101,
0b10110101,
0b11011011,
0b11101111,
]
results = []
for a440 in range(4200,4600):
error = 0
for note in range(4,test_notes):
notehz = a440 / 10.0 * math.pow(2.0, (note - 49) / 12.0);
period = round(basehz * s / notehz) / s
tonehz = basehz / period
if period < s or period > 32*s:
tonehz = -10000
period2 = round(basehz2 * s / notehz) / s
tonehz2 = basehz2 / period
if period2 < s or period2 > 32*s:
tonehz2 = -10000
period3 = round(basehz3 * s / notehz) / s
tonehz3 = basehz3 / period
if period3 < s or period3 > 32*s:
tonehz3 = -10000
error += min(abs(notehz-tonehz), abs(notehz-tonehz2), abs(notehz-tonehz3))
results.append((error, a440))
results.sort()
best_error, best_a440 = results[0]
best_a440 /= 10.0
print('//', best_a440, best_error, test_notes)
periods = []
tones = []
bits = []
print("const int note_table[%d] = {" % final_notes)
for note in range(0,final_notes):
notehz = best_a440 * math.pow(2.0, (note - 49) / 12.0);
bestperiod = 255
bestscore = 999999
besthz = -1
for hz in [basehz, basehz2, basehz3]:
period = int(round(hz * s / notehz))
if period >= s and period <= 32*s:
tonehz = hz / period
error = notehz - hz
if error < bestscore:
bestscore = error
bestperiod = period
besthz = hz
#print(note, besthz, bestperiod, notehz)
print('%d,' % period, end='')
periods.append(bestperiod / s - 1)
bits.append(bittable[bestperiod & (s-1)])
if besthz==basehz:
tones.append(4)
elif besthz==basehz2:
tones.append(12)
elif besthz==basehz3:
tones.append(6)
else:
tones.append(0)
print("};")
print(periods)
print(bits)
print(tones)

View File

@ -1,9 +0,0 @@
d = 16
s = 800
for n in range(0,128):
z = n/2+d
y = s/z
print("%d," % y, end='')
print()

View File

@ -1,2 +0,0 @@
*.c
*.pbm

View File

@ -1,29 +0,0 @@
all: cp437.mw8080.c c64.mw8080.c baddies-horiz.rot.c scrappy.rot.c
# convert DOS CP437 font (256 chars)
cp437.mw8080.c: ../fonts/cp437-8x8.bdf
python ../parsebdf8.py $< -f -r -C > $@
# convert C64 font (63 chars)
c64.mw8080.c: ../fonts/c64.bdf
python ../parsebdf8.py $< -f -r -C -s 32 -e 94 > $@
%.h:
cat $* | hexdump -v -e '"\n" 128/1 "0x%02x,"'
# convert PBM bitmap to C array
%.c: %.pbm
python ../pbm_to_c.py $< > $@
#%.rot.pbm: %.pbm
# convert $< -transpose -bordercolor white -border 4x4 $@
# rotate and dither example bitmaps
baddies-horiz.rot.pbm: ../images/baddies-horiz.png
convert $< +dither -brightness-contrast 50x50 -fill black -transpose -negate $@
scrappy.rot.pbm: ../images/scrappy48x64.pbm
convert $< -transpose -bordercolor white -border 4x4 $@

View File

@ -1,11 +0,0 @@
all: nametable.dat
clean:
rm -f *.dat road.png
nametable.dat: road.png
makechr -e error.png $< #-b 0000ff
road.png: road.py
python road.py

View File

@ -1,102 +0,0 @@
#!/usr/bin/python
# Import a library of functions called 'pygame'
import pygame
import random
from math import pi
# Initialize the game engine
pygame.init()
# Define the colors we will use in RGB format
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
BLUE = ( 0, 0, 255)
GREEN = ( 0, 184, 0)
CURBING = [
(136,20,0),
(168,16,0),
]
CENLINE = [
(124,124,124),
(188,188,188),
]
MOUNTAINS = [
(80,48,0),
(172,124,0)
]
# Set the height and width of the screen
size = [512, 240]
y0 = 112
x0 = 256
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Example code for the draw module")
#Loop until the user clicks the close button.
done = False
clock = pygame.time.Clock()
while not done:
# This limits the while loop to a max of 10 times per second.
# Leave this out and we will use all CPU we can.
clock.tick(10)
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done=True # Flag that we are done so we exit this loop
# All drawing code happens after the for loop and but
# inside the main while done==False loop.
# Clear the screen and set the screen background
screen.fill(BLUE)
pygame.draw.rect(screen, GREEN, [0, y0, 512, 240-y0])
# draw the road
for y in range(y0,240):
i = y-y0
rw = i*2
cw = rw/4
lw = rw/32
z = 500.0/(i+1)
curbcol = CURBING[int(z) % 2]
cencol = CENLINE[int(z) % 2]
if i < 16:
cencol = BLACK #CENLINE[0]
if i < 0:
curbcol = BLACK #CURBING[0]
pygame.draw.line(screen, BLACK, [x0-rw, y], [x0+rw, y], 1)
pygame.draw.line(screen, curbcol, [x0-rw-cw, y], [x0-rw, y], 1)
pygame.draw.line(screen, curbcol, [x0+rw, y], [x0+rw+cw, y], 1)
pygame.draw.line(screen, cencol, [x0-rw/3-lw, y], [x0-rw/3+lw, y], 1)
pygame.draw.line(screen, cencol, [x0+rw/3-lw, y], [x0+rw/3+lw, y], 1)
# draw mountains
h1 = 1
h2 = 2
for x in range(0,512):
pygame.draw.line(screen, MOUNTAINS[0], [x, y0-1], [x, y0-h1], 1)
pygame.draw.line(screen, MOUNTAINS[1], [x, y0-1], [x, y0-h2], 1)
if random.randint(0,8) > h1:
h1 += 1
elif h1 > 1:
h1 -= 1
if random.randint(0,6) > h2:
h2 += 1
elif h2 > 1:
h2 -= 1
# Go ahead and update the screen with what we've drawn.
# This MUST happen after all the other drawing commands.
pygame.display.flip()
pygame.image.save(screen, 'road.png')
# Be IDLE friendly
pygame.quit()

View File

@ -1,11 +0,0 @@
import sys
chr = open(sys.argv[1],'rb').read()
out = open('outsms.bin','wb')
for i in range(0,len(chr),16):
for y in range(0,8):
arr = [ ord(chr[i+y]), ord(chr[i+8+y]), 0, 0 ]
out.write(bytearray(arr))
out.close()

View File

@ -1,58 +0,0 @@
#!/usr/bin/python
import sys, struct
# playfield bytes, one array for each of 6 columns
output = [[],[],[],[],[],[]]
# reverse byte
def rev(n):
return int('{:08b}'.format(n)[::-1], 2)
# output bits in given range
def out(i, pix, lb, hb, reverse=0, shift=0):
x = (pix >> lb) & ((1<<(hb-lb))-1)
if reverse:
x = rev(x)
if shift:
x = x << shift
assert(x>=0 and x<=255)
output[i].append(x)
# read PBM (binary P4 format) file
with open(sys.argv[1],'rb') as f:
# read PBM header
header = f.readline().strip()
assert(header == b'P4')
dims = f.readline().strip()
if dims[0:1] == b'#':
dims = f.readline().strip()
width,height = list(map(int, dims.split()))
assert(width==48)
# read bitmap rows
for y in range(0,height):
row = bytes(f.read(6) + b'\0\0') # pad to 8 bytes
# convert to 64-bit integer
pix = struct.unpack('<q',row)[0]
#print '%010lx' % pix
# generate playfield bytes
out(0, pix, 0, 8, 0)
out(1, pix, 8, 16, 0)
out(2, pix, 16, 24, 0)
out(3, pix, 24, 32, 0)
out(4, pix, 32, 40, 0)
out(5, pix, 40, 48, 0)
# output bitmap tables
for c in range(0,6):
print("\talign $100")
print(("Bitmap%d" % c))
print("\thex 00")
s = '\thex '
for i in range(0,height):
s += '%02x' % output[c][height-i-1]
if i % 16 == 15:
print(s)
s = '\thex '
if len(s)>5:
print(s)

View File

@ -1,60 +0,0 @@
#!/usr/bin/python
import sys, struct
# playfield bytes, one array for each of 6 columns
output = [[],[],[],[],[],[]]
# reverse byte
def rev(n):
return int('{:08b}'.format(n)[::-1], 2)
# output bits in given range
def out(i, pix, lb, hb, reverse=0, shift=0):
x = (pix >> lb) & ((1<<(hb-lb))-1)
if reverse:
x = rev(x)
if shift:
x = x << shift
assert(x>=0 and x<=255)
output[i].append(x)
# read PBM (binary P4 format) file
with open(sys.argv[1],'rb') as f:
# read PBM header
header = f.readline().strip()
assert(header == b'P4')
dims = f.readline().strip()
if dims[0:1] == b'#':
dims = f.readline().strip()
print(dims)
width,height = list(map(int, dims.split()))
assert(width==40)
# read bitmap rows
for y in range(0,height):
row = bytes(f.read(5) + b'\0\0\0') # pad to 8 bytes
# convert bytes from MSB first to LSB first
row2 = []
for i in range(0,8):
row2.append(rev(row[i]))
# convert to 64-bit integer
pix = struct.unpack('<q',bytes(row2))[0]
# generate playfield bytes
out(0, pix, 0, 4, 0, 4)
out(1, pix, 4, 12, 1)
out(2, pix, 12, 20, 0)
out(3, pix, 20, 24, 0, 4)
out(4, pix, 24, 32, 1)
out(5, pix, 32, 40, 0)
# output bitmap tables
for c in range(0,6):
print(("PFBitmap%d" % c))
s = '\thex '
for i in range(0,height):
s += '%02x' % output[c][height-i-1]
if i % 16 == 15:
print(s)
s = '\thex '
if len(s)>5:
print(s)

View File

@ -1,71 +0,0 @@
#!/usr/bin/python
import sys,string
height = 5
lochar = 41
hichar = 90
chars = {}
inbitmap = 0
with open(sys.argv[1],'r') as f:
lines = f.readlines()
for l in lines:
l = l.strip()
toks = l.split()
if toks[0] == 'ENCODING':
chord = int(toks[1])
elif toks[0] == 'BITMAP':
inbitmap = True
bytes = []
elif toks[0] == 'ENDCHAR':
inbitmap = False
if chord >= lochar and chord <= hichar:
while len(bytes) < height:
bytes.insert(0,0)
assert(len(bytes) == height)
bytes.reverse()
print((chord,bytes))
chars[chord] = bytes
elif inbitmap and len(toks) == 1:
byte = int(toks[0],16)
assert((byte&15)==0)
assert((byte&1)==0)
byte = byte / 32
bytes.append(byte)
# output font table
x = 0
output = []
outputlo = []
outputhi = []
for ch in range(lochar,hichar+1):
x = 0
bytes = chars.get(ch)
#bytes = bytes + [0]
if not bytes:
bytes = [0] * height
for b in bytes:
if not x:
v = b
else:
v = v | (b<<4)
output.append(v)
x ^= 1
outputlo.append(b)
outputhi.append(b<<4)
def tohex(v):
return '%02x'%v
def tohex2(v):
return '0x%02x'%v
def tobin(v):
return "bitarray[0][0]=3'b{0:3b};\n".format(v)
print(('\thex ' + ''.join(map(tohex,output))))
print((''.join(map(tohex2,output))))
print(('\thex ' + ''.join(map(tohex,outputlo))))
print(('\thex ' + ''.join(map(tohex,outputhi))))
print((''.join(map(tobin,output))))
print((len(output),len(outputlo),len(outputhi)))

View File

@ -1,65 +0,0 @@
#!/usr/bin/python
import sys,string,argparse
#lochar = 0x20 #48
#hichar = 0x5e #57
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--start', type=int, default=0, help="index of first character")
parser.add_argument('-e', '--end', type=int, default=255, help="index of last character")
parser.add_argument('bdffile', help="BDF bitmap file")
args = parser.parse_args()
lochar = args.start
hichar = args.end
def tohex(v):
return '%02x'%v
def tohex2(v):
return '0x%02x'%v
chars = {}
inbitmap = 0
with open(args.bdffile,'r') as f:
lines = f.readlines()
for l in lines:
l = l.strip()
toks = l.split()
#print l,toks
if toks[0] == 'ENCODING':
chord = int(toks[1])
elif toks[0] == 'BITMAP':
inbitmap = True
bytes = []
elif toks[0] == 'BBX':
bbx = [int(x) for x in toks[1:]]
elif toks[0] == 'ENDCHAR':
inbitmap = False
if chord >= lochar and chord <= hichar:
#bytes.reverse()
#print chord,bytes,bbx
width = bbx[0]+1
height = bbx[1]
output = [(width+1)//2 + (width)*16, height + (height+bbx[3])*16]
for y in range(0,height):
for x in range(0,width,2):
b = 0
if bytes[y] & (0x80 >> x):
b |= 0xf0
if bytes[y] & (0x40 >> x):
b |= 0x0f
output.append(b)
print('const char CH_%d[] = { %s };' % ( chord, ','.join([tohex2(x) for x in output]) ))
chars[chord] = 'CH_%d' % chord
elif inbitmap and len(toks) == 1:
byte = int(toks[0],16)
bytes.append(byte)
print('const char* const FONT_TABLE[%d] = {' % (hichar-lochar+1), end=' ')
for ch in range(lochar, hichar+1):
if chars.get(ch):
print('%s,' % chars[ch], end=' ')
else:
print('0,', end=' ')
print("};")

View File

@ -1,120 +0,0 @@
#!/usr/bin/python
import sys,string,argparse
#lochar = 0x20 #48
#hichar = 0x5e #57
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--start', type=int, default=0, help="index of first character")
parser.add_argument('-e', '--end', type=int, default=255, help="index of last character")
parser.add_argument('-H', '--height', type=int, default=8, help="character height")
parser.add_argument('-i', '--invert', action="store_true", help="invert bits")
parser.add_argument('-r', '--rotate', action="store_true", help="rotate bits")
parser.add_argument('-f', '--flip', action="store_true", help="flip bits (vertically)")
parser.add_argument('-m', '--mirror', action="store_true", help="mirror bits (horizontally)")
outfmtgroup = parser.add_mutually_exclusive_group()
outfmtgroup.add_argument("-A", "--asmhex", action="store_true", help="DASM-compatible hex")
outfmtgroup.add_argument("-B", "--asmdb", action="store_true", help="Z80ASM-compatible hex")
outfmtgroup.add_argument("-C", "--carray", action="store_true", help="Nested C array")
outfmtgroup.add_argument("-F", "--flatcarray", action="store_true", help="Flat C array")
outfmtgroup.add_argument("-V", "--verilog", action="store_true", help="Verilog-compatible hex")
parser.add_argument('bdffile', help="BDF bitmap file")
args = parser.parse_args()
height = args.height
lochar = args.start
hichar = args.end
invert = args.invert
flip = args.flip
rotate = args.rotate
mirror = args.mirror
chars = {}
inbitmap = 0
with open(args.bdffile,'r') as f:
lines = f.readlines()
for l in lines:
l = l.strip()
toks = l.split()
#print l,toks
if toks[0] == 'ENCODING':
chord = int(toks[1])
elif toks[0] == 'BITMAP':
inbitmap = True
bytes = []
elif toks[0] == 'ENDCHAR':
inbitmap = False
if chord >= lochar and chord <= hichar:
while len(bytes) < height:
bytes.insert(0,0)
assert(len(bytes) == height)
bytes.reverse()
#print chord,bytes
chars[chord] = bytes
elif inbitmap and len(toks) == 1:
byte = int(toks[0],16)
bytes.append(byte)
def revbits(n):
r = 0
for i in range(0,8):
if (n & (1<<i)):
r |= (1<<(7-i))
return r
# output font table
x = 0
output = []
revoutput = []
rotoutput = []
rot2output = []
for ch in range(lochar,hichar+1):
bytes = chars.get(ch)
if not bytes:
bytes = [0] * height
if flip:
bytes.reverse()
if mirror:
for i in range(0,height):
bytes[i] = revbits(bytes[i])
if rotate:
rotbytes = [0] * height
for x in range(0,height):
for y in range(0,height):
rotbytes[-1-x] |= (((bytes[-1-y]>>x)&1)<<y)
bytes = rotbytes
#rotoutput[-7+x] |= (((output[-1-y]>>x)&1)<<y)
#rotoutput[-1-x] |= (((output[-1-y]>>x)&1)<<y)
#rot2output[-1-x] |= (((output[-7+y]>>x)&1)<<y)
for b in bytes:
output.append(b)
def tohex(v):
return '%02x'%v
def tohex2(v):
return '0x%02x'%v
def tohexv(v):
return "8'h%02x"%v
for arr in [output]:
if args.asmhex:
print('\thex ' + ''.join(list(map(tohex,arr))))
if args.asmdb:
for i in range(0,len(output),height):
print('.DB', ','.join(list(map(tohex2,arr[i:i+height]))), ';%d'%(i/height+lochar))
if args.carray:
print("static char FONT[%d][%d] = {" % (hichar-lochar+1, height))
for i in range(0,len(output),height):
print('{', ','.join(list(map(tohex2,arr[i:i+height]))), '},', end=' ')
print()
print("};")
if args.flatcarray:
print("static char FONT[%d] = {" % ((hichar-lochar+1) * height))
print(','.join(list(map(tohex2,arr))))
print("}");
if args.verilog:
j = 0
for i in range(0,len(output),height):
print(','.join(list(map(tohexv,arr[i:i+height]))) + ", //%d" % (i/height))
j += 1

View File

@ -1,37 +0,0 @@
#!/usr/bin/python
import sys
# reverse byte
def rev(n):
return int('{:08b}'.format(n)[::-1], 2)
# output bits in given range
def out(i, pix, lb, hb, reverse=0, shift=0):
x = (pix >> lb) & ((1<<(hb-lb))-1)
if reverse:
x = rev(x)
if shift:
x = x << shift
assert(x>=0 and x<=255)
output[i].append(x)
# read PBM (binary P4 format) file
with open(sys.argv[1],'rb') as f:
# read PBM header
header = f.readline().strip()
assert(header == 'P4')
dims = f.readline().strip()
while dims[0] == '#':
dims = f.readline().strip()
width,height = map(int, dims.split())
wbytes = (width+7)/8
data = f.read()
print("{%d,%d," % (wbytes,height), end='')
for i in range(0,len(data)):
if i>0:
sys.stdout.write(",")
ofs = i+wbytes-(i%wbytes)*2-1
sys.stdout.write( "0x%02x" % ord(data[ofs]) )
print("}")

View File

@ -1,46 +0,0 @@
#!/usr/bin/python
import sys, array, string
col0 = 0
def tocolor(x):
if x == 0:
return 0
else:
return x + col0
def tohex2(v):
return '0x%02x'%v
with open(sys.argv[1],'rb') as f:
data = array.array('B', f.read())
assert data[0] == 0xa
assert data[3] == 8
# palette
print("byte palette[16] = {", end='')
for i in range(0,16):
r = data[16+i*3]
g = data[17+i*3]
b = data[18+i*3]
entry = (r>>5) | ((g>>2)&0x38) | (b&0xc0)
print('%s,' % (tohex2(entry)), end='')
print("}")
# image data
width = (data[9] << 8) + data[8] + 1
height = (data[11] << 8) + data[10] + 1
rowlen = (data[0x43] << 8) + data[0x42]
print("const byte sprite[] = {")
print("%d,%d," % ((width+1)/2,height))
for y in range(0,height):
ofs = 0x80 + y*rowlen
output = []
for x in range(0,width,2):
b = (tocolor(data[ofs]) << 4) + tocolor(data[ofs+1])
output.append(b)
ofs += 2
print(','.join(map(tohex2,output)) + ',')
print("}")

View File

@ -1,83 +0,0 @@
#!/usr/bin/env node
var fs = require('fs'),
PNG = require('pngjs').PNG,
RgbQuant = require('rgbquant');
var data = fs.readFileSync(process.argv[2]);
var png = PNG.sync.read(data);
q = new RgbQuant();
q.colors = 4;
q.sample(png.data);
pal = q.palette(false, true);
//console.log(q);
function readfonttxt(s) {
var lines = s.split(/\r?\n/);// TODO
}
function remapBits(x, arr) {
if (!arr) return x;
var y = 0;
for (var i=0; i<arr.length; i++) {
var s = arr[i];
if (s < 0) {
s = -s-1;
y ^= 1 << s;
}
if (x & (1 << i)) {
y ^= 1 << s;
}
}
return y;
}
function reorder(arrin, remap) {
var out = [];
for (var i=0; i<arrin.length; i++) {
var j = remapBits(i, remap);
//console.log(i,j);
if (j >= arrin.length) throw i+" -> "+j+" >= "+arrin.length;
out.push(arrin[j] | 0);
}
return out;
}
function packbits(arrin, bpp, brev) {
var out = new Uint8Array((arrin.length * bpp) >> 3);
for (var i=0; i<arrin.length; i++) {
var j = (i * bpp) >> 3;
var s = (i * bpp) & 7;
if (brev) s = 8-bpp-s;
out[j] |= arrin[i] << s;
}
return out;
}
function hex(n) {
return (n < 16 ? "0" : "") + n.toString(16);
}
function dump(arr, bpl) {
var s = '';
for (var i=0; i<arr.length; i++) {
if (i % bpl == 0) {
s += '\n.byte ';
} else {
s += ',';
}
s += '$' + hex(arr[i]);
}
s += '\n';
return s;
}
idximg = q.reduce(png.data, 2);
//idximg = idximg.slice(0, 8*16*128);
//idximg = idximg.slice(8*16*64);
idx2 = reorder(idximg, [0,1,2,3,4,5,6,11,12,13,-8,-9,-10,-11]); // 8x16 font
//idx2 = reorder(idximg, [0,1,2,3,5,6,11,12,13,99,-8,-9,-10,-5]); // 8x16 CHR tileset
idx3 = packbits(idx2, 2, true);
//console.log(idximg.length, idx2.length, idx3.length);
console.log(dump(idx3, 8));
console.log(";;",idx3.length,"bytes,",pal.length/4,'colors');

View File

@ -1,462 +0,0 @@
/*
---------------------------------------------------------------
TMSOPT v.0.1 - Eduardo A. Robsy Petrus & Arturo Ragozini 2007
Credits to Rafael Jannone for his Floyd-Steinberg implementation
---------------------------------------------------------------
TGA image converter (24 bpp, uncompressed) to TMS9918 format
---------------------------------------------------------------
Overview
---------------------------------------------------------------
Selects the best solution for each 8x1 pixel block
Optimization uses the following algorithm:
(a) Select one 1x8 block, select a couple of colors, apply
Floyd-Steinberg within the block, compute the squared error,
repeat for all 105 color combinations, keep the best couple
of colors.
(b) Apply Floyd-Steinberg to the current 1x8 block with the best
two colors seleted before and spread the errors to the
adjacent blocks.
(c) repeat (a) and (b) on the next 1x8 block, scan all lines.
(d) Convert the image in pattern and color definitions (CHR & CLR)
To load in MSX basic use something like this:
10 screen 2: color 15,0,0
20 bload"FILE.CHR",s
30 bload"FILE.CLR",s
40 goto 40
---------------------------------------------------------------
Compilation instructions
---------------------------------------------------------------
Tested with GCC/Win32 [mingw]:
GCC TMSopt.c -oTMSopt.exe -O3 -s
It is standard C, so there is a fair chance of being portable!
NOTE
In the current release the name of the C file has become scr2floyd.c
---------------------------------------------------------------
History
---------------------------------------------------------------
Ages ago - algorithm created
16/05/2007 - first C version (RAW format)
17/05/2007 - TGA format included, some optimization included
18/05/2007 - Big optimization (200 times faster), support for
square errors
19/05/2007 - Floyd-Stenberg added, scaling for better rounding
24/05/2007 - Floyd-Stenberg included in the color optimization.
---------------------------------------------------------------
Legal disclaimer
---------------------------------------------------------------
Do whatever you want to do with this code/program.
Use at your own risk, all responsability would be declined.
It would be nice if you credit the authors, though.
---------------------------------------------------------------
*/
// Headers!
#include<stdio.h>
#include<time.h>
#include<limits.h>
#include<stdlib.h>
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned short ushort;
//#define DEBUG
#define scale 16
#define inrange8(t) ((t)<0) ? 0 :(((t)>255) ? 255:(t))
#define clamp(t) ((t)<0) ? 0 :(((t)>255*scale) ? 255*scale : (t))
// Just one function for everything
int main(int argc, char **argv)
{
// Vars
FILE *file,*CHR,*CLR;
int bc,bp,i,j,x,y,c,p,k,MAXX,MAXY;
uint n,total=0,done=0,size;
char *name;
short image[512+2][512+2][3],header[18],palette[16][3];
// TMS9918 RGB palette - approximated 50Hz PAL values
uint pal[16][3]= {
{ 0,0,0}, // 0 Transparent
{ 0,0,0}, // 1 Black 0 0 0
{ 33,200,66}, // 2 Medium green 33 200 66
{ 94,220,120}, // 3 Light green 94 220 120
{ 84,85,237}, // 4 Dark blue 84 85 237
{ 125,118,252}, // 5 Light blue 125 118 252
{ 212,82,77}, // 6 Dark red 212 82 77
{ 66,235,245}, // 7 Cyan 66 235 245
{ 252,85,84}, // 8 Medium red 252 85 84
{ 255,121,120}, // 9 Light red 255 121 120
{ 212,193,84}, // A Dark yellow 212 193 84
{ 230,206,128}, // B Light yellow 230 206 128
{ 33,176,59}, // C Dark green 33 176 59
{ 201,91,186}, // D Magenta 201 91 186
{ 204,204,204}, // E Gray 204 204 204
{ 255,255,255} // F White 255 255 255
};
// Scale palette
for (i=0;i<16;i++)
for (k=0;k<3;k++)
palette[i][k] = scale*pal[i][k];
// Get time
clock();
// Application prompt
printf("TMSopt v.0.1 - TGA 24bpp to TMS9918 converter.\nCoded by Eduardo A. Robsy Petrus & Arturo Ragozini 2007.\n\n");
printf("Credits to Rafael Jannone for his Floyd-Steinberg implementation.\n \n");
// Guess the name of the image I used for testing
#ifdef DEBUG
argc = 2;
argv[1] = malloc(20);
argv[1][0] = 'l';
argv[1][1] = 'e';
argv[1][2] = 'n';
argv[1][3] = 'n';
argv[1][4] = 'a';
argv[1][5] = '_';
argv[1][6] = '.';
argv[1][7] = 't';
argv[1][8] = 'g';
argv[1][9] = 'a';
argv[1][10] = 0;
#endif
// Test if only one command-line parameter is available
if (argc==1)
{
printf("Syntax: TMSopt [file.tga]\n");
return 1;
}
// Open source image (TGA, 24-bit, uncompressed)
if ((file=fopen(argv[1],"rb"))==NULL)
{
printf("cannot open %s file!\n",argv[1]);
return 2;
}
// Read TGA header
for (i=0;i<18;i++) header[i]=fgetc(file);
// Check header info
for (i=0,n=0;i<12;i++) n+=header[i];
// I deleted the check on n, was it important ?
if ((header[2]!=2)||(header[17])||(header[16]!=24))
{
printf("Unsupported file format!\n");
return 3;
}
// Calculate size
MAXX=header[12]|header[13]<<8;
MAXY=header[14]|header[15]<<8;
size=((MAXX+7)>>3)*MAXY;
// Check size limits
if ((!MAXX)||(MAXX>512)||(!MAXY)||(MAXY>512))
{
printf("Unsupported size!");
return 4;
}
// Load image data
for (y=MAXY-1;y>=0;y--)
for (x=0;x<MAXX;x++)
for (k=0;k<3;k++)
image[x+1][y+1][2-k]=((short)fgetc(file))*scale; // Scale image
for (x=0;x<MAXX;x++)
for (k=0;k<3;k++)
image[x][0][k] = image[x][1][k];
for (y=0;y<MAXY;y++)
for (k=0;k<3;k++)
image[0][y][k] = image[1][0][k];
// Close file
fclose(file);
// Information
printf("Converting %s (%i,%i) to TMS9918 format ",argv[1],MAXX,MAXY);
printf("in (%i,%i) screen 2 tiles... ",((MAXX+7)>>3),((MAXY+7)>>3));
// Image processing
for (y=0;y<((MAXY+7)>>3);y++)
for (j=0;j<8;j++)
for (x=0;x<((MAXX+7)>>3);x++)
{
// Generate alternatives
uchar c1, c2;
uchar bc1, bc2;
uint bv;
uint bs = INT_MAX;
uint yy = 1+((y<<3)|j);
for (c1=1;c1<16;c1++)
{
ushort c1r,c1g,c1b;
c1r = palette[c1][0];
c1g = palette[c1][1];
c1b = palette[c1][2];
for (c2=c1+1;c2<16;c2++)
{
ushort c2r,c2g,c2b;
ushort r,g,b;
uint cs = 0;
uint cv = 0;
uint xx = 1+(x<<3);
c2r = palette[c2][0];
c2g = palette[c2][1];
c2b = palette[c2][2];
r = clamp(image[xx][yy][0]);
g = clamp(image[xx][yy][1]);
b = clamp(image[xx][yy][2]);
for (i=0;i<8;i++)
{
short e10 = (r-c1r);
short e11 = (g-c1g);
short e12 = (b-c1b);
uint mc1 = e10*e10+e11*e11+e12*e12;
short e20 = (r-c2r);
short e21 = (g-c2g);
short e22 = (b-c2b);
uint mc2 = e20*e20+e21*e21+e22*e22;
cs += (mc1>mc2) ? mc2 : mc1;
if (cs>bs) break;
cv |= ((mc1>mc2)<<i);
xx++;
if (mc1>mc2)
{
r = clamp(image[xx][yy][0]) + 7*e20/16 ;
g = clamp(image[xx][yy][1]) + 7*e21/16 ;
b = clamp(image[xx][yy][2]) + 7*e22/16 ;
}
else
{
r = clamp(image[xx][yy][0]) + 7*e10/16 ;
g = clamp(image[xx][yy][1]) + 7*e11/16 ;
b = clamp(image[xx][yy][2]) + 7*e12/16 ;
}
}
if (cs<bs)
{
bs = cs;
bv = cv;
bc1 = c1;
bc2 = c2;
}
}
}
// Here we have the best colors and the best pattern for line j
short quant_error;
uint xx = 1+((x<<3));
for (i=0;i<8;i++,xx++)
for (k=0;k<3;k++)
{
// Compute the quantization error
if (bv&(1<<i))
{
quant_error = (clamp(image[xx][yy][k]) - palette[bc2][k])/16;
image[xx][yy][k] = palette[bc2][k];
}
else
{
quant_error = (clamp(image[xx][yy][k]) - palette[bc1][k])/16;
image[xx][yy][k] = palette[bc1][k];
}
// Spread the quantization error
short q2 = quant_error<<1;
image[xx+1][yy+1][k] = clamp(image[xx+1][yy+1][k])+ quant_error; // 1 *
quant_error += q2 ;
image[xx-1][yy+1][k] = clamp(image[xx-1][yy+1][k])+ quant_error; // 3 *
quant_error += q2 ;
image[xx+0][yy+1][k] = clamp(image[xx+0][yy+1][k])+ quant_error; // 5 *
quant_error += q2 ;
image[xx+1][yy+0][k] = clamp(image[xx+1][yy+0][k])+ quant_error; // 7 *
}
// Update status counter
if (done*100/size<(done+1)*100/size)
printf("\b\b\b%2i%%",100*done/size);
done++;
total++;
}
// Conversion done
printf("\b\b\bOk \n");
// Create TMS output files (CHR, CLR)
argv[1][strlen(argv[1])-3]='C';
argv[1][strlen(argv[1])-2]='H';
argv[1][strlen(argv[1])-1]='R';
CHR=fopen(argv[1],"wb");
argv[1][strlen(argv[1])-2]='L';
CLR=fopen(argv[1],"wb");
fputc(0xFE,CLR); // Binary data
fputc(0x00,CLR); // Start at 2000h
fputc(0x20,CLR);
fputc(0xFF,CLR); // Stop at 37FFh
fputc(0x37,CLR);
fputc(0x00,CLR); // Run
fputc(0x00,CLR);
fputc(0xFE,CHR); // Binary data
fputc(0x00,CHR); // Start at 0000h
fputc(0x00,CHR);
fputc(0xFF,CHR); // Stop at 17FFh
fputc(0x17,CHR);
fputc(0x00,CHR); // Run
fputc(0x00,CHR);
// Save best pattern and colour combination
// NOTE1:
// THIS PART CAN BE LARGELY CUTTED AND OPTIMIZED REUSING
// RESULTS FROM THE PREVIOUS LOOP, BUT WHO CARES?
// NOTE2:
// This code can be used for conversion without dithering
for (y=0;y<((MAXY+7)>>3);y++)
for (x=0;(x<(MAXX+7)>>3);x++)
for (j=0;j<8;j++)
{
uchar c1,c2;
uint bs = INT_MAX;
uchar bp = 0, bc = 0;
uint yy = 1+((y<<3)|j);
for (c1=1;c1<16;c1++)
for (c2=c1+1;c2<16;c2++)
{
uint cs = 0;
uint cp = 0;
for (i=0;i<8;i++)
{
uint xx = 1+((x<<3)|i);
short u0 = (palette[c1][0]-image[xx][yy][0]);
short u1 = (palette[c1][1]-image[xx][yy][1]);
short u2 = (palette[c1][2]-image[xx][yy][2]);
uint mc1 = u0*u0+u1*u1+u2*u2;
short v0 = (palette[c2][0]-image[xx][yy][0]);
short v1 = (palette[c2][1]-image[xx][yy][1]);
short v2 = (palette[c2][2]-image[xx][yy][2]);
uint mc2 = v0*v0+v1*v1+v2*v2;
cp = (cp<<1) | (mc1>mc2);
cs += (mc1>mc2) ? mc2 : mc1;
if (cs>bs) break;
}
if (cs<bs)
{
bs=cs;
bp=cp;
bc=c2*16+c1;
}
}
fputc(bc,CLR);
fputc(bp,CHR);
}
fclose(CHR);
fclose(CLR);
// Generate new name
name = malloc(0x100);
argv[1][strlen(argv[1])-4]=0;
strcpy(name,argv[1]);
strcat(name,"_tms.tga");
// Save file header
file=fopen(name,"wb");
for (i=0;i<18;i++) fputc(header[i],file);
// Save image data
for (y=MAXY-1;y>=0;y--)
for (x=0;x<MAXX;x++)
for (k=0;k<3;k++)
fputc(inrange8(image[1+x][1+y][2-k]/scale),file); // Scale to char
// Close file
fclose(file);
// Prompt elapsed time
printf("%.2f million combinations analysed in %.2f seconds.\n",total/1e6,(float)clock()/(float)CLOCKS_PER_SEC);
printf("Note: the .CLR and .CHR files have correct headers only for 256x192 images. \n");
return 0;
}

View File

@ -1,476 +0,0 @@
/*
---------------------------------------------------------------
TMSOPT v.0.1 - Eduardo A. Robsy Petrus & Arturo Ragozini 2007
Credits to Rafael Jannone for his Floyd-Steinberg implementation
---------------------------------------------------------------
TGA image converter (24 bpp, uncompressed) to TMS9918 format
---------------------------------------------------------------
Overview
---------------------------------------------------------------
Selects the best solution for each 8x1 pixel block
Optimization uses the following algorithm:
(a) Select one 1x8 block, select a couple of colors, apply
Floyd-Steinberg within the block, compute the squared error,
repeat for all 105 color combinations, keep the best couple
of colors.
(b) Apply Floyd-Steinberg to the current 1x8 block with the best
two colors seleted before and spread the errors to the
adjacent blocks.
(c) repeat (a) and (b) on the next 1x8 block, scan all lines.
(d) Convert the image in pattern and color definitions (CHR & CLR)
To load in MSX basic use something like this:
10 screen 2: color 15,0,0
20 bload"FILE.CHR",s
30 bload"FILE.CLR",s
40 goto 40
---------------------------------------------------------------
Compilation instructions
---------------------------------------------------------------
Tested with GCC/Win32 [mingw]:
GCC TMSopt.c -oTMSopt.exe -O3 -s
It is standard C, so there is a fair chance of being portable!
NOTE
In the current release the name of the C file has become scr2floyd.c
---------------------------------------------------------------
History
---------------------------------------------------------------
Ages ago - algorithm created
16/05/2007 - first C version (RAW format)
17/05/2007 - TGA format included, some optimization included
18/05/2007 - Big optimization (200 times faster), support for
square errors
19/05/2007 - Floyd-Stenberg added, scaling for better rounding
24/05/2007 - Floyd-Stenberg included in the color optimization.
---------------------------------------------------------------
Legal disclaimer
---------------------------------------------------------------
Do whatever you want to do with this code/program.
Use at your own risk, all responsability would be declined.
It would be nice if you credit the authors, though.
---------------------------------------------------------------
*/
// Headers!
#include<stdio.h>
#include<time.h>
#include<limits.h>
#include<stdlib.h>
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;
//#define DEBUG
#define scale 16
#define inrange8(t) ((t)<0) ? 0 :(((t)>255) ? 255:(t))
#define clamp(t) ((t)<0) ? 0 :(((t)>255*scale) ? 255*scale : (t))
typedef struct {
float r, g, b;
} RGB;
float ColourDistance(RGB e1, RGB e2)
{
float r,g,b;
float rmean;
e1.r/=scale;
e1.g/=scale;
e1.b/=scale;
e2.r/=scale;
e2.g/=scale;
e2.b/=scale;
rmean = ( (int)e1.r + (int)e2.r ) / 2 ;
r = ((int)e1.r - (int)e2.r);
g = ((int)e1.g - (int)e2.g);
b = ((int)e1.b - (int)e2.b);
// return r*r+g*g+b*b;
return ((((512+rmean)*r*r)/256) + 4*g*g + (((767-rmean)*b*b)/256));
}
// Just one function for everything
int main(int argc, char **argv)
{
// Vars
FILE *file,*CHR,*CLR;
int bc,bp,i,j,x,y,c,p,k,MAXX,MAXY;
uint n,total=0,done=0,size;
char *name;
short image[512+2][512+2][3],header[18],palette[16][3];
// TMS9918 RGB palette - approximated 50Hz PAL values
uint pal[16][3]= {
{ 0,0,0}, // 0 Transparent
{ 0,0,0}, // 1 Black 0 0 0
{ 33,200,66}, // 2 Medium green 33 200 66
{ 94,220,120}, // 3 Light green 94 220 120
{ 84,85,237}, // 4 Dark blue 84 85 237
{ 125,118,252}, // 5 Light blue 125 118 252
{ 212,82,77}, // 6 Dark red 212 82 77
{ 66,235,245}, // 7 Cyan 66 235 245
{ 252,85,84}, // 8 Medium red 252 85 84
{ 255,121,120}, // 9 Light red 255 121 120
{ 212,193,84}, // A Dark yellow 212 193 84
{ 230,206,128}, // B Light yellow 230 206 128
{ 33,176,59}, // C Dark green 33 176 59
{ 201,91,186}, // D Magenta 201 91 186
{ 204,204,204}, // E Gray 204 204 204
{ 255,255,255} // F White 255 255 255
};
// Scale palette
for (i=0;i<16;i++)
for (k=0;k<3;k++)
palette[i][k] = scale*pal[i][k];
// Get time
clock();
// Application prompt
printf("TMSopt v.0.1 - TGA 24bpp to TMS9918 converter.\nCoded by Eduardo A. Robsy Petrus & Arturo Ragozini 2007.\n\n");
printf("Credits to Rafael Jannone for his Floyd-Steinberg implementation.\n \n");
// Guess the name of the image I used for testing
#ifdef DEBUG
argc = 2;
argv[1] = malloc(20);
argv[1][0] = 'l';
argv[1][1] = 'e';
argv[1][2] = 'n';
argv[1][3] = 'n';
argv[1][4] = 'a';
argv[1][5] = '_';
argv[1][6] = '.';
argv[1][7] = 't';
argv[1][8] = 'g';
argv[1][9] = 'a';
argv[1][10] = 0;
#endif
// Test if only one command-line parameter is available
if (argc==1)
{
printf("Syntax: TMSopt [file.tga]\n");
return 1;
}
// Open source image (TGA, 24-bit, uncompressed)
if ((file=fopen(argv[1],"rb"))==NULL)
{
printf("cannot open %s file!\n",argv[1]);
return 2;
}
// Read TGA header
for (i=0;i<18;i++) header[i]=fgetc(file);
// Check header info
for (i=0,n=0;i<12;i++) n+=header[i];
// I deleted the check on n, was it important ?
if ((header[2]!=2)||(header[17])||(header[16]!=24))
{
printf("Unsupported file format!\n");
return 3;
}
// Calculate size
MAXX=header[12]|header[13]<<8;
MAXY=header[14]|header[15]<<8;
size=((MAXX+7)>>3)*MAXY;
// Check size limits
if ((!MAXX)||(MAXX>512)||(!MAXY)||(MAXY>512))
{
printf("Unsupported size!");
return 4;
}
// Load image data
for (y=MAXY-1;y>=0;y--)
for (x=0;x<MAXX;x++)
for (k=0;k<3;k++)
image[x+1][y+1][2-k]=((short)fgetc(file))*scale; // Scale image
for (x=0;x<MAXX;x++)
for (k=0;k<3;k++)
image[x][0][k] = image[x][1][k];
for (y=0;y<MAXY;y++)
for (k=0;k<3;k++)
image[0][y][k] = image[1][0][k];
// Close file
fclose(file);
// Information
printf("Converting %s (%i,%i) to TMS9918 format ",argv[1],MAXX,MAXY);
printf("in (%i,%i) screen 2 tiles... ",((MAXX+7)>>3),((MAXY+7)>>3));
// Image processing
for (y=0;y<((MAXY+7)>>3);y++)
for (j=0;j<8;j++)
for (x=0;x<((MAXX+7)>>3);x++)
{
// Generate alternatives
uchar c1, c2;
uchar bc1, bc2;
uint bv;
uint bs = INT_MAX;
uint yy = 1+((y<<3)|j);
for (c1=1;c1<16;c1++)
{
RGB cp1 = {palette[c1][0],palette[c1][1],palette[c1][2]};
for (c2=c1+1;c2<16;c2++)
{
RGB cp2 = {palette[c2][0],palette[c2][1],palette[c2][2]};
uint xx = 1+(x<<3);
RGB ppp = {clamp(image[xx][yy][0]),clamp(image[xx][yy][1]),clamp(image[xx][yy][2])};
uint cs = 0;
uint cv = 0;
for (i=0;i<8;i++)
{
short e10 = (ppp.r-cp1.r);
short e11 = (ppp.g-cp1.g);
short e12 = (ppp.b-cp1.b);
long mc1 = ColourDistance(cp1,ppp);
short e20 = (ppp.r-cp2.r);
short e21 = (ppp.g-cp2.g);
short e22 = (ppp.b-cp2.b);
long mc2 = ColourDistance(cp2,ppp);
cs += (mc1>mc2) ? mc2 : mc1;
if (cs>bs) break;
cv |= ((mc1>mc2)<<i);
xx++;
if (mc1>mc2)
{
ppp.r = clamp(image[xx][yy][0]) + 7*e20/16;
ppp.g = clamp(image[xx][yy][1]) + 7*e21/16;
ppp.b = clamp(image[xx][yy][2]) + 7*e22/16;
}
else
{
ppp.r = clamp(image[xx][yy][0]) + 7*e10/16;
ppp.g = clamp(image[xx][yy][1]) + 7*e11/16;
ppp.b = clamp(image[xx][yy][2]) + 7*e12/16;
}
}
if (cs<bs)
{
bs = cs;
bv = cv;
bc1 = c1;
bc2 = c2;
}
}
}
// Here we have the best colors and the best pattern for line j
short quant_error;
uint xx = 1+((x<<3));
for (i=0;i<8;i++,xx++)
for (k=0;k<3;k++)
{
// Compute the quantization error
if (bv&(1<<i))
{
quant_error = (clamp(image[xx][yy][k]) - palette[bc2][k])/16;
image[xx][yy][k] = palette[bc2][k];
}
else
{
quant_error = (clamp(image[xx][yy][k]) - palette[bc1][k])/16;
image[xx][yy][k] = palette[bc1][k];
}
// Spread the quantization error
short q2 = quant_error<<1;
image[xx+1][yy+1][k] = clamp(image[xx+1][yy+1][k])+ quant_error; // 1 *
quant_error += q2 ;
image[xx-1][yy+1][k] = clamp(image[xx-1][yy+1][k])+ quant_error; // 3 *
quant_error += q2 ;
image[xx+0][yy+1][k] = clamp(image[xx+0][yy+1][k])+ quant_error; // 5 *
quant_error += q2 ;
image[xx+1][yy+0][k] = clamp(image[xx+1][yy+0][k])+ quant_error; // 7 *
}
// Update status counter
if (done*100/size<(done+1)*100/size)
printf("\b\b\b%2i%%",100*done/size);
done++;
total++;
}
// Conversion done
printf("\b\b\bOk \n");
// Create TMS output files (CHR, CLR)
argv[1][strlen(argv[1])-3]='C';
argv[1][strlen(argv[1])-2]='H';
argv[1][strlen(argv[1])-1]='R';
CHR=fopen(argv[1],"wb");
argv[1][strlen(argv[1])-2]='L';
CLR=fopen(argv[1],"wb");
fputc(0xFE,CLR); // Binary data
fputc(0x00,CLR); // Start at 2000h
fputc(0x20,CLR);
fputc(0xFF,CLR); // Stop at 37FFh
fputc(0x37,CLR);
fputc(0x00,CLR); // Run
fputc(0x00,CLR);
fputc(0xFE,CHR); // Binary data
fputc(0x00,CHR); // Start at 0000h
fputc(0x00,CHR);
fputc(0xFF,CHR); // Stop at 17FFh
fputc(0x17,CHR);
fputc(0x00,CHR); // Run
fputc(0x00,CHR);
// Save best pattern and colour combination
// NOTE1:
// THIS PART CAN BE LARGELY CUTTED AND OPTIMIZED REUSING
// RESULTS FROM THE PREVIOUS LOOP, BUT WHO CARES?
// NOTE2:
// This code can be used for conversion without dithering
for (y=0;y<((MAXY+7)>>3);y++)
for (x=0;(x<(MAXX+7)>>3);x++)
for (j=0;j<8;j++)
{
uchar c1,c2;
uint bs = INT_MAX;
uchar bp = 0, bc = 0;
uint yy = 1+((y<<3)|j);
for (c1=1;c1<16;c1++)
{
RGB cp1 = {palette[c1][0],palette[c1][1],palette[c1][2]};
for (c2=c1+1;c2<16;c2++)
{
RGB cp2 = {palette[c2][0],palette[c2][1],palette[c2][2]};
uint cs = 0;
uint cp = 0;
for (i=0;i<8;i++)
{
uint xx = 1+((x<<3)|i);
RGB ppp = {clamp(image[xx][yy][0]),clamp(image[xx][yy][1]),clamp(image[xx][yy][2])};
long mc1 = ColourDistance(cp1,ppp);
long mc2 = ColourDistance(cp2,ppp);
cp = (cp<<1) | (mc1>mc2);
cs += (mc1>mc2) ? mc2 : mc1;
if (cs>bs) break;
}
if (cs<bs)
{
bs=cs;
bp=cp;
bc=c2*16+c1;
}
}
}
fputc(bc,CLR);
fputc(bp,CHR);
}
fclose(CHR);
fclose(CLR);
// Generate new name
name = malloc(0x100);
argv[1][strlen(argv[1])-4]=0;
strcpy(name,argv[1]);
strcat(name,"_tms.tga");
// Save file header
file=fopen(name,"wb");
for (i=0;i<18;i++) fputc(header[i],file);
// Save image data
for (y=MAXY-1;y>=0;y--)
for (x=0;x<MAXX;x++)
for (k=0;k<3;k++)
fputc(inrange8(image[1+x][1+y][2-k]/scale),file); // Scale to char
// Close file
fclose(file);
// Prompt elapsed time
printf("%.2f million combinations analysed in %.2f seconds.\n",total/1e6,(float)clock()/(float)CLOCKS_PER_SEC);
printf("Note: the .CLR and .CHR files have correct headers only for 256x192 images. \n");
return 0;
}

View File

@ -1,43 +0,0 @@
#!/usr/bin/python
import sys, zipfile
OUTFILE = 'scramble.zip'
ROMS = [
( "s1.2d", 0x0000, 0x0800),
( "s2.2e", 0x0800, 0x0800),
( "s3.2f", 0x1000, 0x0800),
( "s4.2h", 0x1800, 0x0800),
( "s5.2j", 0x2000, 0x0800),
( "s6.2l", 0x2800, 0x0800),
( "s7.2m", 0x3000, 0x0800),
( "s8.2p", 0x3800, 0x0800),
# ROM_REGION( 0x10000, "audiocpu", 0 )
( "ot1.5c", 0x0000, 0x0800),
( "ot2.5d", 0x0800, 0x0800),
( "ot3.5e", 0x1000, 0x0800),
# ROM_REGION( 0x1000, "gfx1", 0 )
( "c2.5f", 0x4000, 0x0800),
( "c1.5h", 0x4800, 0x0800),
# ROM_REGION( 0x0020, "proms", 0 )
( "c01s.6e", 0x5000, 0x0020),
]
fn = sys.argv[1]
with open(fn, 'rb') as f:
data = f.read()
print "Read %d bytes of %s" % (len(data), fn)
with zipfile.ZipFile(OUTFILE, 'w') as zipf:
for name,start,length in ROMS:
romdata = data[start:start+length]
if len(romdata) != length:
print "*** No data for %s (offset 0x%x)" % (name,start)
romdata = '\0' * length
zipf.writestr(name, romdata)
else:
print 'Wrote %s (%d bytes)' % (name, length)
zipf.writestr(name, romdata)

View File

@ -1,16 +0,0 @@
import math
#n = 8
#m = 127
n = 32
m = 127
n = 4
m = 7
for i in range(0,n*4):
print('%d,' % int(round(math.sin(i*math.pi/2/n)*m)), end='')
if i % 16 == 15:
print('')

View File

@ -1,71 +0,0 @@
#!/usr/bin/python
import sys
from xml.dom import minidom
def textToFloat(name):
if name:
return float(name)
else:
return None
def textToColor(name,opacity):
if name is None or not name[0] == '#':
return None
color = int(name[1:],16) << 8
if opacity:
print(('opacity',opacity))
return color
svg_file = sys.argv[1]
doc = minidom.parse(svg_file) # parseString also exists
groups = doc.getElementsByTagName('g')
for grp in groups:
groupID = grp.getAttribute('id')
paths = grp.getElementsByTagName('path')
print((groupID,paths))
if len(paths):
for path in paths:
shape = {}
d = path.getAttribute('d')
styleAttrs = {}
style = path.getAttribute('style')
sarr = style.split(';')
for s in sarr:
nvarr = s.split(':', 2)
if len(nvarr) == 2:
styleAttrs[nvarr[0]] = nvarr[1]
print((path,d,styleAttrs))
shape['pts'] = []
shape['currentColor'] = textToColor(styleAttrs.get("stroke"), styleAttrs.get("stroke-opacity"))
shape['currentWidth'] = textToFloat(styleAttrs.get("strokeWidth"))
hidden = "none" == styleAttrs.get("display")
cmds = d.split(' ')
x = 0
y = 0
i0 = 0
start = True
for cmd in cmds:
print(cmd)
ch = cmd[0]
if ch == 'm' or ch == 'l':
start = True
elif ch == 'z':
origin = shape['pts'][i0]
shape.lineTo(origin.x, origin.y)
elif ch == 'c':
skip = True
else:
xy = cmd.split(',')
print(xy)
x += float(xy[0])
y -= float(xy[1])
if start or hidden:
shape.moveTo(x,y)
else:
shape.lineTo(x,y)
start = False
doc.unlink()

View File

@ -1,17 +0,0 @@
# convert PBM bitmap to playfield bytes
%-pf.hex: %-pf.pbm p4_to_pfbytes.py
python p4_to_pfbytes.py $< > $@
# convert PBM bitmap to 48-pixel sprite
%-48.hex: %-48.pbm p4_to_48pix.py
python p4_to_48pix.py $< > $@
# convert JPG to pbm
%-pf.pbm: %.jpg
convert $< -resize 40x192\! -colorspace Gray -dither FloydSteinberg $@
%-48.pbm: %.jpg
convert $< -resize 48x192\! -colorspace Gray -dither FloydSteinberg $@

View File

@ -1,58 +0,0 @@
#!/usr/bin/python
import sys, struct
# playfield bytes, one array for each of 6 columns
output = [[],[],[],[],[],[]]
# reverse byte
def rev(n):
return int('{:08b}'.format(n)[::-1], 2)
# output bits in given range
def out(i, pix, lb, hb, reverse=0, shift=0):
x = (pix >> lb) & ((1<<(hb-lb))-1)
if reverse:
x = rev(x)
if shift:
x = x << shift
assert(x>=0 and x<=255)
output[i].append(x)
# read PBM (binary P4 format) file
with open(sys.argv[1],'rb') as f:
# read PBM header
header = f.readline().strip()
assert(header == 'P4')
dims = f.readline().strip()
if dims[0] == '#':
dims = f.readline().strip()
width,height = map(int, dims.split())
assert(width==48)
# read bitmap rows
for y in range(0,height):
row = bytes(f.read(6) + '\0\0') # pad to 8 bytes
# convert to 64-bit integer
pix = struct.unpack('<q',row)[0]
#print '%010lx' % pix
# generate playfield bytes
out(0, pix, 0, 8, 0)
out(1, pix, 8, 16, 0)
out(2, pix, 16, 24, 0)
out(3, pix, 24, 32, 0)
out(4, pix, 32, 40, 0)
out(5, pix, 40, 48, 0)
# output bitmap tables
for c in range(0,6):
print "\talign $100"
print "Bitmap%d" % c
print "\thex 00"
s = '\thex '
for i in range(0,height):
s += '%02x' % output[c][height-i-1]
if i % 16 == 15:
print s
s = '\thex '
if len(s)>5:
print s

View File

@ -1,62 +0,0 @@
#!/usr/bin/python
import sys, struct
# playfield bytes, one array for each of 6 columns
output = [[],[],[],[],[],[]]
# reverse byte
def rev(n):
return int('{:08b}'.format(n)[::-1], 2)
# output bits in given range
def out(i, pix, lb, hb, reverse=0, shift=0):
x = (pix >> lb) & ((1<<(hb-lb))-1)
if reverse:
x = rev(x)
if shift:
x = x << shift
assert(x>=0 and x<=255)
output[i].append(x)
# read PBM (binary P4 format) file
with open(sys.argv[1],'rb') as f:
# read PBM header
header = f.readline().strip()
assert(header == 'P4')
dims = f.readline().strip()
if dims[0] == '#':
dims = f.readline().strip()
width,height = map(int, dims.split())
assert(width==40)
# read bitmap rows
for y in range(0,height):
row = bytes(f.read(5) + '\0\0\0') # pad to 8 bytes
# convert bytes from MSB first to LSB first
row2 = ''
for i in range(0,8):
row2 += chr(rev(ord(row[i])))
# convert to 64-bit integer
pix = struct.unpack('<q',row2)[0]
#print '%010lx' % pix
# generate playfield bytes
out(0, pix, 0, 4, 0, 4)
out(1, pix, 4, 12, 1)
out(2, pix, 12, 20, 0)
out(3, pix, 20, 24, 0, 4)
out(4, pix, 24, 32, 1)
out(5, pix, 32, 40, 0)
# output bitmap tables
for c in range(0,6):
#print "\talign $100"
print "PFBitmap%d" % c
#print "\thex 00"
s = '\thex '
for i in range(0,height):
s += '%02x' % output[c][height-i-1]
if i % 16 == 15:
print s
s = '\thex '
if len(s)>5:
print s

View File

@ -1,118 +0,0 @@
#include <string.h>
#include <stdio.h>
typedef unsigned char byte;
typedef unsigned short word;
#define P(x,y) ((((x) & 0xF) << 4) | (((y) & 0xF) << 0))
#define FONT_UP 0xFE
#define FONT_LAST 0xFF
const byte vecfont[59][8] = {
/*' '*/{ FONT_LAST },
/*'!'*/{ P(4,0), P(3,2), P(5,2), P(4,0), FONT_UP, P(4,4), P(4,12), FONT_LAST },
/*'"'*/{ P(2,10), P(2,6), FONT_UP, P(6,10), P(6,6), FONT_LAST },
/*'#'*/{ P(0,4), P(8,4), P(6,2), P(6,10), P(8,8), P(0,8), P(2,10), P(2,2) },
/*'$'*/{ P(6,2), P(2,6), P(6,10), FONT_UP, P(4,12), P(4,0), FONT_LAST },
/*'%'*/{ P(0,0), P(8,12), FONT_UP, P(2,10), P(2,8), FONT_UP, P(6,4), P(6,2) },
/*'&'*/{ P(8,0), P(4,12), P(8,8), P(0,4), P(4,0), P(8,4), FONT_LAST },
/*'''*/{ P(0,12), P(8,0), FONT_LAST },
/*'('*/{ P(6,0), P(2,4), P(2,8), P(6,12), FONT_LAST },
/*')'*/{ P(2,0), P(6,4), P(6,8), P(2,12), FONT_LAST },
/*'*'*/{ P(0,0), P(4,12), P(8,0), P(0,8), P(8,8), P(0,0), FONT_LAST },
/*'+'*/{ P(1,6), P(7,6), FONT_UP, P(4,9), P(4,3), FONT_LAST },
/*','*/{ P(2,0), P(4,2), FONT_LAST },
/*'-'*/{ P(2,6), P(6,6), FONT_LAST },
/*'.'*/{ P(3,0), P(4,0), FONT_LAST },
/*'/'*/{ P(0,0), P(8,12), FONT_LAST },
/*'0'*/{ P(0,0), P(8,0), P(8,12), P(0,12), P(0,0), P(8,12), FONT_LAST },
/*'1'*/{ P(4,0), P(4,12), P(3,10), FONT_LAST },
/*'2'*/{ P(0,12), P(8,12), P(8,7), P(0,5), P(0,0), P(8,0), FONT_LAST },
/*'3'*/{ P(0,12), P(8,12), P(8,0), P(0,0), FONT_UP, P(0,6), P(8,6), FONT_LAST },
/*'4'*/{ P(0,12), P(0,6), P(8,6), FONT_UP, P(8,12), P(8,0), FONT_LAST },
/*'5'*/{ P(0,0), P(8,0), P(8,6), P(0,7), P(0,12), P(8,12), FONT_LAST },
/*'6'*/{ P(0,12), P(0,0), P(8,0), P(8,5), P(0,7), FONT_LAST },
/*'7'*/{ P(0,12), P(8,12), P(8,6), P(4,0), FONT_LAST },
/*'8'*/{ P(0,0), P(8,0), P(8,12), P(0,12), P(0,0), FONT_UP, P(0,6), P(8,6), },
/*'9'*/{ P(8,0), P(8,12), P(0,12), P(0,7), P(8,5), FONT_LAST },
/*':'*/{ P(4,9), P(4,7), FONT_UP, P(4,5), P(4,3), FONT_LAST },
/*';'*/{ P(4,9), P(4,7), FONT_UP, P(4,5), P(1,2), FONT_LAST },
/*'<'*/{ P(6,0), P(2,6), P(6,12), FONT_LAST },
/*'='*/{ P(1,4), P(7,4), FONT_UP, P(1,8), P(7,8), FONT_LAST },
/*'>'*/{ P(2,0), P(6,6), P(2,12), FONT_LAST },
/*'?'*/{ P(0,8), P(4,12), P(8,8), P(4,4), FONT_UP, P(4,1), P(4,0), FONT_LAST },
/*'@'*/{ P(8,4), P(4,0), P(0,4), P(0,8), P(4,12), P(8,8), P(4,4), P(3,6) },
/*'A'*/{ P(0,0), P(0,8), P(4,12), P(8,8), P(8,0), FONT_UP, P(0,4), P(8,4) },
/*'B'*/{ P(0,0), P(0,12), P(4,12), P(8,10), P(4,6), P(8,2), P(4,0), P(0,0) },
/*'C'*/{ P(8,0), P(0,0), P(0,12), P(8,12), FONT_LAST },
/*'D'*/{ P(0,0), P(0,12), P(4,12), P(8,8), P(8,4), P(4,0), P(0,0), FONT_LAST },
/*'E'*/{ P(8,0), P(0,0), P(0,12), P(8,12), FONT_UP, P(0,6), P(6,6), FONT_LAST },
/*'F'*/{ P(0,0), P(0,12), P(8,12), FONT_UP, P(0,6), P(6,6), FONT_LAST },
/*'G'*/{ P(6,6), P(8,4), P(8,0), P(0,0), P(0,12), P(8,12), FONT_LAST },
/*'H'*/{ P(0,0), P(0,12), FONT_UP, P(0,6), P(8,6), FONT_UP, P(8,12), P(8,0) },
/*'I'*/{ P(0,0), P(8,0), FONT_UP, P(4,0), P(4,12), FONT_UP, P(0,12), P(8,12) },
/*'J'*/{ P(0,4), P(4,0), P(8,0), P(8,12), FONT_LAST },
/*'K'*/{ P(0,0), P(0,12), FONT_UP, P(8,12), P(0,6), P(6,0), FONT_LAST },
/*'L'*/{ P(8,0), P(0,0), P(0,12), FONT_LAST },
/*'M'*/{ P(0,0), P(0,12), P(4,8), P(8,12), P(8,0), FONT_LAST },
/*'N'*/{ P(0,0), P(0,12), P(8,0), P(8,12), FONT_LAST },
/*'O'*/{ P(0,0), P(0,12), P(8,12), P(8,0), P(0,0), FONT_LAST },
/*'P'*/{ P(0,0), P(0,12), P(8,12), P(8,6), P(0,5), FONT_LAST },
/*'Q'*/{ P(0,0), P(0,12), P(8,12), P(8,4), P(0,0), FONT_UP, P(4,4), P(8,0) },
/*'R'*/{ P(0,0), P(0,12), P(8,12), P(8,6), P(0,5), FONT_UP, P(4,5), P(8,0) },
/*'S'*/{ P(0,2), P(2,0), P(8,0), P(8,5), P(0,7), P(0,12), P(6,12), P(8,10) },
/*'T'*/{ P(0,12), P(8,12), FONT_UP, P(4,12), P(4,0), FONT_LAST },
/*'U'*/{ P(0,12), P(0,2), P(4,0), P(8,2), P(8,12), FONT_LAST },
/*'V'*/{ P(0,12), P(4,0), P(8,12), FONT_LAST },
/*'W'*/{ P(0,12), P(2,0), P(4,4), P(6,0), P(8,12), FONT_LAST },
/*'X'*/{ P(0,0), P(8,12), FONT_UP, P(0,12), P(8,0), FONT_LAST },
/*'Y'*/{ P(0,12), P(4,6), P(8,12), FONT_UP, P(4,6), P(4,0), FONT_LAST },
/*'Z'*/{ P(0,12), P(8,12), P(0,0), P(8,0), FONT_UP, P(2,6), P(6,6), FONT_LAST },
};
////
static int frame = 0;
void draw_char(char ch) {
const byte* p = vecfont[ch - ' '];
byte bright = 0;
byte x = 0;
byte y = 0;
byte i;
if (ch < ' ' || ch > 'Z') return;
printf("const word VECFONT_%d[] = { ", ch);
for (i=0; i<8; i++) {
byte b = *p++;
if (b == FONT_LAST) break; // last move
else if (b == FONT_UP) bright = 0; // pen up
else {
byte x2 = b>>4;
byte y2 = b&15;
printf("_SVEC(%d,%d,%d), ", (char)(x2-x), (char)(y2-y), bright);
bright = 4;
x = x2;
y = y2;
}
}
printf("_SVEC(%d,%d,%d), _RTSL() };\n", (char)12-x, (char)-y, 0);
}
void main(void) {
for (int i=' '; i<='Z'; i++) {
draw_char(i);
}
printf("const word* const VECFONT[] = { ");
for (int i=' '; i<='Z'; i++) {
printf("VECFONT_%d,", i);
}
printf(" };\n");
}

View File

@ -1,18 +0,0 @@
all: cp437.vicdual.c c64.vicdual.c
clean:
rm -f cp437.vicdual.c c64.vicdual.c
# convert DOS CP437 font (256 chars)
cp437.vicdual.c: ../fonts/cp437-8x8.bdf
python ../parsebdf8.py $< -r -C > $@
# convert C64 font (256 chars, some unused)
c64.vicdual.c: ../fonts/c64.bdf
python ../parsebdf8.py $< -r -C > $@
%.h:
cat $* | hexdump -v -e '"\n" 128/1 "0x%02x,"'

View File

@ -1,44 +0,0 @@
#!/usr/bin/python
import sys, zipfile
OUTFILE = 'carnival.zip'
ROMS = [
( "epr-651.u33", 0x0000, 0x0400 ),
( "epr-652.u32", 0x0400, 0x0400 ),
( "epr-653.u31", 0x0800, 0x0400 ),
( "epr-654.u30", 0x0c00, 0x0400 ),
( "epr-655.u29", 0x1000, 0x0400 ),
( "epr-656.u28", 0x1400, 0x0400 ),
( "epr-657.u27", 0x1800, 0x0400 ),
( "epr-658.u26", 0x1c00, 0x0400 ),
( "epr-659.u8", 0x2000, 0x0400 ),
( "epr-660.u7", 0x2400, 0x0400 ),
( "epr-661.u6", 0x2800, 0x0400 ),
( "epr-662.u5", 0x2c00, 0x0400 ),
( "epr-663.u4", 0x3000, 0x0400 ),
( "epr-664.u3", 0x3400, 0x0400 ),
( "epr-665.u2", 0x3800, 0x0400 ),
( "epr-666.u1", 0x3c00, 0x0400 ),
( "316-633", 0x4000, 0x0020 ),
( "epr-412", 0x4040, 0x0400 ),
( "316-0206.u14", 0x4020, 0x0020 )
]
fn = sys.argv[1]
with open(fn, 'rb') as f:
data = f.read()
print "Read %d bytes of %s" % (len(data), fn)
with zipfile.ZipFile(OUTFILE, 'w') as zipf:
for name,start,length in ROMS:
romdata = data[start:start+length]
if len(romdata) != length:
print "*** No data for %s (offset 0x%x)" % (name,start)
romdata = '\0' * length
zipf.writestr(name, romdata)
else:
zipf.writestr(name, romdata)

View File

@ -1,30 +0,0 @@
all: baddies.c badspacerobots.tga tom-thumb.c swave.c.rom.h
clean:
rm -f baddies.[ch] *.gif *.tga *.tga.png tom-thumb.c swave.c.rom.h
%.h: %
cat $* | hexdump -v -e '"\n" 128/1 "0x%02x,"' > $@
# convert PCX (or PNG) file to Williams C sprite
%.c: %.pcx
python3 ../pcx2will.py $< > $@
# convert PNG into RLE-encoded TGA bitmap
%.tga: %.png
convert $< -resize 192 $<.gif
convert $<.gif +dither -type palette -depth 4 -compress RLE -colors 8 -flip $@
convert $@ $@.png
# convert PNG to 15-color PCX
%.pcx: %.png
convert $< -format raw -type palette -compress none -colors 15 +dither $@
#%.4.pcx: %.png
# convert $< -format raw -type palette -compress none -colors 4 +dither $@
# convert BDF font file to definitions
%.c: ../fonts/%.bdf
python3 ../parsebdf4bit.py -s 33 -e 97 $< > $@

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.