Skip to content

Instantly share code, notes, and snippets.

@dwilliamson
Created June 8, 2019 21:01
Show Gist options
  • Save dwilliamson/ff5e59194f3986cd35b78eb1463e082a to your computer and use it in GitHub Desktop.
Save dwilliamson/ff5e59194f3986cd35b78eb1463e082a to your computer and use it in GitHub Desktop.
// polygen.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <conio.h>
#define CHAR_VALUE(c, x, y) (c[y] & (1 << (7 - x)))
#define CHAR_ASSIGN(c, x, y) (c[y] |= (1 << (7 - x)))
#define CLEAR_SCREEN { memset(tbuf, 0, 25 * 80 * 2); }
#define PUT_CHAR(x, y, c) (tbuf[(y * 160) + (x * 2)] = c)
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
#pragma pack(push,1 )
typedef struct
{
unsigned char x, y;
} Point2D;
typedef struct
{
Point2D pt[3];
} Triangle;
#pragma pack(pop)
typedef struct
{
byte pos_x, pos_y;
byte width, height;
} Box;
typedef struct
{
byte bitmap[8]; /* Image from ROM */
byte mask[8]; /* Which areas have been mapped */
Box box_list[40]; /* List of boxes */
dword box_ctr; /* Current number of boxes */
Triangle tri_list[40 * 3]; /* Glide type triangle list */
} CharModel;
byte *fbuf = (byte *)0xFFA6EL;
byte *tbuf = (byte *)0xB8000L;
void GetCharPattern(CharModel *cptr, byte value)
{
dword offset;
offset = (dword)value << 3;
memcpy(&cptr->bitmap[0], &fbuf[offset], 8);
}
void PrintCharInText(CharModel *cptr)
{
dword x, y;
printf("\n");
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
{
if (CHAR_VALUE(cptr->bitmap, x, y))
printf("*");
else
printf(" ");
}
printf(" ");
for (x = 0; x < 8; x++)
{
if (CHAR_VALUE(cptr->mask, x, y))
printf("*");
else
printf(" ");
}
printf("\n");
}
}
void AddBox(CharModel *cptr, Box *bptr)
{
memcpy(&cptr->box_list[cptr->box_ctr++], bptr, sizeof(Box));
}
void DrawBox(Box *bptr)
{
byte x, y;
for (y = 0; y < bptr->height; y++)
for (x = 0; x < bptr->width; x++)
PUT_CHAR((bptr->pos_x + x), (bptr->pos_y + y), '*');
}
void EvaluateBoxes(CharModel *cptr)
{
Box tbox;
dword x, y;
memset(&cptr->mask[0], 0, 8);
for (y = 0; y < 8; y++)
{
memset(&tbox, 0, sizeof(Box));
for (x = 0; x < 8; x++)
{
if (CHAR_VALUE(cptr->bitmap, x, y) && !CHAR_VALUE(cptr->mask, x, y))
{
tbox.pos_x = (byte)x;
tbox.pos_y = (byte)y;
tbox.width = 0;
tbox.height = 0;
/* Scan across the grid */
while (CHAR_VALUE(cptr->bitmap, (x + tbox.width), y) &&
!CHAR_VALUE(cptr->mask, (x + tbox.width), y))
{
if ((x + tbox.width) >= 7)
break;
tbox.width++;
}
/* If the width is substantial then this must definitely be
* a polygon so mask the area out and continue scanning down the grid
* to see if the box can be expanded further.
*/
if (tbox.width > 1)
{
dword tx;
byte flag = 1;
for (tx = x; tx < x + tbox.width; tx++)
CHAR_ASSIGN(cptr->mask, tx, y);
/* Do a sweep-scan down the grid for any rectangles */
while (flag)
{
tbox.height++;
/* Can't go any further than the bottom of the grid */
if ((y + tbox.height) >= 7) break;
/* Try not to intrude on already formed rectangles */
if (x > 0 && CHAR_VALUE(cptr->bitmap, (x - 1), (y + tbox.height)))
break;
/* Try not to intrude on already formed rectangles */
if ((x + tbox.width) < 7 && CHAR_VALUE(cptr->bitmap, (x + tbox.width + 1), (y + tbox.height)))
break;
/* Scan along the grid checking for any mis-matches */
for (tx = x; tx < x + tbox.width; tx++)
{
if (!CHAR_VALUE(cptr->bitmap, tx, (y + tbox.height)) ||
CHAR_VALUE(cptr->mask, tx, (y + tbox.height)))
{
flag = 0;
break;
}
}
/* Now fill in the mask for this row */
if (flag)
for (tx = x; tx < x + tbox.width; tx++)
CHAR_ASSIGN(cptr->mask, tx, (y + tbox.height));
}
AddBox(cptr, &tbox);
}
else
{
/* Do a singular scan down the grid for vertical lines */
while (CHAR_VALUE(cptr->bitmap, x, (y + tbox.height)) &&
!CHAR_VALUE(cptr->mask, x, (y + tbox.height)))
{
CHAR_ASSIGN(cptr->mask, x, (y + tbox.height));
tbox.height++;
/* Don't over-run the grid */
if ((y + tbox.height) == 7)
break;
}
/* This a simple vertical line so just add it straight away - it could
* even be a cell on it's own.
*/
AddBox(cptr, &tbox);
}
}
}
}
}
void Generate3DModel(CharModel *cptr)
{
dword x;
Box *current_box;
Triangle *current_tri;
for (x = 0; x < cptr->box_ctr; x++)
{
current_box = &cptr->box_list[x];
current_tri = &cptr->tri_list[(x << 1) + 0];
current_tri->pt[0].x = current_box->pos_x;
current_tri->pt[0].y = current_box->pos_y;
current_tri->pt[1].x = current_box->pos_x + current_box->width;
current_tri->pt[1].y = current_box->pos_y;
current_tri->pt[2].x = current_box->pos_x + current_box->width;
current_tri->pt[2].y = current_box->pos_y + current_box->height;
current_tri = &cptr->tri_list[(x << 1) + 1];
current_tri->pt[0].x = current_box->pos_x;
current_tri->pt[0].y = current_box->pos_y;
current_tri->pt[1].x = current_box->pos_x + current_box->width;
current_tri->pt[1].y = current_box->pos_y + current_box->height;
current_tri->pt[2].x = current_box->pos_x;
current_tri->pt[2].y = current_box->pos_y + current_box->height;
}
}
void GenerateFontFile(byte *filename, byte low_range, byte high_range)
{
CharModel current_char;
byte x, triangles, y;
FILE *fp;
fp = fopen((const char *)filename, "wb");
fwrite(&low_range, 1, sizeof(byte), fp);
fwrite(&high_range, 1, sizeof(byte), fp);
for (x = low_range; x < high_range; x++)
{
memset(&current_char, 0, sizeof(CharModel));
GetCharPattern(&current_char, x);
EvaluateBoxes(&current_char);
PrintCharInText(&current_char);
Generate3DModel(&current_char);
triangles = (byte)(current_char.box_ctr * 2);
fwrite(&triangles, 1, sizeof(byte), fp);
for (y = 0; y < triangles; y++)
{
fputc(current_char.tri_list[y].pt[0].x, fp);
fputc(current_char.tri_list[y].pt[0].y, fp);
fputc(current_char.tri_list[y].pt[1].x, fp);
fputc(current_char.tri_list[y].pt[1].y, fp);
fputc(current_char.tri_list[y].pt[2].x, fp);
fputc(current_char.tri_list[y].pt[2].y, fp);
}
}
fclose(fp);
}
int main(int argc, char* argv[])
{
GenerateFontFile((byte *)"c:\\lucky.fnt", 0, 128);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment