// THIS IS A WORK-IN-PROGRESS ... translated from GIMMS.imp, which was hosted on
// a big-endian machine, as opposed to the Intel system I'm testing the port on.
// The ported version doesn't look right, for several reasons, not just the
// obvious scaling/rounding issues.
// (Gimms-based) symbol drawing routines
#include <stdio.h>
#include <stdlib.h>
const float defaultscale=0.12;
//const float defaultscale=0.5; // using larger numbers and a smaller scale may be faster on the vectrex
#define byte char
#define half short
#define integer int
typedef struct charheader {
byte xbias,xmax,ybias,ymax;
half data;
} charheader;
typedef struct gimmsheader {
integer fontlength,gimm,number,dummy0,dummy1,dummy2,dummy3;
half scale;
byte xx,yy;
half start[128];
} gimmsheader;
const integer penup=1<<15,lastvector=1<<7;
static struct gimmsheader *header=NULL;
static struct charheader *ch;
static byte *chdata;
static integer xmax,ymax;
static float factor;
void readregion(FILE *f, int offset, int length, void *address) {
static int last_offset = 0;
char *put = (char *)address;
int i, c;
//DEBUG: fprintf(stderr, "Read %d byte block at offset %d\n", length, offset);
if (offset != last_offset) fseek(f, offset, SEEK_SET);
//DEBUG: fputc('[', stderr);
for (i = 0; i < length; i++) {
c = fgetc(f);
//DEBUG: if (c >= 32 && c < 127) fputc(c, stderr); else fputc('.', stderr);
*put++ = c; last_offset++;
}
//DEBUG: fputc(']', stderr);
//DEBUG: fputc('\n', stderr);
}
void lineabs(integer fromx, integer fromy, integer tox, integer toy) {
fprintf(stdout, "lineabs(%d,%d, %d,%d);\n", fromx, fromy, tox, toy);
}
void moveabs(integer tox, integer toy) {
fprintf(stdout, "moveabs(%d,%d);\n", tox, toy);
}
void linerel(integer tox, integer toy) {
fprintf(stdout, "linerel(%d,%d);\n", tox, toy);
}
int sexswap2(half x) {
return ((x>>8)&255) | ((x&255)<<8);
}
int sexswap4(integer x) {
return (sexswap2((x>>16)&65535)) | ((sexswap2(x&65535))<<16);
}
void setup(void);
void setscale(float r, float rawfactor) {
if (!header) setup();
factor = rawfactor*r;
}
void setup(void) {
FILE *filetoken;
integer filepos=0,i;
header = malloc((sizeof(*header)));
filetoken = fopen("GIMMS.BIN","rb");
if (filetoken == NULL) {
fprintf(stderr, "Cannot open GIMMS.BIN\n");
exit(1);
}
do {
readregion(filetoken,filepos,sizeof(*header),header);
header->fontlength = sexswap4(header->fontlength); /*header->gimm = sexswap4(header->gimm);*/ /*header->number = sexswap4(header->number);*/
header->scale = sexswap2(header->scale);
for (i = 0; i < 128; i++) header->start[i] = sexswap2(header->start[i]);
//DEBUG: fprintf(stderr, "font length = %d (%04x)\n", header->fontlength, header->fontlength);
filepos = filepos+header->fontlength;
if (header->gimm != (*(int *) (char[]) {'G', 'I', 'M', 'M'})) {fprintf(stderr, "GIMMS file corrupt"); exit(1);}
} while (header->number != (*(int *) (char[]) {'0', '0', '0', '5'}));
filepos = filepos-header->fontlength+sizeof(*header);
i = header->fontlength-sizeof(*header);
chdata = (byte *)malloc(i);
readregion(filetoken,filepos,i,chdata); fclose(filetoken);
xmax = 0; ymax = 0;
for (i = 0; i < 128; i++) {
if (header->start[i]==0) continue;
ch = (charheader *)(&chdata[header->start[i]-256]);
if (ch->xmax>xmax) xmax = ch->xmax;
if (ch->ymax>ymax) ymax = ch->ymax;
}
setscale(defaultscale, 511.0 / (float)ymax); // NOTE: using 511.0 gives results that sometimes differ by 1 unit from using 511.
}
void sizesymbol(integer i, integer *n, integer *s, integer *e, integer *w) {
integer xpos,ypos,x,y;
half *d;
if (!header) setup();
*n = 0; *s = 0; *e = 0; *w = 0;
if (header->start[i]==0) return;
ch = (charheader *)(&chdata[header->start[i]-256]); d = &ch->data; // d not used, may have had sex problem anyway
*w = (int)(ch->xbias*factor); *s = (int)(ch->ybias*factor);
*e = (int)(ch->xmax*factor)-*w; *n = (int)(ch->ymax*factor)-*s;
}
void drawsymbol(integer i, integer xbase, integer ybase) {
integer xpos,ypos,x,y;
half *d;
if (!header) setup();
if (header->start[i]==0) return;
ch = (charheader *)(&chdata[header->start[i]-256]);
d = &ch->data; *d = sexswap2(*d); // WATCH OUT FOR SEX OF *d
//DEBUG: fprintf(stderr, "xbias: %d xmax: %d ybias: %d ymax: %d data: %d\n", ch->xbias,ch->xmax,ch->ybias,ch->ymax, ch->data);
x = (int)(ch->xbias*factor); y = (int)(ch->ybias*factor);
xbase = xbase-x; ybase = ybase-y;
xpos = 0; ypos = 0;
for (;;) {
// fprintf(stderr, "*d = %d\n", *d);
x = (int)((((*d)>>8)&127)*factor);
y = (int)(((*d)&127)*factor);
#ifdef ABS_LINES
if ((*d)&penup) {
xpos = x; ypos = y;
} else {
lineabs(xpos+xbase,ypos+ybase,x+xbase,y+ybase); xpos = x; ypos = y;
}
#else
if ((*d)&penup) {
xpos = x; ypos = y;
moveabs(xbase+x,ybase+y);
} else { // xbase+xpos to xbase+x
linerel(x-xpos,y-ypos); xpos = x; ypos = y;
}
#endif
if ((*d)&lastvector) break;
d++; *d = sexswap2(*d); //???
}
}
int main(int argc, char **argv) {
int i;
for (i = 0; i < 162; i++) {
fprintf(stdout, "// GIMMS %d\n", i);
drawsymbol(i,0,0);
}
exit(0);
return 1;
}