world's saddest console
authorJohn Tsiombikas <nuclear@member.fsf.org>
Fri, 20 Dec 2019 03:54:00 +0000 (05:54 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Fri, 20 Dec 2019 03:54:00 +0000 (05:54 +0200)
17 files changed:
.gitignore
GNUmakefile
Makefile.dj
cspr/README [new file with mode: 0644]
src/cfgopt.c
src/cfgopt.h
src/console.c [new file with mode: 0644]
src/console.h [new file with mode: 0644]
src/demo.c
src/demo.h
src/dos/keyb.h
src/dos/main.c
src/screen.c
src/screen.h
src/sdl/main.c
tools/csprite/src/main.c
tools/procdata [new file with mode: 0755]

index afb00f8..e5f03cc 100644 (file)
@@ -39,4 +39,4 @@ data
 *.dja
 *.DJA
 tools/csprite/csprite
-font.asm
+cspr/
index d0eec53..511b0ad 100644 (file)
@@ -3,7 +3,7 @@ obj = $(src:.c=.o) $(asmsrc:.asm=.o)
 dep = $(obj:.o=.d)
 bin = demo
 
-asmsrc += font.asm
+asmsrc += cspr/dbgfont.asm cspr/confont.asm
 
 inc = -I/usr/local/include -Isrc -Isrc/scr -Isrc/sdl -Ilibs -Ilibs/imago/src -Ilibs/mikmod/include
 warn = -pedantic -Wall -Wno-unused-variable -Wno-unused-function
@@ -18,6 +18,9 @@ else
        sdl_ldflags = `sdl-config --libs`
 endif
 
+.PHONY: all
+all: data $(bin)
+
 $(bin): $(obj) imago mikmod
        $(CC) -o $@ $(obj) $(LDFLAGS)
 
@@ -51,8 +54,6 @@ clean:
 cleandep:
        rm -f $(dep)
 
-tools/csprite/csprite:
-       $(MAKE) -C tools/csprite
-
-font.asm: data/legible.fnt tools/csprite/csprite
-       tools/csprite/csprite -n cs_font -s 8x16 -conv565 -nasm $< >$@
+.PHONY: data
+data:
+       @tools/procdata
index b5c42bb..af00af7 100644 (file)
@@ -4,7 +4,7 @@ obj = $(src:.c=.cof) $(asmsrc:.asm=.cof)
 dep = $(obj:.cof=.dep)
 bin = demo.exe
 
-asmsrc += font.asm
+asmsrc += cspr/dbgfont.asm cspr/confont.asm
 
 ifeq ($(findstring COMMAND.COM, $(SHELL)), COMMAND.COM)
        hostsys = dos
@@ -23,6 +23,11 @@ AR = $(TOOLPREFIX)ar
 CFLAGS = $(warn) -march=pentium $(dbg) $(opt) $(inc)
 LDFLAGS = libs/imago/imago.dja libs/anim/anim.dja libs/mikmod/dos/libmikmod.a
 
+ifneq ($(hostsys), dos)
+.PHONY: all
+all: data $(bin)
+endif
+
 $(bin): $(obj) imago anim mikmod
        $(CC) -o $@ -Wl,-Map=ld.map $(obj) $(LDFLAGS)
 
@@ -76,11 +81,8 @@ clean:
 
 cleandep:
        rm -f $(dep)
-endif
 
-
-tools/csprite/csprite:
-       $(MAKE) -C tools/csprite
-
-font.asm: data/legible.fnt tools/csprite/csprite
-       tools/csprite/csprite -n cs_font -s 8x16 -conv565 -nasm $< >$@
+.PHONY: data
+data:
+       @tools/procdata
+endif
diff --git a/cspr/README b/cspr/README
new file mode 100644 (file)
index 0000000..6218818
--- /dev/null
@@ -0,0 +1,3 @@
+This directory is for compile sprites generated by tools/csprite. The tool runs
+on UNIX/windows, not DOS. So this directory need to be populated by running
+tools/procdata or tools/procdata.bat, and copied over to any DOS dev-boxes.
index ef16167..8f3759b 100644 (file)
@@ -4,12 +4,25 @@
 #include <ctype.h>
 #include "cfgopt.h"
 
+#ifdef NDEBUG
+/* release build default options */
+struct options opt = {
+       0,      /* start_scr */
+       1,      /* music */
+       0,      /* sball */
+       1,      /* vsync */
+       0       /* dbginfo */
+};
+#else
+/* debug build default options */
 struct options opt = {
        0,      /* start_scr */
        0,      /* music */
        0,      /* sball */
-       1       /* vsync */
+       1,      /* vsync */
+       1       /* dbginfo */
 };
+#endif
 
 int parse_args(int argc, char **argv)
 {
@@ -30,6 +43,10 @@ int parse_args(int argc, char **argv)
                                opt.vsync = 1;
                        } else if(strcmp(argv[i], "-novsync") == 0) {
                                opt.vsync = 0;
+                       } else if(strcmp(argv[i], "-dbg") == 0) {
+                               opt.dbginfo = 1;
+                       } else if(strcmp(argv[i], "-nodbg") == 0) {
+                               opt.dbginfo = 0;
                        } else {
                                fprintf(stderr, "invalid option: %s\n", argv[i]);
                                return -1;
@@ -116,6 +133,8 @@ int load_config(const char *fname)
                        opt.sball = bool_value(value);
                } else if(strcmp(line, "vsync") == 0) {
                        opt.vsync = bool_value(value);
+               } else if(strcmp(line, "debug") == 0) {
+                       opt.dbginfo = bool_value(value);
                } else {
                        fprintf(stderr, "%s:%d invalid option: %s\n", fname, nline, line);
                        return -1;
index 57c41f6..0c302a6 100644 (file)
@@ -6,6 +6,7 @@ struct options {
        int music;
        int sball;
        int vsync;
+       int dbginfo;
 };
 
 extern struct options opt;
diff --git a/src/console.c b/src/console.c
new file mode 100644 (file)
index 0000000..f1afac2
--- /dev/null
@@ -0,0 +1,235 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "console.h"
+#include "demo.h"
+#include "screen.h"
+
+static int runcmd(void);
+static int cmd_list(const char *args);
+static int cmd_help(const char *args);
+
+#define CBUF_SIZE      64
+#define CBUF_MASK      (CBUF_SIZE - 1)
+
+#define HIST_SIZE      32
+#define SBUF_SIZE      4
+
+static char cbuf[CBUF_SIZE];
+static char inp[CBUF_SIZE + 1], *dptr;
+static int rd, wr;
+
+static char hist[HIST_SIZE][CBUF_SIZE + 1];
+static int hist_head, hist_tail;
+
+static char sbuf[SBUF_SIZE][CBUF_SIZE + 1];
+static int sbuf_head, sbuf_tail;
+static int sbuf_size;
+
+
+int con_init(void)
+{
+       wr = rd = 0;
+       hist_head = hist_tail = 0;
+       sbuf_head = sbuf_tail = 0;
+       sbuf_size = 0;
+       return 0;
+}
+
+void con_start(void)
+{
+       wr = rd = 0;
+}
+
+void con_stop(void)
+{
+}
+
+void con_draw(uint16_t *fb)
+{
+       int x, y, sidx, cidx;
+
+       /* print output buffer */
+       y = 1;
+       sidx = sbuf_head;
+       while(sidx != sbuf_tail) {
+               cs_cputs(fb, 1, y, sbuf[sidx]);
+               sidx = (sidx + 1) & (SBUF_SIZE - 1);
+               y += 8;
+       }
+
+       memset(fb + y++ * 320, 0xff, 640);
+
+       cs_confont(fb, 1, y, '>' - 32);
+       cidx = rd;
+       x = 10;
+       while(cidx != wr) {
+               cs_confont(fb, x, y, cbuf[cidx] - 32);
+               x += 6;
+               cidx = (cidx + 1) & CBUF_MASK;
+       }
+       memset(fb + (y + 8) * 320, 0xff, 640);
+}
+
+int con_input(int key)
+{
+       switch(key) {
+       case '\b':
+               if(wr != rd) {
+                       wr = (wr + CBUF_SIZE - 1) & CBUF_MASK;
+               }
+               break;
+
+       case '\n':
+       case '\r':
+               dptr = inp;
+               while(rd != wr) {
+                       *dptr++ = cbuf[rd];
+                       rd = (rd + 1) & CBUF_MASK;
+               }
+               *dptr = 0;
+               if(inp[0]) {
+                       /* add to history */
+                       memcpy(hist[hist_tail], inp, dptr - inp + 1);
+                       hist_tail = (hist_tail + 1) & (HIST_SIZE - 1);
+                       if(hist_tail == hist_head) {    /* ovf */
+                               hist_head = (hist_head + 1) & (HIST_SIZE - 1);
+                       }
+
+                       return runcmd();
+               }
+               break;
+
+       case KB_UP:
+               if(hist_head == hist_tail) break;
+               hist_tail = (hist_tail + HIST_SIZE - 1) & (HIST_SIZE - 1);
+               strcpy(inp, hist[hist_tail]);
+               break;
+
+       default:
+               if(key < 256 && isprint(key)) {
+                       cbuf[wr] = key;
+                       wr = (wr + 1) & CBUF_MASK;
+                       if(wr == rd) { /* overflow */
+                               rd = (rd + 1) & CBUF_MASK;
+                       }
+               }
+               break;
+       }
+
+       return 1;
+}
+
+void con_printf(const char *fmt, ...)
+{
+       int len;
+       va_list ap;
+
+       va_start(ap, fmt);
+       len = vsprintf(sbuf[sbuf_tail], fmt, ap);
+       sbuf[sbuf_tail][len] = 0;
+       va_end(ap);
+
+       sbuf_tail = (sbuf_tail + 1) & (SBUF_SIZE - 1);
+       if(sbuf_tail == sbuf_head) {    /* ovf */
+               sbuf_head = (sbuf_head + 1) & (SBUF_SIZE - 1);
+       }
+
+       if(sbuf_size < SBUF_SIZE) sbuf_size++;
+}
+
+static struct {
+       const char *name;
+       int (*func)(const char*);
+} cmd[] = {
+       {"ls", cmd_list},
+       {"help", cmd_help},
+       {"?", cmd_help},
+       {0, 0}
+};
+
+static int runcmd(void)
+{
+       int i, nscr;
+       char *endp, *args;
+
+       switch(inp[0]) {
+       case '/':
+               nscr = scr_num_screens();
+               for(i=0; i<nscr; i++) {
+                       if(strstr(scr_screen(i)->name, inp + 1)) {
+                               change_screen(i);
+                               return 0;
+                       }
+               }
+               con_printf("no such screen: %s\n", inp + 1);
+               break;
+
+       case '#':
+               i = strtol(inp + 1, &endp, 10);
+               if(endp == inp + 1) {
+                       con_printf("usage: #<screen number>\n");
+                       break;
+               }
+               nscr = scr_num_screens();
+               if(i < 0 || i >= nscr) {
+                       con_printf("no such screen: %d\n", i);
+                       break;
+               }
+               change_screen(i);
+               return 0;
+
+       default:
+               endp = inp;
+               while(*endp && isspace(*endp)) endp++;
+               while(*endp && !isspace(*endp)) endp++;
+
+               args = *endp ? endp + 1 : 0;
+               *endp = 0;
+
+               for(i=0; cmd[i].name; i++) {
+                       if(strcmp(inp, cmd[i].name) == 0) {
+                               cmd[i].func(args);
+                               return 1;
+                       }
+               }
+
+               con_printf("?%s\n", inp);
+       }
+
+       return 1;
+}
+
+static int cmd_list(const char *args)
+{
+       int i, nscr, len;
+       char buf[512], *ptr = buf;
+
+       nscr = scr_num_screens();
+       for(i=0; i<nscr; i++) {
+               char *sname = scr_screen(i)->name;
+               len = strlen(sname);
+
+               if(ptr - buf + len > 53) {
+                       *ptr = 0;
+                       con_printf("%s", buf);
+                       ptr = buf;
+               }
+
+               len = sprintf(ptr, "%s ", sname);
+               ptr += len;
+       }
+       if(ptr > buf) {
+               *ptr = 0;
+               con_printf("%s", buf);
+       }
+       return 0;
+}
+
+static int cmd_help(const char *args)
+{
+       con_printf("cmds: /, #, ls, help, ?\n");
+       return 0;
+}
diff --git a/src/console.h b/src/console.h
new file mode 100644 (file)
index 0000000..ed2c337
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef CONSOLE_H_
+#define CONSOLE_H_
+
+#include "inttypes.h"
+
+int con_init(void);
+void con_start(void);
+void con_stop(void);
+void con_draw(uint16_t *fb);
+int con_input(int key);
+
+void con_printf(const char *fmt, ...);
+
+#endif /* CONSOLE_H_ */
index e2b8155..8ad984c 100644 (file)
@@ -10,6 +10,7 @@
 #include "3dgfx.h"
 #include "music.h"
 #include "cfgopt.h"
+#include "console.h"
 #include "tinyfps.h"
 #include "util.h"
 
@@ -27,7 +28,7 @@ unsigned int mouse_bmask;
 float sball_matrix[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
 
 static unsigned long nframes;
-static int console_active;
+static int con_active;
 
 int demo_init(int argc, char **argv)
 {
@@ -44,6 +45,7 @@ int demo_init(int argc, char **argv)
                return -1;
        }
 
+       con_init();
        initFpsFonts();
 
        if(g3d_init() == -1) {
@@ -102,12 +104,25 @@ void demo_draw(void)
        scr_update();
        scr_draw();
 
-       draw_mouse_pointer(vmem);
-
        ++nframes;
 }
 
+/* called by swap_buffers just before the actual swap */
+void demo_post_draw(void *pixels)
+{
+       if(opt.dbginfo) {
+               drawFps(pixels);
+               if(dbg_curscr_name) {
+                       cs_dputs(pixels, dbg_curscr_name_pos, 240 - 16, dbg_curscr_name);
+               }
+       }
+
+       if(con_active) {
+               con_draw(pixels);
+       }
 
+       draw_mouse_pointer(pixels);
+}
 
 #define DEST(x, y)     dest[(y) * FB_WIDTH + (x)]
 void draw_mouse_pointer(uint16_t *fb)
@@ -164,37 +179,37 @@ void draw_mouse_pointer(uint16_t *fb)
        }
 }
 
-void cs_puts(void *fb, int x, int y, const char *str)
+void cs_puts_font(cs_font_func csfont, int sz, void *fb, int x, int y, const char *str)
 {
        while(*str) {
                int c = *str++;
 
                if(c > ' ' && c < 128) {
-                       cs_font(fb, x, y, c - ' ');
+                       csfont(fb, x, y, c - ' ');
                }
-               x += 9;
+               x += sz;
        }
 }
 
-static void change_screen(int idx)
+void change_screen(int idx)
 {
        printf("change screen %d\n", idx);
        scr_change(scr_screen(idx), 4000);
 }
 
-#define CBUF_SIZE      64
-#define CBUF_MASK      (CBUF_SIZE - 1)
 void demo_keyboard(int key, int press)
 {
-       static char cbuf[CBUF_SIZE];
-       static int rd, wr;
-       char inp[CBUF_SIZE + 1], *dptr;
-       int i, nscr;
+       int nscr;
 
        if(press) {
                switch(key) {
                case 27:
-                       demo_quit();
+                       if(con_active) {
+                               con_stop();
+                               con_active = 0;
+                       } else {
+                               demo_quit();
+                       }
                        return;
 
                case 127:
@@ -202,71 +217,34 @@ void demo_keyboard(int key, int press)
                        return;
 
                case '`':
-                       console_active = !console_active;
-                       if(console_active) {
-                               printf("> ");
-                               fflush(stdout);
+                       con_active = !con_active;
+                       if(con_active) {
+                               con_start();
                        } else {
-                               putchar('\n');
+                               con_stop();
                        }
                        return;
 
-               case '\b':
-                       if(console_active) {
-                               if(wr != rd) {
-                                       printf("\b \b");
-                                       fflush(stdout);
-                                       wr = (wr + CBUF_SIZE - 1) & CBUF_MASK;
-                               }
+               case '/':
+                       if(!con_active) {
+                               con_start();
+                               con_active = con_input('/');
                                return;
                        }
-                       break;
-
-               case '\n':
-               case '\r':
-                       if(console_active) {
-                               dptr = inp;
-                               while(rd != wr) {
-                                       *dptr++ = cbuf[rd];
-                                       rd = (rd + 1) & CBUF_MASK;
-                               }
-                               *dptr = 0;
-                               if(inp[0]) {
-                                       printf("\ntrying to match: %s\n", inp);
-                                       nscr = scr_num_screens();
-                                       for(i=0; i<nscr; i++) {
-                                               if(strstr(scr_screen(i)->name, inp)) {
-                                                       change_screen(i);
-                                                       break;
-                                               }
-                                       }
-                               }
-                               console_active = 0;
+
+               default:
+                       if(con_active) {
+                               con_active = con_input(key);
                                return;
                        }
-                       break;
 
-               default:
                        if(key >= '1' && key <= '9' && key <= '1' + scr_num_screens()) {
                                change_screen(key - '1');
+                               return;
                        } else if(key == '0' && scr_num_screens() >= 10) {
                                change_screen(9);
-                       }
-
-                       if(console_active) {
-                               if(key < 256 && isprint(key)) {
-                                       putchar(key);
-                                       fflush(stdout);
-
-                                       cbuf[wr] = key;
-                                       wr = (wr + 1) & CBUF_MASK;
-                                       if(wr == rd) { /* overflow */
-                                               rd = (rd + 1) & CBUF_MASK;
-                                       }
-                               }
                                return;
                        }
-                       break;
                }
 
                scr_keypress(key);
index a3cc66a..ff58caa 100644 (file)
@@ -17,12 +17,32 @@ enum {
        MOUSE_BN_MIDDLE         = 4
 };
 
+/* special keys */
+enum {
+       KB_ESC = 27,
+       KB_BACKSP = 127,
+
+       KB_NUM_0, KB_NUM_1, KB_NUM_2, KB_NUM_3, KB_NUM_4,
+       KB_NUM_5, KB_NUM_6, KB_NUM_7, KB_NUM_8, KB_NUM_9,
+       KB_NUM_DOT, KB_NUM_DIV, KB_NUM_MUL, KB_NUM_MINUS, KB_NUM_PLUS, KB_NUM_ENTER, KB_NUM_EQUALS,
+       KB_UP, KB_DOWN, KB_RIGHT, KB_LEFT,
+       KB_INSERT, KB_HOME, KB_END, KB_PGUP, KB_PGDN,
+       KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6,
+       KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12,
+       KB_F13, KB_F14, KB_F15,
+       KB_NUMLK, KB_CAPSLK, KB_SCRLK,
+       KB_RSHIFT, KB_LSHIFT, KB_RCTRL, KB_LCTRL, KB_RALT, KB_LALT,
+       KB_RMETA, KB_LMETA, KB_LSUPER, KB_RSUPER, KB_MODE, KB_COMPOSE,
+       KB_HELP, KB_PRINT, KB_SYSRQ, KB_BREAK
+};
+
 extern float sball_matrix[16];
 
 int demo_init(int argc, char **argv);
 void demo_cleanup(void);
 
 void demo_draw(void);
+void demo_post_draw(void *pixels);
 
 void demo_keyboard(int key, int press);
 
@@ -35,15 +55,22 @@ void set_palette(int idx, int r, int g, int b);
 /* if pixels is 0, it defaults to fb_pixels */
 void swap_buffers(void *pixels);
 
+void change_screen(int idx);
+
 /* call each frame to get 3D viewing spherical coordinates */
 void mouse_orbit_update(float *theta, float *phi, float *dist);
 
 void draw_mouse_pointer(uint16_t *fb);
 
 /* compiled sprites available */
-void cs_font(void *fb, int x, int y, int idx);
+typedef void (*cs_font_func)(void *, int, int, int);
+void cs_dbgfont(void *fb, int x, int y, int idx);
+void cs_confont(void *fb, int x, int y, int idx);
 
 /* helper to print text with cs_font */
-void cs_puts(void *fb, int x, int y, const char *str);
+void cs_puts_font(cs_font_func csfont, int sz, void *fb, int x, int y, const char *str);
+
+#define cs_dputs(fb, x, y, idx)        cs_puts_font(cs_dbgfont, 9, fb, x, y, idx)
+#define cs_cputs(fb, x, y, idx)        cs_puts_font(cs_confont, 6, fb, x, y, idx)
 
 #endif /* DEMO_H_ */
index 9be97db..537a679 100644 (file)
@@ -18,29 +18,13 @@ along with the program. If not, see <http://www.gnu.org/licenses/>
 #ifndef KEYB_H_
 #define KEYB_H_
 
+#include "demo.h"
+
 #define KB_ANY         (-1)
 #define KB_ALT         (-2)
 #define KB_CTRL                (-3)
 #define KB_SHIFT       (-4)
 
-/* special keys */
-enum {
-       KB_LALT, KB_RALT,
-       KB_LCTRL, KB_RCTRL,
-       KB_LSHIFT, KB_RSHIFT,
-       KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6,
-       KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12,
-       KB_CAPSLK, KB_NUMLK, KB_SCRLK, KB_SYSRQ,
-       KB_ESC = 27,
-       KB_INSERT, KB_DEL, KB_HOME, KB_END, KB_PGUP, KB_PGDN,
-       KB_LEFT, KB_RIGHT, KB_UP, KB_DOWN,
-       KB_NUM_DOT, KB_NUM_ENTER, KB_NUM_PLUS, KB_NUM_MINUS, KB_NUM_MUL, KB_NUM_DIV,
-       KB_NUM_0, KB_NUM_1, KB_NUM_2, KB_NUM_3, KB_NUM_4,
-       KB_NUM_5, KB_NUM_6, KB_NUM_7, KB_NUM_8, KB_NUM_9,
-       KB_BACKSP = 127
-};
-
-
 #ifdef __cplusplus
 extern "C" {
 #endif
index 70ea449..4dcca05 100644 (file)
@@ -124,11 +124,12 @@ void swap_buffers(void *pixels)
                pixels = fb_pixels;
        }
 
+       demo_post_draw(pixels);
+
        /* just memcpy to the front buffer */
        if(opt.vsync) {
                wait_vsync();
        }
-       drawFps(pixels);
        memcpy(vmem, pixels, fbsize);
 }
 
index 68a8c7f..362a15c 100644 (file)
@@ -5,6 +5,13 @@
 #include "screen.h"
 #include "demo.h"
 
+#define DBG_SCRCHG \
+       do { \
+               dbg_curscr_name = cur->name ? cur->name : "<unknown>"; \
+               dbg_curscr_name_len = strlen(dbg_curscr_name); \
+               dbg_curscr_name_pos = 320 - dbg_curscr_name_len * 9; \
+       } while(0)
+
 struct screen *tunnel_screen(void);
 struct screen *fract_screen(void);
 struct screen *grise_screen(void);
@@ -92,6 +99,8 @@ void scr_update(void)
                        prev = 0;
                        cur = next;
                        next = 0;
+
+                       DBG_SCRCHG;
                }
        }
 }
@@ -101,9 +110,6 @@ void scr_draw(void)
 {
        if(cur) {
                cur->draw();
-
-               /* print screen name */
-               cs_puts(fb_pixels, 0, 0, cur->name);
        }
 }
 
@@ -158,6 +164,8 @@ int scr_change(struct screen *s, long trans_time)
 
                cur = s;
                prev = 0;
+
+               DBG_SCRCHG;
        }
        return 0;
 }
