Browse Source

Misc standardization

main
neauoire 5 years ago
parent
commit
7a7d95e8c8
  1. 15
      README.md
  2. 176
      nasu.c

15
README.md

@ -22,22 +22,19 @@ To resume working on a tileset:
### Generics ### Generics
- `+` Zoom In - `ctrl+n` New
- `-` Zoom Out - `ctrl+s` Save(.chr)
- `ctrl+shift+s` Save(.bmp)
### IO - `ctrl+plus` Zoom In
- `ctrl+minus` Zoom Out
- `E` Export(nasu-export.chr) - `ctrl+H` Toggle Guides
- `R` Render(nasu-render.bmp)
### General ### General
- `1-4` Colors0-3 - `1-4` Colors0-3
- `ASDFG` Modes0-4 - `ASDFG` Modes0-4
- `H` Toggle Guides
- `Z` Decr. Brush Size - `Z` Decr. Brush Size
- `X` Incr. Brush Size - `X` Incr. Brush Size
- `N` Clear
### Paint ### Paint

176
nasu.c

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

Loading…
Cancel
Save