Skip to content

Instantly share code, notes, and snippets.

@JettMonstersGoBoom
Created September 24, 2020 18:19
Show Gist options
  • Save JettMonstersGoBoom/06932170a8348d302fee5cf08e61318e to your computer and use it in GitHub Desktop.
Save JettMonstersGoBoom/06932170a8348d302fee5cf08e61318e to your computer and use it in GitHub Desktop.
// Windows
// gcc c6.c tigr\tigr.c -I tigr -lopengl32 -lgdi32 -Os -s -o c6.exe
// Linux
// gcc c6.c tigr\tigr.c -I tigr -lGLU -lGL -lX11 -Os -s -o c6.exe
// OSX
// gcc c6.c tigr\tigr.c -I tigr -framework OpenGL -framework Cocoa -Os -s -o c6.exe
// using Tigr
// from https://github.com/erkkah/tigr
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "tigr.h"
// NOTE Zoom is removed as it's not needed with Tigr
// PAD is reduced
#define PAD 8
#define color1 0x000000
#define color2 0x72DEC2
#define color3 0xFFFFFF
#define color4 0x444444
#define color0 0x111111
typedef struct Point {
int x;
int y;
} Point;
typedef struct Brush {
int color;
int down;
Point pos;
} Brush;
unsigned char buffer[4096];
int colors[] = {color1, color2, color3, color4, color0};
int WIDTH = 128 + PAD * 2;
int HEIGHT = 128 + PAD * 2;
int GUIDES = 1;
Tigr *screen;
uint32_t* pixels;
Point *setpt(Point* p, int x, int y)
{
p->x = x;
p->y = y;
return p;
}
void pixel(uint32_t* dst, Point p, int c)
{
int x, y;
p.x = (p.x) + PAD;
p.y = (p.y) + PAD;
dst[(p.y) * WIDTH + (p.x)] = c;
}
void draw(uint32_t* dst, int id, int color)
{
int ti = id / 64;
int px = (ti / 256) * 128;
int tx = (ti % 16) * 8;
int ty = ((ti / 16) * 8) % 128;
int odd = (ti + (ti / 16 + 2)) % 2 == 0;
Point p;
p.x = px + tx + (id % 8);
p.y = ty + ((id % 64) / 8);
pixel(dst, p, colors[GUIDES && odd && color == 0 ? 4 : color]);
}
void redraw(void)
{
int b, i, j, id = 0, ch1, ch2, color;
for(b = 0; b < 4096; b += 16)
{
for(i = 0; i < 8; i++)
{
for(j = 7; j >= 0; j--)
{
ch1 = buffer[b + i];
ch2 = buffer[b + i + 8];
color = ((ch1 >> j) & 0x1) + (((ch2 >> j) & 0x1) << 1);
draw(pixels, id, color);
id++;
}
}
}
}
void write(int tx, int ty, int px, int py, int color)
{
int id = tx + ty * 16;
int row = py + id * 16;
if(id > 255)
return;
if(color == 0) {
buffer[row] &= ~(1UL << (7 - px));
buffer[row + 8] &= ~(1UL << (7 - px));
} else if(color == 2) {
buffer[row] |= 1UL << (7 - px);
buffer[row + 8] &= ~(1UL << (7 - px));
} else if(color == 1) {
buffer[row] &= ~(1UL << (7 - px));
buffer[row + 8] |= 1UL << (7 - px);
} else if(color == 3) {
buffer[row] |= 1UL << (7 - px);
buffer[row + 8] |= 1UL << (7 - px);
}
}
void edit(Brush* b)
{
Point p1;
setpt(&p1, b->pos.x - PAD, b->pos.y - PAD);
if(p1.x < 0 || p1.y < 0 || p1.x > 128 || p1.y > 128 )
return;
write(
p1.x / (8),
p1.y / (8),
(p1.x) % 8,
(p1.y) % 8,
b->color);
redraw();
}
void erase(Brush* b)
{
int i, id;
Point p1;
setpt(&p1, b->pos.x - PAD, b->pos.y - PAD);
if(p1.x < 0 || p1.y < 0 || p1.x > 128 || p1.y > 128)
return;
id = (p1.x / (8)) + (p1.y / (8)) * 16;
for(i = 0; i < 8; ++i) {
buffer[(id * 16) + i] = 0x00;
buffer[(id * 16) + i + 8] = 0x00;
}
redraw();
}
int error(char* msg, const char* err)
{
printf("Error %s: %s\n", msg, err);
return 0;
}
void create(void)
{
int i;
for(i = 0; i < 4096; ++i)
buffer[i] = 0x00;
redraw();
}
void save(void)
{
FILE* f = fopen("output.chr", "wb");
if(!fwrite(buffer, sizeof(buffer), 1, f))
error("Save", "Invalid output file");
fclose(f);
}
void load(char* path)
{
FILE* f = fopen(path, "rb");
if(f == NULL)
error("Load", "Invalid input file");
if(!fread(buffer, sizeof(buffer), 1, f))
error("Load", "Invalid file size");
fclose(f);
redraw();
}
void quit(void)
{
tigrFree(screen);
exit(0);
}
void domouse(void* event, Brush* b)
{
static int last_buttons = 0x0000;
int input_buttons,x,y;
tigrMouse(screen,&x,&y,&input_buttons);
// left released
if (((input_buttons&1)==0) && ((last_buttons&1)!=0))
b->down = 0;
// left held or pressed
if ((input_buttons&1)==1)
b->down = 1;
// right released
if (((input_buttons&4)==0) && ((last_buttons&4)!=0))
{
setpt(&b->pos, x, y);
erase(b);
}
// left held or pressed
if ((input_buttons&1)==1)
b->down = 1;
if(b->down==1) {
setpt(&b->pos, x, y);
edit(b);
}
last_buttons = input_buttons;
}
void dokey(void* event, Brush* b)
{
if (tigrKeyDown(screen,'1'))
b->color = 0;
if (tigrKeyDown(screen,'2'))
b->color = 1;
if (tigrKeyDown(screen,'3'))
b->color = 2;
if (tigrKeyDown(screen,'4'))
b->color = 3;
if (tigrKeyDown(screen,'H'))
{
GUIDES = !GUIDES;
redraw();
}
}
int
init(void)
{
int i, j;
screen = tigrWindow(WIDTH, HEIGHT, "CHR66", TIGR_3X);
pixels = (uint32_t*)&screen->pix[0];
for(i = 0; i < HEIGHT; i++)
for(j = 0; j < WIDTH; j++)
pixels[i * WIDTH + j] = 0x000000;
return 1;
}
int
main(int argc, char** argv)
{
int ticknext = 0;
Brush brush;
brush.color = 1;
if(!init())
return error("TIGR", "failure");
/* IO */
if(argc > 1)
load(argv[1]);
else
create();
/* main loop */
while (!tigrClosed(screen) && !tigrKeyDown(screen, TK_ESCAPE))
{
tigrUpdate(screen);
domouse(NULL,&brush);
dokey(NULL,&brush);
}
quit();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment