1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
#!/usr/bin/env bash
# This really is a bash script. It also seems to work in zsh, but not
# ksh or dash. This is not a bug.
SELF="$( basename $0 )"
help() {
cat <<EOF
$SELF - Quick & dirty image converter for Atari 8-bit computers,
using ImageMagick.
Written by B. Watson (yalhcru@gmail.com), released under the
WTFPL. See http://www.wtfpl.net/txt/copying/ for details.
Usage: $SELF [options] [inputfile] [outputfile]
Options:
-g <mode> Graphics mode for outputfile (8, 9, or 15, default 9)
-f <color> Color register value for GR.8 foreground (default 0x0c)
-b <color> Color register value for GR.8 background (default 0x00)
-x Create standalone executable with loader and viewer
-X Create executable with loader only as an init segment
-a <addr> Create binary load data file, load image at <addr>
-l <addr> Load address for -x/-X loader (default 0x0400). Give
address in either decimal or hex with 0x prefix.
-d Dither. May improve results, or ruin them (YMMV). Doesn't
actually seem to have any visible effect.
-r <byte> For use with -x/-X: set RAMTOP. Default 192 (>=48K Atari
with no cartridge or BASIC). Use 160 if BASIC will be enabled,
or 64 for unexpanded 400 or 600XL, etc.
To write to standard output, use - as the outputfile. Reading from
standard input is not supported.
The image is scaled to fit in the desired graphics mode (with aspect
ratio preserved) and converted to greyscale: 4 bits for -g 9, 2 bits
for -g 15, and 1 bit (true monochrome) for -g 8.
With -g 15, the loader will set the color registers to \$00 \$04 \$08
\$0C. For raw images, you'll want to set them in whatever code you write
that uses the raw file.
Output file format depends on options given:
- With no -a/-x/-X options, the output is a raw screen memory image.
With -g 8 or 9, this is the same as an Atari .GR8 or .GR9 file. With
-g 15, it's similar to a Koala .pic file, except the color registers
aren't saved.
- With -a, the output is an Atari binary load file that loads the
image data at the given address, but includes no executable code. By
itself, this isn't very useful, but it could be used as part of a
multi-segment executable, or with the BLOAD command in Turbo BASIC.
- With -x, the output is a standalone executable that loads and displays
the image in the given graphics mode, then waits for the user to press
a key, then exits to DOS.
- With -X, the output is a binary load file that displays the image, but
doesn't include the "wait for keypress" code. This would be useful as
part of a multi-segment executable.
EOF
}
#-n BROKEN! Narrow GTIA mode (256x192 for GR.8, 128x192 for GR.15)
die() {
echo "$SELF: $@" 1>&2
exit 1
}
printbyte() {
printf -v tmpbyte "%02x" "$1"
LANG=C echo -n -e "\x$tmpbyte"
}
printword() {
printbyte $(( $1 % 256 ))
printbyte $(( $1 / 256 ))
}
printbytes() {
for i in "$@"; do printbyte 0x$i; done
}
GRMODE=9
DITHER="+dither"
RAMTOP=192
LOADERADDR=1024
SDMCTL=0x22
if [ "$#" = "0" ]; then
help
exit 0
fi
while [ "$1" != "" ]; do
case "$1" in
"--help"|"-help"|"-h"|"-?") help ; exit 0 ;;
"-g") GRMODE="$2" ; shift ;;
"-f") FGCOLOR="$2" ; shift ;;
"-b") BGCOLOR="$2" ; shift ;;
"-x") LOADER=1; VIEWER=1 ;;
"-X") LOADER=1; VIEWER=0 ;;
"-a") IMGSTART="$2" ; shift ;;
"-l") LOADERADDR="$2" ; shift ;;
#"-n") NARROW=1; SDMCTL=0x21 ;;
"-n") die "narrow mode not yet supported" ;;
"-d") DITHER="" ;;
"-r") RAMTOP="$2" ; shift ;;
-?*) die "invalid option '$1'" ;;
*)
if [ "$INFILE" = "" ]; then
INFILE="$1"
elif [ "$OUTFILE" = "" ]; then
OUTFILE="$1"
else
die "extra junk on the command line: '$1'"
fi
;;
esac
shift
done
type -p convert > /dev/null && type -p composite > /dev/null || \
die "Can't find 'convert' and 'composite' in \$PATH. Install ImageMagick?"
[ "$INFILE" = "" ] && die "No input filename given"
[ "$INFILE" = "-" ] && die "Reading stdin not supported"
[ "$OUTFILE" = "" ] && die "No output filename given (use - for stdout)"
# ASPECT pretends GR.8 pixels are square, GR.15 are 2x1 rectangles,
# and GR.9 are 4x1. This isn't entirely true...
case "$GRMODE" in
8) W=320; H=192; COLORS=2; DEPTH=1; ASPECT=100; FGCOLOR=${FGCOLOR:-0x0c}; BGCOLOR=${BGCOLOR:-0x00} ;;
15) W=160; H=192; COLORS=4; DEPTH=2; ASPECT=50 ;;
9) W=80; H=192; COLORS=16; DEPTH=4; ASPECT=25 ;;
*) die "invalid graphics mode '$GRMODE' (only 8 and 15 supported)" ;;
esac
#[ "$NARROW" = "1" ] && W=$(( $W / 40 * 32 ))
[ "$OUTFILE" = "" ] && OUTFILE="-"
[ "$OUTFILE" != "-" ] && exec > $OUTFILE
if [ "$LOADER" = "1" ]; then
if [ "$IMGSTART" != "" ]; then
die "-a option can't be combined with -x/-X"
fi
LOADEREND=$(( $LOADERADDR + 113 ))
IMGSTART=$(( $RAMTOP * 256 - 7856 ))
# xex header
printword 0xffff
printword $LOADERADDR
printword $LOADEREND
# data table (see loader.s)
printbyte $RAMTOP
printbyte $GRMODE
printbyte 0x04
printbyte ${FGCOLOR:-0x08}
printbyte ${BGCOLOR:-0x0c}
printbyte 0x00
printbyte 0x00
printbyte $SDMCTL
# code (see loader.s)
printbytes 78 a9 00 8d 0e d4 a9 60 85 d4 20 d4 00 ba ca bd 00 01
printbytes 38 e9 14 85 d4 bd 01 01 e9 00 85 d5 58 a9 40 8d
printbytes 0e d4 a0 00 b1 d4 85 6a a2 60 a9 0c 9d 42 03 20
printbytes 56 e4 a2 60 a9 0c 9d 4a 03 a0 01 b1 d4 9d 4b 03
printbytes a9 03 9d 42 03 a9 53 85 d6 a9 d6 9d 44 03 a9 00
printbytes 9d 45 03 20 56 e4 a0 02 b1 d4 99 c2 02 c8 c0 07
printbytes d0 f6 b1 d4 8d 2f 02 60
# INITAD segment
printbytes e2 02 e3 02
printword $(( LOADERADDR + 8 ))
# Narrow display needs 2nd DL LMS adjusted
## if [ "$NARROW" = 1 ]; then
## printword 0xffff
## printword $(( IMGSTART - 182 ))
## printword $(( IMGSTART - 181 ))
## printword $(( IMGSTART + 32 * 94 ))
## fi
fi
if [ "$IMGSTART" != "" ]; then
IMGBYTES=$(( $W * $H / 8 * $DEPTH ))
IMGEND=$(( $IMGSTART + $IMGBYTES - 1 ))
printword 0xffff
printword $IMGSTART
printword $IMGEND
fi
convert "$INFILE" $DITHER -scale ${ASPECT}%x100%\! -colorspace gray -scale ${W}x${H} -depth $DEPTH -colors $COLORS gif:- | \
composite gif:- -size ${W}x${H} -depth $DEPTH -colors $COLORS -gravity center xc:black gray:-
if [ "$VIEWER" = 1 ]; then
LOADEREND=$(( $LOADERADDR + 12 ))
# xex header
printword 0xffff
printword $LOADERADDR
printword $LOADEREND
# code (see viewer.s)
printbytes a9 ff 8d fc 02 ad fc 02 c9 ff f0 f9 60
# RUNAD segment
printbytes e0 02 e1 02
printword $LOADERADDR
fi
exit 0
# dump pixels' RGB values as text:
# convert in.png +dither -scale 320x192 -depth 2 -colors 4 -remap a8_ntsc_palette.png txt:- |sed 's,.*#\([0-9A-F]\{6\}\).*,\1,'|sort -u
# could someday be used to support color images in GR.15, or something like APAC.
|