@@ 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();