index c2e4974..85a1f86 100644 (file)
@@ -15,6 +15,9 @@ struct screen {
        void (*keypress)(int key);
 };
 
+const char *dbg_curscr_name;
+int dbg_curscr_name_len, dbg_curscr_name_pos;
+
 int scr_init(void);
 void scr_shutdown(void);
 
index 6a52021..de27777 100644 (file)
@@ -16,6 +16,8 @@ static void toggle_fullscreen(void);
 static int handle_sball_event(sball_event *ev);
 static void recalc_sball_matrix(float *xform);
 
+static int sdlkey_to_demokey(int sdlkey);
+
 
 static int quit;
 static SDL_Surface *fbsurf;
@@ -91,7 +93,6 @@ int main(int argc, char **argv)
 
                time_msec = get_msec();
                demo_draw();
-               drawFps(fb_pixels);
 
                if(SDL_MUSTLOCK(fbsurf)) {
                        SDL_LockSurface(fbsurf);
@@ -140,6 +141,8 @@ void wait_vsync(void)
 
 void swap_buffers(void *pixels)
 {
+       demo_post_draw(pixels ? pixels : fb_pixels);
+
        /* do nothing, all pointers point to the same buffer */
        if(opt.vsync) {
                wait_vsync();
@@ -163,6 +166,8 @@ static int bnmask(int sdlbn)
 
 static void handle_event(SDL_Event *ev)
 {
+       int key;
+
        switch(ev->type) {
        case SDL_QUIT:
                quit = 1;
@@ -175,7 +180,8 @@ static void handle_event(SDL_Event *ev)
                        toggle_fullscreen();
                        break;
                }
-               demo_keyboard(ev->key.keysym.sym, ev->key.state == SDL_PRESSED ? 1 : 0);
+               key = sdlkey_to_demokey(ev->key.keysym.sym);
+               demo_keyboard(key, ev->key.state == SDL_PRESSED ? 1 : 0);
                break;
 
        case SDL_MOUSEMOTION:
@@ -252,10 +258,17 @@ static int handle_sball_event(sball_event *ev)
        return 0;
 }
 
-void recalc_sball_matrix(float *xform)
+static void recalc_sball_matrix(float *xform)
 {
        quat_to_mat(xform, rot);
        xform[12] = pos.x;
        xform[13] = pos.y;
        xform[14] = pos.z;
 }
+
+static int sdlkey_to_demokey(int sdlkey)
+{
+       if(sdlkey < 128) return sdlkey;
+       if(sdlkey < 256) return 0;
+       return sdlkey - 128;
+}
index 0192002..fab302b 100644 (file)
@@ -24,6 +24,8 @@ int fbpitch, fbwidth = 320;
 const char *name = "sprite";
 int asyntax = AS_GNU;
 int conv565;
+int padding;
+const char *wrop = "mov";
 
 int main(int argc, char **argv)
 {
@@ -46,6 +48,13 @@ int main(int argc, char **argv)
                                        return 1;
                                }
 
+                       } else if(strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-pad") == 0) {
+                               padding = strtol(argv[++i], &endp, 10);
+                               if(endp == argv[i] || padding < 0) {
+                                       fprintf(stderr, "%s must be followed by a positive number\n", argv[i - 1]);
+                                       return 1;
+                               }
+
                        } else if(strcmp(argv[i], "-coffset") == 0) {
                                cmap_offs = strtol(argv[++i], &endp, 10);
                                if(endp == argv[i] || cmap_offs < 0 || cmap_offs >= 256) {
@@ -84,6 +93,9 @@ int main(int argc, char **argv)
                        } else if(strcmp(argv[i], "-conv565") == 0) {
                                conv565 = 1;
 
+                       } else if(strcmp(argv[i], "-x") == 0 || strcmp(argv[i], "-xor") == 0) {
+                               wrop = "xor";
+
                        } else if(strcmp(argv[i], "-gas") == 0) {
                                asyntax = AS_GNU;
 
@@ -155,7 +167,7 @@ const char *prefixfmt[] = {
 
 int proc_sheet(const char *fname)
 {
-       int i, j, num_xtiles, num_ytiles, xsz, ysz, tidx;
+       int i, j, x, y, num_xtiles, num_ytiles, xsz, ysz, tidx;
        struct image img;
 
        if(load_image(&img, fname) == -1) {
@@ -182,11 +194,25 @@ int proc_sheet(const char *fname)
 
        if(tile_xsz <= 0) {
                num_xtiles = num_ytiles = 1;
-               xsz = rect.w;
-               ysz = rect.h;
+               xsz = rect.w - padding;
+               ysz = rect.h - padding;
        } else {
-               num_xtiles = rect.w / tile_xsz;
-               num_ytiles = rect.h / tile_ysz;
+               if(padding) {
+                       num_xtiles = num_ytiles = 0;
+                       i = 0;
+                       while(i < rect.w) {
+                               num_xtiles++;
+                               i += tile_xsz + padding;
+                       }
+                       i = 0;
+                       while(i < rect.h) {
+                               num_ytiles++;
+                               i += tile_ysz + padding;
+                       }
+               } else {
+                       num_xtiles = rect.w / tile_xsz;
+                       num_ytiles = rect.h / tile_ysz;
+               }
                xsz = tile_xsz;
                ysz = tile_ysz;
        }
@@ -202,11 +228,15 @@ int proc_sheet(const char *fname)
        putchar('\n');
 
        tidx = 0;
+       y = rect.y;
        for(i=0; i<num_ytiles; i++) {
+               x = rect.x;
                for(j=0; j<num_xtiles; j++) {
                        printf("tile%d:\n", tidx++);
-                       csprite(&img, rect.x + j * xsz, rect.y + i * ysz, xsz, ysz);
+                       csprite(&img, x, y, xsz, ysz);
+                       x += xsz + padding;
                }
+               y += ysz + padding;
        }
 
        free(img.pixels);
@@ -300,9 +330,9 @@ int csprite(struct image *img, int x, int y, int xsz, int ysz)
                        lenbytes = optr->len * pixsz;
                        for(j=0; j<lenbytes / 4; j++) {
                                if(asyntax == AS_GNU) {
-                                       printf("\tmovl $0x%x, %d(%%edx)\n", *(uint32_t*)pptr, j * 4);
+                                       printf("\t%sl $0x%x, %d(%%edx)\n", wrop, *(uint32_t*)pptr, j * 4);
                                } else {
-                                       printf("\tmov dword [edx + %d], 0x%x\n", j * 4, *(uint32_t*)pptr);
+                                       printf("\t%s dword [edx + %d], 0x%x\n", wrop, j * 4, *(uint32_t*)pptr);
                                }
                                pptr += 4;
                        }
@@ -310,24 +340,24 @@ int csprite(struct image *img, int x, int y, int xsz, int ysz)
                        switch(lenbytes % 4) {
                        case 3:
                                if(asyntax == AS_GNU) {
-                                       printf("\tmovb $0x%x, %d(%%edx)\n", (unsigned int)*pptr++, j++);
+                                       printf("\t%sb $0x%x, %d(%%edx)\n", wrop, (unsigned int)*pptr++, j++);
                                } else {
-                                       printf("\tmov byte [edx + %d], 0x%x\n", j++, (unsigned int)*pptr++);
+                                       printf("\t%s byte [edx + %d], 0x%x\n", wrop, j++, (unsigned int)*pptr++);
                                }
                        case 2:
                                if(asyntax == AS_GNU) {
-                                       printf("\tmovw $0x%x, %d(%%edx)\n", (unsigned int)*(uint16_t*)pptr, j);
+                                       printf("\t%sw $0x%x, %d(%%edx)\n", wrop, (unsigned int)*(uint16_t*)pptr, j);
                                } else {
-                                       printf("\tmov word [edx + %d], 0x%x\n", j, (unsigned int)*(uint16_t*)pptr);
+                                       printf("\t%s word [edx + %d], 0x%x\n", wrop, j, (unsigned int)*(uint16_t*)pptr);
                                }
                                pptr += 2;
                                j += 2;
                                break;
                        case 1:
                                if(asyntax == AS_GNU) {
-                                       printf("\tmovb $0x%x, %d(%%edx)\n", (unsigned int)*pptr++, j++);
+                                       printf("\t%sb $0x%x, %d(%%edx)\n", wrop, (unsigned int)*pptr++, j++);
                                } else {
-                                       printf("\tmov byte [edx + %d], 0x%x\n", j++, (unsigned int)*pptr++);
+                                       printf("\t%s byte [edx + %d], 0x%x\n", wrop, j++, (unsigned int)*pptr++);
                                }
                                break;
                        }
@@ -351,10 +381,12 @@ void print_usage(const char *argv0)
        printf("Options:\n");
        printf(" -s,-size <WxH>: tile size (default: whole image)\n");
        printf(" -r,-rect <WxH+X+Y>: use rectangle of the input image (default: whole image)\n");
+       printf(" -p,-pad <N>: how many pixels to skip between tiles in source image (default: 0)\n");
        printf(" -coffset <offs>: colormap offset [0, 255] (default: 0)\n");
        printf(" -fbpitch <pitch>: target framebuffer pitch (scanline size in bytes)\n");
        printf(" -k,-key <color>: color-key for transparency (default: 0)\n");
        printf(" -conv565: convert image to 16bpp 565 before processing\n");
+       printf(" -x,-xor: use XOR for writing pixels instead of MOV\n");
        printf(" -gas: output GNU assembler code (default)\n");
        printf(" -nasm: output NASM-compatible code\n");
        printf(" -h: print usage and exit\n");
diff --git a/tools/procdata b/tools/procdata
new file mode 100755 (executable)
index 0000000..3cef48a
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+[ -f ./procdata ] && cd ..
+if [ ! -f tools/procdata ]; then
+       echo 'run from the demo root directory' >&2
+       exit 1
+fi
+
+if [ ! -f tools/csprite/csprite ]; then
+       make -C tools/csprite || exit 1
+fi
+
+alias csprite=tools/csprite/csprite
+
+mkdir -p cspr
+if [ ! -f cspr/dbgfont.asm -o data/legible.fnt -nt cspr/dbgfont.asm ]; then
+       echo 'csprite: dbgfont'
+       csprite -n cs_dbgfont -s 8x16 -conv565 -nasm -xor data/legible.fnt >cspr/dbgfont.asm
+fi
+if [ ! -f cspr/confont.asm -o data/con.fnt -nt cspr/confont.asm ]; then
+       echo 'csprite: confont'
+       csprite -n cs_confont -s 6x7 -pad 1 -conv565 -nasm data/con.fnt >cspr/confont.asm
+fi