// 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; }