|
|
|
|
@ -14,21 +14,27 @@ WITH REGARD TO THIS SOFTWARE.
|
|
|
|
|
|
|
|
|
|
#define HOR 32 |
|
|
|
|
#define VER 16 |
|
|
|
|
#define PAD 8 |
|
|
|
|
#define PAD 2 |
|
|
|
|
#define SZ (HOR * VER * 16) |
|
|
|
|
|
|
|
|
|
typedef unsigned char Uint8; |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
char name[256]; |
|
|
|
|
Uint8 data[SZ]; |
|
|
|
|
} Document; |
|
|
|
|
|
|
|
|
|
typedef struct Brush { |
|
|
|
|
int x, y, px, py; |
|
|
|
|
int mode, size, color; |
|
|
|
|
int down, erase; |
|
|
|
|
} Brush; |
|
|
|
|
|
|
|
|
|
int WIDTH = 8 * HOR + PAD * 2; |
|
|
|
|
int HEIGHT = 8 * (VER + 2) + PAD * 2; |
|
|
|
|
int WIDTH = 8 * HOR + 8 * PAD * 2; |
|
|
|
|
int HEIGHT = 8 * (VER + 2) + 8 * PAD * 2; |
|
|
|
|
int FPS = 30, GUIDES = 1, ZOOM = 2; |
|
|
|
|
|
|
|
|
|
Document doc; |
|
|
|
|
Brush brush; |
|
|
|
|
|
|
|
|
|
Uint32 theme[] = { |
|
|
|
|
@ -50,7 +56,6 @@ Uint8 icons[][8] = {
|
|
|
|
|
{0x00, 0x38, 0x44, 0x92, 0x28, 0x10, 0x00, 0x00} /* eye closed */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
Uint8 chrbuf[SZ]; |
|
|
|
|
SDL_Window *gWindow; |
|
|
|
|
SDL_Renderer *gRenderer; |
|
|
|
|
SDL_Texture *gTexture; |
|
|
|
|
@ -58,6 +63,16 @@ Uint32 *pixels;
|
|
|
|
|
|
|
|
|
|
/* helpers */ |
|
|
|
|
|
|
|
|
|
char * |
|
|
|
|
scpy(char *src, char *dst, int len) |
|
|
|
|
{ |
|
|
|
|
int i = 0; |
|
|
|
|
while((dst[i] = src[i]) && i < len) |
|
|
|
|
i++; |
|
|
|
|
dst[i + 1] = '\0'; |
|
|
|
|
return dst; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
distance(int ax, int ay, int bx, int by) |
|
|
|
|
{ |
|
|
|
|
@ -85,14 +100,6 @@ shex(char *s, int len)
|
|
|
|
|
|
|
|
|
|
/* chr */ |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
newchr(void) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
for(i = 0; i < SZ; ++i) |
|
|
|
|
chrbuf[i] = 0x00; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
rowchr(int x, int y) |
|
|
|
|
{ |
|
|
|
|
@ -105,8 +112,8 @@ getchr(int x, int y)
|
|
|
|
|
int ch1, ch2, r = rowchr(x, y); |
|
|
|
|
if(r < 0 || r > SZ - 8) |
|
|
|
|
return 0; |
|
|
|
|
ch1 = (chrbuf[r] >> (7 - x % 8)) & 1; |
|
|
|
|
ch2 = (chrbuf[r + 8] >> (7 - x % 8)) & 1; |
|
|
|
|
ch1 = (doc.data[r] >> (7 - x % 8)) & 1; |
|
|
|
|
ch2 = (doc.data[r + 8] >> (7 - x % 8)) & 1; |
|
|
|
|
if(ch1 && !ch2) |
|
|
|
|
return 1; |
|
|
|
|
if(!ch1 && ch2) |
|
|
|
|
@ -125,13 +132,13 @@ putchr(int x, int y, int color)
|
|
|
|
|
if(y < 0 || y >= VER * 8) |
|
|
|
|
return; |
|
|
|
|
if(color == 0 || color == 2) |
|
|
|
|
chrbuf[row] &= ~(1UL << (7 - col)); |
|
|
|
|
doc.data[row] &= ~(1UL << (7 - col)); |
|
|
|
|
else |
|
|
|
|
chrbuf[row] |= 1UL << (7 - col); |
|
|
|
|
doc.data[row] |= 1UL << (7 - col); |
|
|
|
|
if(color == 0 || color == 1) |
|
|
|
|
chrbuf[row + 8] &= ~(1UL << (7 - col)); |
|
|
|
|
doc.data[row + 8] &= ~(1UL << (7 - col)); |
|
|
|
|
else |
|
|
|
|
chrbuf[row + 8] |= 1UL << (7 - col); |
|
|
|
|
doc.data[row + 8] |= 1UL << (7 - col); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
@ -216,7 +223,7 @@ void
|
|
|
|
|
putpixel(Uint32 *dst, int x, int y, int color) |
|
|
|
|
{ |
|
|
|
|
if(x >= 0 && x < WIDTH - 8 && y >= 0 && y < HEIGHT - 8) |
|
|
|
|
dst[(y + PAD) * WIDTH + (x + PAD)] = theme[color]; |
|
|
|
|
dst[(y + PAD * 8) * WIDTH + (x + PAD * 8)] = theme[color]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
@ -227,8 +234,8 @@ drawchr(Uint32 *dst, int x, int y, int id)
|
|
|
|
|
for(h = 0; h < 8; h++) { |
|
|
|
|
int px = (x * 8) + (8 - h); |
|
|
|
|
int py = (y * 8) + v; |
|
|
|
|
int ch1 = chrbuf[offset + v]; |
|
|
|
|
int ch2 = chrbuf[offset + v + 8]; |
|
|
|
|
int ch1 = doc.data[offset + v]; |
|
|
|
|
int ch2 = doc.data[offset + v + 8]; |
|
|
|
|
int clr = ((ch1 >> h) & 0x1) + (((ch2 >> h) & 0x1) << 1); |
|
|
|
|
int guides = GUIDES && !clr && (x + y) % 2; |
|
|
|
|
putpixel(dst, px, py, guides ? 4 : clr); |
|
|
|
|
@ -236,13 +243,13 @@ drawchr(Uint32 *dst, int x, int y, int id)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
drawicon(Uint32 *dst, int x, int y, Uint8 *icon, int color) |
|
|
|
|
drawicon(Uint32 *dst, int x, int y, Uint8 *icon, int fg, int bg) |
|
|
|
|
{ |
|
|
|
|
int v, h; |
|
|
|
|
for(v = 0; v < 8; v++) |
|
|
|
|
for(h = 0; h < 8; h++) { |
|
|
|
|
int c = (icon[v] >> (8 - h)) & 0x1; |
|
|
|
|
putpixel(dst, x + h, y + v, c ? color : 0); |
|
|
|
|
int clr = (icon[v] >> (7 - h)) & 0x1; |
|
|
|
|
putpixel(dst, x + h, y + v, clr == 1 ? fg : bg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -250,16 +257,15 @@ void
|
|
|
|
|
drawui(Uint32 *dst) |
|
|
|
|
{ |
|
|
|
|
int bottom = VER * 8 + 8; |
|
|
|
|
drawicon(dst, 0, bottom, brush.color == 1 ? icons[1] : icons[0], 1); |
|
|
|
|
drawicon(dst, 8, bottom, brush.color == 2 ? icons[1] : icons[0], 2); |
|
|
|
|
drawicon(dst, 16, bottom, brush.color == 3 ? icons[1] : icons[0], 3); |
|
|
|
|
drawicon(dst, 4 * 8, bottom, icons[2], brush.mode == 0 ? 1 : 2); |
|
|
|
|
drawicon(dst, 5 * 8, bottom, icons[3], brush.mode == 1 ? 1 : 2); |
|
|
|
|
drawicon(dst, 6 * 8, bottom, icons[4], brush.mode == 2 ? 1 : 2); |
|
|
|
|
drawicon(dst, 7 * 8, bottom, icons[5], brush.mode == 3 ? 1 : 2); |
|
|
|
|
drawicon(dst, 8 * 8, bottom, icons[6], brush.mode == 4 ? 1 : 2); |
|
|
|
|
|
|
|
|
|
drawicon(dst, 10 * 8, bottom, icons[GUIDES ? 8 : 7], GUIDES ? 1 : 2); |
|
|
|
|
drawicon(dst, 0, bottom, brush.color == 1 ? icons[1] : icons[0], 1, 0); |
|
|
|
|
drawicon(dst, 8, bottom, brush.color == 2 ? icons[1] : icons[0], 2, 0); |
|
|
|
|
drawicon(dst, 16, bottom, brush.color == 3 ? icons[1] : icons[0], 3, 0); |
|
|
|
|
drawicon(dst, 4 * 8, bottom, icons[2], brush.mode == 0 ? 1 : 2, 0); |
|
|
|
|
drawicon(dst, 5 * 8, bottom, icons[3], brush.mode == 1 ? 1 : 2, 0); |
|
|
|
|
drawicon(dst, 6 * 8, bottom, icons[4], brush.mode == 2 ? 1 : 2, 0); |
|
|
|
|
drawicon(dst, 7 * 8, bottom, icons[5], brush.mode == 3 ? 1 : 2, 0); |
|
|
|
|
drawicon(dst, 8 * 8, bottom, icons[6], brush.mode == 4 ? 1 : 2, 0); |
|
|
|
|
drawicon(dst, 10 * 8, bottom, icons[GUIDES ? 8 : 7], GUIDES ? 1 : 2, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
@ -330,21 +336,38 @@ setguides(int v)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
destroy(void) |
|
|
|
|
newchr(void) |
|
|
|
|
{ |
|
|
|
|
newchr(); |
|
|
|
|
int i; |
|
|
|
|
for(i = 0; i < SZ; ++i) |
|
|
|
|
doc.data[i] = 0x00; |
|
|
|
|
scpy("untitled.chr", doc.name, 256); |
|
|
|
|
printf("New: %s\n", doc.name); |
|
|
|
|
redraw(pixels); |
|
|
|
|
puts("Destroy"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
exportchr(void) |
|
|
|
|
savechr(void) |
|
|
|
|
{ |
|
|
|
|
FILE *f = fopen("nasu-export.chr", "wb"); |
|
|
|
|
if(!fwrite(chrbuf, sizeof(chrbuf), 1, f)) |
|
|
|
|
FILE *f = fopen(doc.name, "wb"); |
|
|
|
|
if(!fwrite(doc.data, sizeof(doc.data), 1, f)) |
|
|
|
|
return error("Export", "Failure"); |
|
|
|
|
fclose(f); |
|
|
|
|
puts("Export: nasu-export.chr"); |
|
|
|
|
printf("Save: %s\n", doc.name); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
openchr(char *name) |
|
|
|
|
{ |
|
|
|
|
FILE *f = fopen(name, "r"); |
|
|
|
|
if(!f) |
|
|
|
|
return error("Load", "Invalid input file"); |
|
|
|
|
if(!fread(doc.data, sizeof(doc.data), 1, f)) |
|
|
|
|
return error("Load", "Invalid input size"); |
|
|
|
|
scpy(name, doc.name, 256); |
|
|
|
|
fclose(f); |
|
|
|
|
printf("Load: %s\n", doc.name); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -364,18 +387,6 @@ renderbmp(void)
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
loadchr(FILE *f) |
|
|
|
|
{ |
|
|
|
|
if(!f) |
|
|
|
|
return error("Load", "Invalid input file"); |
|
|
|
|
if(!fread(chrbuf, sizeof(chrbuf), 1, f)) |
|
|
|
|
return error("Load", "Invalid input size"); |
|
|
|
|
puts("Load: Complete"); |
|
|
|
|
fclose(f); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
loadtheme(FILE *f) |
|
|
|
|
{ |
|
|
|
|
@ -434,6 +445,10 @@ domouse(SDL_Event *event)
|
|
|
|
|
brush.erase = 0; |
|
|
|
|
break; |
|
|
|
|
case SDL_MOUSEBUTTONDOWN: |
|
|
|
|
if(event->motion.y / ZOOM / 8 - PAD == VER + 1) { |
|
|
|
|
selectoption(event->motion.x / ZOOM / 8 - PAD); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if(event->button.button == SDL_BUTTON_LEFT) |
|
|
|
|
brush.down = 1; |
|
|
|
|
if(event->button.button == SDL_BUTTON_RIGHT) |
|
|
|
|
@ -441,16 +456,14 @@ domouse(SDL_Event *event)
|
|
|
|
|
if(event->button.button == SDL_BUTTON_MIDDLE) { |
|
|
|
|
brush.erase = 0; |
|
|
|
|
if(brush.px != 0 && brush.py != 0) { |
|
|
|
|
brush.x = (event->motion.x - (PAD * ZOOM)) / ZOOM; |
|
|
|
|
brush.y = (event->motion.y - (PAD * ZOOM)) / ZOOM; |
|
|
|
|
brush.x = (event->motion.x - (PAD * 8 * ZOOM)) / ZOOM; |
|
|
|
|
brush.y = (event->motion.y - (PAD * 8 * ZOOM)) / ZOOM; |
|
|
|
|
line(brush.px - 1, brush.py, brush.x, brush.y, brush.erase ? 0 : brush.color); |
|
|
|
|
redraw(pixels); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
brush.px = (event->motion.x - (PAD * ZOOM)) / ZOOM; |
|
|
|
|
brush.py = (event->motion.y - (PAD * ZOOM)) / ZOOM; |
|
|
|
|
if(event->motion.y / ZOOM / 8 == VER + 2) |
|
|
|
|
selectoption(event->motion.x / ZOOM / 8 - 1); |
|
|
|
|
brush.px = (event->motion.x - (PAD * 8 * ZOOM)) / ZOOM; |
|
|
|
|
brush.py = (event->motion.y - (PAD * 8 * ZOOM)) / ZOOM; |
|
|
|
|
if(brush.down && brush.mode == 0) { |
|
|
|
|
putchr(brush.px - 1, brush.py, brush.erase ? 0 : brush.color); |
|
|
|
|
redraw(pixels); |
|
|
|
|
@ -458,8 +471,8 @@ domouse(SDL_Event *event)
|
|
|
|
|
break; |
|
|
|
|
case SDL_MOUSEMOTION: |
|
|
|
|
if(brush.down) { |
|
|
|
|
brush.x = (event->motion.x - (PAD * ZOOM)) / ZOOM; |
|
|
|
|
brush.y = (event->motion.y - (PAD * ZOOM)) / ZOOM; |
|
|
|
|
brush.x = (event->motion.x - (PAD * 8 * ZOOM)) / ZOOM; |
|
|
|
|
brush.y = (event->motion.y - (PAD * 8 * ZOOM)) / ZOOM; |
|
|
|
|
if(!brush.mode) |
|
|
|
|
line(brush.px - 1, brush.py, brush.x - 1, brush.y, brush.erase ? 0 : brush.color); |
|
|
|
|
else |
|
|
|
|
@ -475,26 +488,45 @@ domouse(SDL_Event *event)
|
|
|
|
|
void |
|
|
|
|
dokey(SDL_Event *event) |
|
|
|
|
{ |
|
|
|
|
int shift = SDL_GetModState() & KMOD_LSHIFT || SDL_GetModState() & KMOD_RSHIFT; |
|
|
|
|
int ctrl = SDL_GetModState() & KMOD_LCTRL || SDL_GetModState() & KMOD_RCTRL; |
|
|
|
|
switch(event->key.keysym.sym) { |
|
|
|
|
case SDLK_EQUALS: |
|
|
|
|
case SDLK_PLUS: modzoom(1); break; |
|
|
|
|
case SDLK_PLUS: |
|
|
|
|
if(ctrl) |
|
|
|
|
modzoom(1); |
|
|
|
|
break; |
|
|
|
|
case SDLK_UNDERSCORE: |
|
|
|
|
case SDLK_MINUS: modzoom(-1); break; |
|
|
|
|
case SDLK_MINUS: |
|
|
|
|
if(ctrl) |
|
|
|
|
modzoom(-1); |
|
|
|
|
break; |
|
|
|
|
case SDLK_1: setcolor(&brush, 1); break; |
|
|
|
|
case SDLK_2: setcolor(&brush, 2); break; |
|
|
|
|
case SDLK_3: setcolor(&brush, 3); break; |
|
|
|
|
case SDLK_4: setcolor(&brush, 0); break; |
|
|
|
|
case SDLK_e: exportchr(); break; |
|
|
|
|
case SDLK_r: renderbmp(); break; |
|
|
|
|
case SDLK_a: setmode(&brush, 0); break; |
|
|
|
|
case SDLK_s: setmode(&brush, 1); break; |
|
|
|
|
case SDLK_s: |
|
|
|
|
if(ctrl && shift) |
|
|
|
|
renderbmp(); |
|
|
|
|
else if(ctrl) |
|
|
|
|
savechr(); |
|
|
|
|
else |
|
|
|
|
setmode(&brush, 1); |
|
|
|
|
break; |
|
|
|
|
case SDLK_d: setmode(&brush, 2); break; |
|
|
|
|
case SDLK_f: setmode(&brush, 3); break; |
|
|
|
|
case SDLK_g: setmode(&brush, 4); break; |
|
|
|
|
case SDLK_h: setguides(!GUIDES); break; |
|
|
|
|
case SDLK_h: |
|
|
|
|
if(ctrl) |
|
|
|
|
setguides(!GUIDES); |
|
|
|
|
break; |
|
|
|
|
case SDLK_z: modsize(&brush, -1); break; |
|
|
|
|
case SDLK_x: modsize(&brush, 1); break; |
|
|
|
|
case SDLK_n: destroy(); break; |
|
|
|
|
case SDLK_n: |
|
|
|
|
if(ctrl) |
|
|
|
|
newchr(); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -532,17 +564,13 @@ int
|
|
|
|
|
main(int argc, char **argv) |
|
|
|
|
{ |
|
|
|
|
int ticknext = 0; |
|
|
|
|
brush.erase = 0; |
|
|
|
|
brush.down = 0; |
|
|
|
|
brush.color = 1; |
|
|
|
|
brush.size = 10; |
|
|
|
|
brush.mode = 0; |
|
|
|
|
if(!init()) |
|
|
|
|
return error("Init", "Failure"); |
|
|
|
|
loadtheme(fopen("theme.svg", "r")); |
|
|
|
|
newchr(); |
|
|
|
|
if(argc > 1) |
|
|
|
|
loadchr(fopen(argv[1], "r")); |
|
|
|
|
if(argc > 1 && !openchr(argv[1])) |
|
|
|
|
newchr(); |
|
|
|
|
redraw(pixels); |
|
|
|
|
while(1) { |
|
|
|
|
int tick = SDL_GetTicks(); |
|
|
|
|
|