|
|
|
|
@ -2,44 +2,32 @@
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
|
#define PAD 32 |
|
|
|
|
#define ZOOM 4 |
|
|
|
|
#define color1 0x000000 |
|
|
|
|
#define color2 0x72DEC2 |
|
|
|
|
#define color3 0xFFFFFF |
|
|
|
|
#define color4 0x333333 |
|
|
|
|
|
|
|
|
|
typedef struct Point { |
|
|
|
|
int x; |
|
|
|
|
int y; |
|
|
|
|
} Point; |
|
|
|
|
|
|
|
|
|
typedef struct Size { |
|
|
|
|
int w; |
|
|
|
|
int h; |
|
|
|
|
} Size; |
|
|
|
|
|
|
|
|
|
typedef struct Brush { |
|
|
|
|
int mode; |
|
|
|
|
int size; |
|
|
|
|
int erase; |
|
|
|
|
int color; |
|
|
|
|
int down; |
|
|
|
|
int button; |
|
|
|
|
Point pos; |
|
|
|
|
Point prev; |
|
|
|
|
} Brush; |
|
|
|
|
|
|
|
|
|
/* TODO: Remove globals, set as arg */ |
|
|
|
|
|
|
|
|
|
static int SCREEN_WIDTH = 512 + PAD * 2; |
|
|
|
|
static int SCREEN_HEIGHT = 512 + PAD * 2; |
|
|
|
|
static int FPS = 30; |
|
|
|
|
|
|
|
|
|
unsigned char buffer[1024 * 4]; |
|
|
|
|
int ZOOM = 4; |
|
|
|
|
int clr = 0; |
|
|
|
|
|
|
|
|
|
uint32_t* pixels; |
|
|
|
|
|
|
|
|
|
unsigned char buffer[4096]; |
|
|
|
|
int colors[] = {color1, color2, color3, color4}; |
|
|
|
|
int WIDTH = 128 * ZOOM + PAD * 2; |
|
|
|
|
int HEIGHT = 128 * ZOOM + PAD * 2; |
|
|
|
|
int FPS = 30; |
|
|
|
|
SDL_Window* gWindow = NULL; |
|
|
|
|
SDL_Renderer* gRenderer = NULL; |
|
|
|
|
SDL_Texture* gTexture = NULL; |
|
|
|
|
|
|
|
|
|
/* helpers */ |
|
|
|
|
uint32_t* pixels; |
|
|
|
|
|
|
|
|
|
Point* |
|
|
|
|
setpt(Point* p, int x, int y) |
|
|
|
|
@ -49,120 +37,97 @@ setpt(Point* p, int x, int y)
|
|
|
|
|
return p; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Point* |
|
|
|
|
divpt(Point* p, int v) |
|
|
|
|
{ |
|
|
|
|
p->x /= v; |
|
|
|
|
p->y /= v; |
|
|
|
|
return p; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Point* |
|
|
|
|
mulpt(Point* p, int v) |
|
|
|
|
{ |
|
|
|
|
p->x *= v; |
|
|
|
|
p->y *= v; |
|
|
|
|
return p; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Point* |
|
|
|
|
addpt(Point* p, int v) |
|
|
|
|
{ |
|
|
|
|
p->x += v; |
|
|
|
|
p->y += v; |
|
|
|
|
return p; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* noodle */ |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
pixel(uint32_t* dst, Point p, int c) |
|
|
|
|
{ |
|
|
|
|
int x, y; |
|
|
|
|
mulpt(&p, ZOOM); |
|
|
|
|
addpt(&p, PAD); |
|
|
|
|
for(x = 0; x < ZOOM; ++x) { |
|
|
|
|
for(y = 0; y < ZOOM; ++y) { |
|
|
|
|
dst[(p.y + y) * SCREEN_WIDTH + (p.x + x)] = c; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
p.x = (p.x * ZOOM) + PAD; |
|
|
|
|
p.y = (p.y * ZOOM) + PAD; |
|
|
|
|
for(x = 0; x < ZOOM; ++x) |
|
|
|
|
for(y = 0; y < ZOOM; ++y) |
|
|
|
|
dst[(p.y + y) * WIDTH + (p.x + x)] = c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
paint(uint32_t* dst, int id, int color) |
|
|
|
|
draw(uint32_t* dst, int id, int color) |
|
|
|
|
{ |
|
|
|
|
int ti = id / 64; |
|
|
|
|
int px = (ti / 256) * 128; |
|
|
|
|
int py = 0; |
|
|
|
|
int tx = (ti % 16) * 8; |
|
|
|
|
int ty = ((ti / 16) * 8) % 128; |
|
|
|
|
Point p; |
|
|
|
|
p.x = px + tx + (id % 8); |
|
|
|
|
p.y = py + ty + ((id % 64) / 8); |
|
|
|
|
if(color == 1) |
|
|
|
|
pixel(dst, p, 0x72DEC2); |
|
|
|
|
else if(color == 2) |
|
|
|
|
pixel(dst, p, 0xFFFFFF); |
|
|
|
|
else if(color == 3) |
|
|
|
|
pixel(dst, p, 0x333333); |
|
|
|
|
else |
|
|
|
|
pixel(dst, p, 0x000000); |
|
|
|
|
p.y = ty + ((id % 64) / 8); |
|
|
|
|
pixel(dst, p, colors[color]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
update(void) |
|
|
|
|
redraw(void) |
|
|
|
|
{ |
|
|
|
|
int b, i, j, id = 0, ch1, ch2, color; |
|
|
|
|
for(b = 0; b < 1024 * 4; b += 16) |
|
|
|
|
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); |
|
|
|
|
paint(pixels, id, color); |
|
|
|
|
draw(pixels, id, color); |
|
|
|
|
id++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
write(int tx, int ty, int px, int py) |
|
|
|
|
write(int tx, int ty, int px, int py, int color) |
|
|
|
|
{ |
|
|
|
|
int id = tx + ty * 16; |
|
|
|
|
int pid = px + py * 8; |
|
|
|
|
int row = id * 16 + py; |
|
|
|
|
|
|
|
|
|
if(clr == 0) { |
|
|
|
|
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(clr == 2) { |
|
|
|
|
} else if(color == 2) { |
|
|
|
|
buffer[row] |= 1UL << (7 - px); |
|
|
|
|
buffer[row + 8] &= ~(1UL << (7 - px)); |
|
|
|
|
} else if(clr == 1) { |
|
|
|
|
} else if(color == 1) { |
|
|
|
|
buffer[row] &= ~(1UL << (7 - px)); |
|
|
|
|
buffer[row + 8] |= 1UL << (7 - px); |
|
|
|
|
} else if(clr == 3) { |
|
|
|
|
} else if(color == 3) { |
|
|
|
|
buffer[row] |= 1UL << (7 - px); |
|
|
|
|
buffer[row + 8] |= 1UL << (7 - px); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
update(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
edit(Point* p) |
|
|
|
|
edit(Brush* b) |
|
|
|
|
{ |
|
|
|
|
int tx, ty, px, py; |
|
|
|
|
Point aligned; |
|
|
|
|
addpt(setpt(&aligned, p->x, p->y), -PAD); |
|
|
|
|
if(aligned.x < 0 || aligned.y < 0 || aligned.x > 8 * 16 * ZOOM || aligned.y > 8 * 16 * ZOOM) |
|
|
|
|
Point p1; |
|
|
|
|
setpt(&p1, b->pos.x - PAD, b->pos.y - PAD); |
|
|
|
|
if(p1.x < 0 || p1.y < 0 || p1.x > 8 * 16 * ZOOM || p1.y > 8 * 16 * ZOOM) |
|
|
|
|
return; |
|
|
|
|
write( |
|
|
|
|
p1.x / (8 * ZOOM), |
|
|
|
|
p1.y / (8 * ZOOM), |
|
|
|
|
(p1.x / ZOOM) % 8, |
|
|
|
|
(p1.y / ZOOM) % 8, |
|
|
|
|
b->color); |
|
|
|
|
redraw(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* convert screen to texture pos */ |
|
|
|
|
tx = aligned.x / (8 * ZOOM); |
|
|
|
|
ty = aligned.y / (8 * ZOOM); |
|
|
|
|
px = (aligned.x / ZOOM) % 8; |
|
|
|
|
py = (aligned.y / ZOOM) % 8; |
|
|
|
|
write(tx, ty, px, py); |
|
|
|
|
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 > 8 * 16 * ZOOM || p1.y > 8 * 16 * ZOOM) |
|
|
|
|
return; |
|
|
|
|
id = (p1.x / (8 * ZOOM)) + (p1.y / (8 * ZOOM)) * 16; |
|
|
|
|
for(i = 0; i < 8; ++i) { |
|
|
|
|
buffer[(id * 16) + i] = 0x00; |
|
|
|
|
buffer[(id * 16) + i + 8] = 0x00; |
|
|
|
|
} |
|
|
|
|
redraw(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void export(uint32_t* dst) |
|
|
|
|
@ -170,8 +135,6 @@ void export(uint32_t* dst)
|
|
|
|
|
/* TODO: chr file export */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* SDL */ |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
error(char* msg, const char* err) |
|
|
|
|
{ |
|
|
|
|
@ -179,52 +142,6 @@ error(char* msg, const char* err)
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
init_array(void) |
|
|
|
|
{ |
|
|
|
|
int i, j; |
|
|
|
|
pixels = (uint32_t*)malloc(SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(uint32_t)); |
|
|
|
|
|
|
|
|
|
if(pixels == NULL) |
|
|
|
|
return error("init_array", "could not allocate memory for pixels"); |
|
|
|
|
|
|
|
|
|
for(i = 0; i < SCREEN_HEIGHT; i++) |
|
|
|
|
for(j = 0; j < SCREEN_WIDTH; j++) |
|
|
|
|
pixels[i * SCREEN_WIDTH + j] = 0x000000; |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
init(void) |
|
|
|
|
{ |
|
|
|
|
if(SDL_Init(SDL_INIT_VIDEO) < 0) |
|
|
|
|
return error("init", SDL_GetError()); |
|
|
|
|
|
|
|
|
|
gWindow = SDL_CreateWindow("nasu6", SDL_WINDOWPOS_UNDEFINED, |
|
|
|
|
SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, |
|
|
|
|
SCREEN_HEIGHT, SDL_WINDOW_SHOWN); |
|
|
|
|
|
|
|
|
|
if(gWindow == NULL) |
|
|
|
|
return error("window", SDL_GetError()); |
|
|
|
|
|
|
|
|
|
gRenderer = SDL_CreateRenderer(gWindow, -1, 0); |
|
|
|
|
|
|
|
|
|
if(gRenderer == NULL) |
|
|
|
|
return error("renderer", SDL_GetError()); |
|
|
|
|
|
|
|
|
|
gTexture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_ARGB8888, |
|
|
|
|
SDL_TEXTUREACCESS_STATIC, SCREEN_WIDTH, |
|
|
|
|
SCREEN_HEIGHT); |
|
|
|
|
|
|
|
|
|
if(gTexture == NULL) |
|
|
|
|
return error("texture", SDL_GetError()); |
|
|
|
|
|
|
|
|
|
init_array(); |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
quit(void) |
|
|
|
|
{ |
|
|
|
|
@ -247,56 +164,41 @@ handle_mouse(SDL_Event* event, Brush* b)
|
|
|
|
|
if(event->button.button == SDL_BUTTON_LEFT) |
|
|
|
|
b->down = 0; |
|
|
|
|
if(event->button.button == SDL_BUTTON_RIGHT) |
|
|
|
|
b->erase = 0; |
|
|
|
|
setpt(&b->prev, 0, 0); |
|
|
|
|
erase(b); |
|
|
|
|
break; |
|
|
|
|
case SDL_MOUSEBUTTONDOWN: |
|
|
|
|
if(event->button.button == SDL_BUTTON_LEFT) |
|
|
|
|
b->down = 1; |
|
|
|
|
if(event->button.button == SDL_BUTTON_RIGHT) |
|
|
|
|
b->erase = 1; |
|
|
|
|
setpt(&b->prev, event->motion.x, event->motion.y); |
|
|
|
|
case SDL_MOUSEMOTION: |
|
|
|
|
if(b->down) { |
|
|
|
|
setpt(&b->pos, event->motion.x, event->motion.y); |
|
|
|
|
edit(&b->pos); |
|
|
|
|
setpt(&b->prev, b->pos.x, b->pos.y); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
addpt(&b->pos, -PAD); |
|
|
|
|
divpt(&b->pos, ZOOM); |
|
|
|
|
pixel(pixels, b->pos, 0xFFFFFF); |
|
|
|
|
setpt(&b->prev, b->pos.x, b->pos.y); |
|
|
|
|
*/ |
|
|
|
|
edit(b); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
handle_keypress(SDL_Event* event, Brush* b, Point* o) |
|
|
|
|
handle_keypress(SDL_Event* event, Brush* b) |
|
|
|
|
{ |
|
|
|
|
switch(event->key.keysym.sym) { |
|
|
|
|
case SDLK_ESCAPE: |
|
|
|
|
quit(); |
|
|
|
|
break; |
|
|
|
|
/* I/O */ |
|
|
|
|
case SDLK_e: |
|
|
|
|
export(pixels); |
|
|
|
|
break; |
|
|
|
|
/* Mode */ |
|
|
|
|
case SDLK_1: |
|
|
|
|
clr = 0; |
|
|
|
|
b->color = 0; |
|
|
|
|
break; |
|
|
|
|
case SDLK_2: |
|
|
|
|
clr = 1; |
|
|
|
|
b->color = 1; |
|
|
|
|
break; |
|
|
|
|
case SDLK_3: |
|
|
|
|
clr = 2; |
|
|
|
|
b->color = 2; |
|
|
|
|
break; |
|
|
|
|
case SDLK_4: |
|
|
|
|
clr = 3; |
|
|
|
|
b->color = 3; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -306,7 +208,40 @@ load(FILE* f)
|
|
|
|
|
{ |
|
|
|
|
if(!fread(buffer, sizeof(buffer), 1, f)) |
|
|
|
|
return error("Invalid size file", ""); |
|
|
|
|
update(); |
|
|
|
|
redraw(); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
init(void) |
|
|
|
|
{ |
|
|
|
|
int i, j; |
|
|
|
|
if(SDL_Init(SDL_INIT_VIDEO) < 0) |
|
|
|
|
return error("init", SDL_GetError()); |
|
|
|
|
gWindow = SDL_CreateWindow("nasu6", |
|
|
|
|
SDL_WINDOWPOS_UNDEFINED, |
|
|
|
|
SDL_WINDOWPOS_UNDEFINED, |
|
|
|
|
WIDTH, |
|
|
|
|
HEIGHT, |
|
|
|
|
SDL_WINDOW_SHOWN); |
|
|
|
|
if(gWindow == NULL) |
|
|
|
|
return error("window", SDL_GetError()); |
|
|
|
|
gRenderer = SDL_CreateRenderer(gWindow, -1, 0); |
|
|
|
|
if(gRenderer == NULL) |
|
|
|
|
return error("renderer", SDL_GetError()); |
|
|
|
|
gTexture = SDL_CreateTexture(gRenderer, |
|
|
|
|
SDL_PIXELFORMAT_ARGB8888, |
|
|
|
|
SDL_TEXTUREACCESS_STATIC, |
|
|
|
|
WIDTH, |
|
|
|
|
HEIGHT); |
|
|
|
|
if(gTexture == NULL) |
|
|
|
|
return error("texture", SDL_GetError()); |
|
|
|
|
pixels = (uint32_t*)malloc(WIDTH * HEIGHT * sizeof(uint32_t)); |
|
|
|
|
if(pixels == NULL) |
|
|
|
|
return error("pixels", "failed to allocate memory"); |
|
|
|
|
for(i = 0; i < HEIGHT; i++) |
|
|
|
|
for(j = 0; j < WIDTH; j++) |
|
|
|
|
pixels[i * WIDTH + j] = 0x000000; |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -315,11 +250,10 @@ main(int argc, char** argv)
|
|
|
|
|
{ |
|
|
|
|
int ticknext = 0; |
|
|
|
|
Brush brush; |
|
|
|
|
Point offset; |
|
|
|
|
FILE* f; |
|
|
|
|
|
|
|
|
|
if(!init()) |
|
|
|
|
return error("Could not initialize SDL", ""); |
|
|
|
|
return error("SDL", "failure"); |
|
|
|
|
|
|
|
|
|
if(argc < 2) |
|
|
|
|
return error("Missing input file", ""); |
|
|
|
|
@ -331,37 +265,30 @@ main(int argc, char** argv)
|
|
|
|
|
|
|
|
|
|
load(f); |
|
|
|
|
|
|
|
|
|
/* main game loop */ |
|
|
|
|
/* main loop */ |
|
|
|
|
|
|
|
|
|
while(1) { |
|
|
|
|
|
|
|
|
|
int tick = SDL_GetTicks(); |
|
|
|
|
SDL_Event event; |
|
|
|
|
|
|
|
|
|
if(SDL_QUIT == event.type) |
|
|
|
|
exit(0); |
|
|
|
|
|
|
|
|
|
if(event.type == SDL_QUIT) |
|
|
|
|
quit(); |
|
|
|
|
if(tick < ticknext) |
|
|
|
|
SDL_Delay(ticknext - tick); |
|
|
|
|
|
|
|
|
|
ticknext = tick + (1000 / FPS); |
|
|
|
|
|
|
|
|
|
SDL_UpdateTexture(gTexture, NULL, pixels, SCREEN_WIDTH * sizeof(uint32_t)); |
|
|
|
|
|
|
|
|
|
SDL_UpdateTexture(gTexture, NULL, |
|
|
|
|
pixels, WIDTH * sizeof(uint32_t)); |
|
|
|
|
while(SDL_PollEvent(&event) != 0) { |
|
|
|
|
if(event.type == SDL_MOUSEBUTTONUP || |
|
|
|
|
event.type == SDL_MOUSEBUTTONDOWN || |
|
|
|
|
event.type == SDL_MOUSEMOTION) { |
|
|
|
|
handle_mouse(&event, &brush); |
|
|
|
|
} else if(event.type == SDL_KEYDOWN) { |
|
|
|
|
handle_keypress(&event, &brush, &offset); |
|
|
|
|
} |
|
|
|
|
} else if(event.type == SDL_KEYDOWN) |
|
|
|
|
handle_keypress(&event, &brush); |
|
|
|
|
} |
|
|
|
|
SDL_RenderClear(gRenderer); |
|
|
|
|
SDL_RenderCopy(gRenderer, gTexture, NULL, NULL); |
|
|
|
|
SDL_RenderPresent(gRenderer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
quit(); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|