fixed bugs, added progress bar, and more
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 23 Dec 2019 10:33:57 +0000 (12:33 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 23 Dec 2019 10:33:57 +0000 (12:33 +0200)
22 files changed:
.gitignore
GNUmakefile
Makefile
Makefile.wat
README.md
src/data.asm [new file with mode: 0644]
src/demo.c
src/dos/keyb.c
src/dos/main.c
src/dos/timer.c
src/gfxutil.c
src/gfxutil.h
src/scr/hairball.c
src/screen.c
src/sdl/main.c
src/sdl/timer.c
src/timer.h
src/util.h
tools/img2bin/Makefile [new file with mode: 0644]
tools/img2bin/img2bin.c [new file with mode: 0644]
tools/procdata
tools/scripts/pceminst [new file with mode: 0755]

index ed1a77c..4aa79a5 100644 (file)
@@ -40,3 +40,4 @@ data
 *.DJA
 tools/csprite/csprite
 cspr/
+tools/img2bin/img2bin
index 511b0ad..057ccfb 100644 (file)
@@ -1,9 +1,11 @@
 src = $(wildcard src/*.c) $(wildcard src/scr/*.c) $(wildcard src/sdl/*.c)
+asmsrc = $(wildcard src/*.asm)
 obj = $(src:.c=.o) $(asmsrc:.asm=.o)
 dep = $(obj:.o=.d)
 bin = demo
 
 asmsrc += cspr/dbgfont.asm cspr/confont.asm
+bindata = data/loading.img
 
 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
@@ -27,6 +29,8 @@ $(bin): $(obj) imago mikmod
 %.o: %.asm
        nasm -f elf -o $@ $<
 
+src/data.o: src/data.asm $(bindata)
+
 -include $(dep)
 
 %.d: %.c
index f3630fa..54e4148 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,6 +5,7 @@ dep = $(obj:.odj=.dep)
 bin = demo.exe
 
 asmsrc += cspr/dbgfont.asm cspr/confont.asm
+bindata = data/loading.img
 
 ifeq ($(findstring COMMAND.COM, $(SHELL)), COMMAND.COM)
        hostsys = dos
@@ -36,6 +37,8 @@ $(bin): $(obj) imago anim
 %.odj: %.asm
        nasm -f coff -o $@ $<
 
+src/data.odj: src/data.asm $(bindata)
+
 ifneq ($(hostsys), dos)
 -include $(dep)
 endif
index 1d0d7da..22e909d 100644 (file)
@@ -9,7 +9,7 @@ bin = demo.exe
 
 libs = imago.lib anim.lib
 
-def = -dM_PI=3.141592653589793
+def = -dM_PI=3.141592653589793 -dUSE_HLT
 opt = -5 -fp5 -otexan -oh -oi -ei
 dbg = -d2
 
index ec9721f..b3a41a1 100644 (file)
--- a/README.md
+++ b/README.md
@@ -129,3 +129,21 @@ U-only pairable instructions:
  - adc, sbb
  - shr, sar, shl, sal with immediate
  - ror, rol, rcr, rcl with immediate=1
+
+Notes about DJGPP & CWSDPMI
+---------------------------
+Can't use the `hlt` instruction for waiting for interrupts, because we're
+running in ring3 by default. I surrounded all the `hlt` instructions with a
+`USE_HLT` conditional, which is undefined when building with DJGPP.
+
+It's possible to arrange for our code to run on ring0 by changing the DPMI
+provider from `cwsdpmi.exe` to `cwsdpr0.exe` by running:
+`stubedit demo.exe dpmi=cwsdpr0.exe`, but I haven't tested under win9x to see if
+it still works if we do that.
+
+Our fucking segments don't start at 0 ... to access arbitrary parts of physical
+memory we need to call `__djgpp_nearptr_enable()` and use the following macros I
+defined in `cdpmi.h`:
+
+    #define virt_to_phys(v)    ((v) + __djgpp_base_address)
+    #define phys_to_virt(p)    ((p) - __djgpp_base_address)
diff --git a/src/data.asm b/src/data.asm
new file mode 100644 (file)
index 0000000..26234fc
--- /dev/null
@@ -0,0 +1,7 @@
+       section .data
+
+       global loading_pixels
+       global _loading_pixels
+loading_pixels:
+_loading_pixels:
+       incbin "data/loading.img"
index 8ad984c..77c3e80 100644 (file)
@@ -30,6 +30,9 @@ 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 con_active;
 
+extern uint16_t loading_pixels[];      /* data.asm */
+
+
 int demo_init(int argc, char **argv)
 {
        struct screen *scr;
@@ -45,6 +48,12 @@ int demo_init(int argc, char **argv)
                return -1;
        }
 
+       /* reuse the loading image as our back buffer.
+        * adjust fb_pixels to leave 4 pixels guard band top/bottom. We have enough
+        * space since the loading image is 8 pixels taller.
+        */
+       fb_pixels = loading_pixels + 320 * 4;
+
        con_init();
        initFpsFonts();
 
index a13ef81..55b9013 100644 (file)
@@ -161,10 +161,12 @@ void kb_wait(void)
 {
        int key;
        while((key = kb_getkey()) == -1) {
+#ifdef USE_HLT
                /* put the processor to sleep while waiting for keypresses, but first
                 * make sure interrupts are enabled, or we'll sleep forever
                 */
                halt();
+#endif
        }
        kb_putback(key);
 }
index 4dcca05..4d2f7fa 100644 (file)
@@ -51,12 +51,17 @@ int main(int argc, char **argv)
                set_mouse(fb_width / 2, fb_height / 2);
        }
 
+       /* now start_loadscr sets up fb_pixels to the space used by the loading image,
+        * so no need to allocate another framebuffer
+        */
+#if 0
        /* allocate a couple extra rows as a guard band, until we fucking fix the rasterizer */
        if(!(fb_pixels = malloc(fbsize + (fb_width * fb_bpp / 8) * 2))) {
                fprintf(stderr, "failed to allocate backbuffer\n");
                return 1;
        }
        fb_pixels += fb_width;
+#endif
 
        if(!(vmem = set_video_mode(fb_width, fb_height, fb_bpp, 1))) {
                return 1;
index dcf790c..d6c3b52 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "pit8254.h"
 #include "inttypes.h"
+#include "util.h"
 
 #define PIT_TIMER_INTR 8
 #define DOS_TIMER_INTR 0x1c
@@ -45,7 +46,7 @@ static _go32_dpmi_seginfo intr, prev_intr;
 
 static void INTERRUPT timer_irq();
 
-static unsigned long ticks;
+static volatile unsigned long ticks;
 static unsigned long tick_interval, ticks_per_dos_intr;
 static int inum;
 
@@ -123,6 +124,16 @@ unsigned long get_msec(void)
        return ticks * tick_interval;
 }
 
+void sleep_msec(unsigned long msec)
+{
+       unsigned long wakeup_time = ticks + msec / tick_interval;
+       while(ticks < wakeup_time) {
+#ifdef USE_HLT
+               halt();
+#endif
+       }
+}
+
 static void set_timer_reload(int reload_val)
 {
        outp(PORT_CMD, CMD_CHAN0 | CMD_ACCESS_BOTH | CMD_OP_SQWAVE);
index 37eb4c5..a8d7edc 100644 (file)
@@ -1,3 +1,4 @@
+#include <string.h>
 #include "gfxutil.h"
 #include "demo.h"
 
@@ -215,3 +216,28 @@ void convimg_rgb24_rgb16(uint16_t *dest, unsigned char *src, int xsz, int ysz)
                *dest++ = PACK_RGB16(r, g, b);
        }
 }
+
+void blitfb(uint16_t *dest, uint16_t *src, int width, int height, int pitch_pix)
+{
+       int i;
+       for(i=0; i<height; i++) {
+               memcpy(dest, src, width * 2);
+               dest += 320;
+               src += pitch_pix;
+       }
+}
+
+void blitfb_key(uint16_t *dest, uint16_t *src, int width, int height, int pitch_pix, uint16_t key)
+{
+       int i, j, dadv = 320 - width;
+
+       for(i=0; i<height; i++) {
+               for(j=0; j<width; j++) {
+                       uint16_t scol = *src++;
+                       if(scol != key) *dest = scol;
+                       dest++;
+               }
+               dest += dadv;
+       }
+
+}
index adbbd15..b46f813 100644 (file)
@@ -28,4 +28,7 @@ void blur_grey_vert(uint16_t *dest, uint16_t *src, int xsz, int ysz, int radius,
 
 void convimg_rgb24_rgb16(uint16_t *dest, unsigned char *src, int xsz, int ysz);
 
+void blitfb(uint16_t *dest, uint16_t *src, int xsz, int ysz, int pitch_pix);
+void blitfb_key(uint16_t *dest, uint16_t *src, int xsz, int ysz, int pitch_pix, uint16_t key);
+
 #endif /* GFXUTIL_H_ */
index 82b0535..5d891cc 100644 (file)
@@ -95,9 +95,9 @@ static int init(void)
 
                        float mindist = FLT_MAX;
                        for(j=0; j<numpt; j++) {
-                               float dx = pos.x - spawnpos[i].x;
-                               float dy = pos.y - spawnpos[i].y;
-                               float dz = pos.z - spawnpos[i].z;
+                               float dx = pos.x - spawnpos[j].x;
+                               float dy = pos.y - spawnpos[j].y;
+                               float dz = pos.z - spawnpos[j].z;
                                float dsq = dx * dx + dy * dy + dz * dz;
                                if(dsq < mindist) {
                                        mindist = dsq;
index 362a15c..ea9bb94 100644 (file)
@@ -4,6 +4,8 @@
 #include <assert.h>
 #include "screen.h"
 #include "demo.h"
+#include "gfxutil.h"
+#include "timer.h"
 
 #define DBG_SCRCHG \
        do { \
@@ -24,6 +26,10 @@ struct screen *greets_screen(void);
 struct screen *infcubes_screen(void);
 struct screen *hairball_screen(void);
 
+void start_loadscr(void);
+void end_loadscr(void);
+void loadscr(int n, int count);
+
 #define NUM_SCR 32
 static struct screen *scr[NUM_SCR];
 static int num_screens;
@@ -35,6 +41,8 @@ int scr_init(void)
 {
        int i, idx = 0;
 
+       start_loadscr();
+
        if(!(scr[idx++] = tunnel_screen())) {
                return -1;
        }
@@ -73,10 +81,13 @@ int scr_init(void)
        assert(num_screens <= NUM_SCR);
 
        for(i=0; i<num_screens; i++) {
+               loadscr(i, num_screens);
                if(scr[i]->init() == -1) {
                        return -1;
                }
        }
+
+       end_loadscr();
        return 0;
 }
 
@@ -169,3 +180,49 @@ int scr_change(struct screen *s, long trans_time)
        }
        return 0;
 }
+
+/* loading screen */
+extern uint16_t loading_pixels[];
+
+void start_loadscr(void)
+{
+       swap_buffers(loading_pixels);
+}
+
+#define SPLAT_X 288
+#define SPLAT_Y 104
+
+#define FING_X 217
+#define FING_LAST_X    291
+#define FING_Y 151
+#define FING_W 7
+#define FING_H 8
+
+void end_loadscr(void)
+{
+       blitfb(loading_pixels + SPLAT_Y * 320 + SPLAT_X, loading_pixels + 320 * 240, 32, 72, 32);
+       blitfb_key(loading_pixels + FING_Y * 320 + FING_LAST_X, loading_pixels + 247 * 320 + 64,
+                       FING_W, FING_H, FING_W, 0);
+       swap_buffers(loading_pixels);
+       sleep_msec(300);
+}
+
+void loadscr(int n, int count)
+{
+       int xoffs = 75 * n / (count - 1);
+       static int prev_xoffs;
+       uint16_t *sptr, *dptr;
+
+       sptr = loading_pixels + 247 * 320 + 64;
+       dptr = loading_pixels + FING_Y * 320 + FING_X + prev_xoffs;
+
+       while(prev_xoffs < xoffs) {
+               blitfb_key(dptr, sptr, FING_W, FING_H, FING_W, 0);
+               dptr++;
+               prev_xoffs++;
+       }
+
+       swap_buffers(loading_pixels);
+
+       /*sleep_msec(200);*/
+}
index fcaee9b..08bddf8 100644 (file)
@@ -33,9 +33,8 @@ static quat_t rot = {0, 0, 0, 1};
 
 int main(int argc, char **argv)
 {
-       int s, i, j;
+       int s;
        char *env;
-       unsigned short *sptr, *dptr;
 
        if((env = getenv("FBSCALE")) && (s = atoi(env))) {
                fbscale = s;
@@ -45,17 +44,21 @@ int main(int argc, char **argv)
        xsz = fb_width * fbscale;
        ysz = fb_height * fbscale;
 
+       /* now start_loadscr sets up fb_pixels to the space used by the loading image,
+        * so no need to allocate another framebuffer
+        */
+#if 0
        /* allocate 1 extra row as a guard band, until we fucking fix the rasterizer */
        if(!(fb_pixels = malloc(fb_width * (fb_height + 1) * fb_bpp / CHAR_BIT))) {
                fprintf(stderr, "failed to allocate virtual framebuffer\n");
                return 1;
        }
-       vmem = fb_pixels;
+#endif
 
        SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE);
        if(!(fbsurf = SDL_SetVideoMode(xsz, ysz, fb_bpp, sdl_flags))) {
                fprintf(stderr, "failed to set video mode %dx%d %dbpp\n", fb_width, fb_height, fb_bpp);
-               free(fb_pixels);
+               /*free(fb_pixels);*/
                SDL_Quit();
                return 1;
        }
@@ -64,10 +67,11 @@ int main(int argc, char **argv)
 
        time_msec = 0;
        if(demo_init(argc, argv) == -1) {
-               free(fb_pixels);
+               /*free(fb_pixels);*/
                SDL_Quit();
                return 1;
        }
+       vmem = fb_pixels;
 
        if(opt.sball && sball_init() == 0) {
                use_sball = 1;
@@ -93,32 +97,6 @@ int main(int argc, char **argv)
 
                time_msec = get_msec();
                demo_draw();
-
-               if(SDL_MUSTLOCK(fbsurf)) {
-                       SDL_LockSurface(fbsurf);
-               }
-
-               sptr = fb_pixels;
-               dptr = (unsigned short*)fbsurf->pixels + (fbsurf->w - xsz) / 2;
-               for(i=0; i<fb_height; i++) {
-                       for(j=0; j<fb_width; j++) {
-                               int x, y;
-                               unsigned short pixel = *sptr++;
-
-                               for(y=0; y<fbscale; y++) {
-                                       for(x=0; x<fbscale; x++) {
-                                               dptr[y * fbsurf->w + x] = pixel;
-                                       }
-                               }
-                               dptr += fbscale;
-                       }
-                       dptr += (fbsurf->w - fb_width) * fbscale;
-               }
-
-               if(SDL_MUSTLOCK(fbsurf)) {
-                       SDL_UnlockSurface(fbsurf);
-               }
-               SDL_Flip(fbsurf);
        }
 
 break_evloop:
@@ -141,12 +119,40 @@ void wait_vsync(void)
 
 void swap_buffers(void *pixels)
 {
+       int i, j;
+       unsigned short *sptr, *dptr;
+
        demo_post_draw(pixels ? pixels : fb_pixels);
 
-       /* do nothing, all pointers point to the same buffer */
        if(opt.vsync) {
                wait_vsync();
        }
+
+       if(SDL_MUSTLOCK(fbsurf)) {
+               SDL_LockSurface(fbsurf);
+       }
+
+       sptr = fb_pixels;
+       dptr = (unsigned short*)fbsurf->pixels + (fbsurf->w - xsz) / 2;
+       for(i=0; i<fb_height; i++) {
+               for(j=0; j<fb_width; j++) {
+                       int x, y;
+                       unsigned short pixel = *sptr++;
+
+                       for(y=0; y<fbscale; y++) {
+                               for(x=0; x<fbscale; x++) {
+                                       dptr[y * fbsurf->w + x] = pixel;
+                               }
+                       }
+                       dptr += fbscale;
+               }
+               dptr += (fbsurf->w - fb_width) * fbscale;
+       }
+
+       if(SDL_MUSTLOCK(fbsurf)) {
+               SDL_UnlockSurface(fbsurf);
+       }
+       SDL_Flip(fbsurf);
 }
 
 static int bnmask(int sdlbn)
index 2193ddd..2f2993b 100644 (file)
@@ -16,3 +16,8 @@ unsigned long get_msec(void)
 {
        return SDL_GetTicks() - start_time;
 }
+
+void sleep_msec(unsigned long msec)
+{
+       SDL_Delay(msec);
+}
index 1fa83c3..395381c 100644 (file)
@@ -13,6 +13,8 @@ void init_timer(int res_hz);
 void reset_timer(void);
 unsigned long get_msec(void);
 
+void sleep_msec(unsigned long msec);
+
 #ifdef __cplusplus
 }
 #endif
index 6d869eb..ce43bbe 100644 (file)
@@ -49,6 +49,9 @@ void perf_end(void);
 
 void debug_break(void);
 #pragma aux debug_break = "int 3";
+
+void halt(void);
+#pragma aux halt = "hlt";
 #endif
 
 #ifdef __GNUC__
@@ -72,6 +75,9 @@ void debug_break(void);
 
 #define debug_break() \
        asm volatile ("int $3")
+
+#define halt() \
+       asm volatile("hlt")
 #endif
 
 #ifdef _MSC_VER
diff --git a/tools/img2bin/Makefile b/tools/img2bin/Makefile
new file mode 100644 (file)
index 0000000..c9423c3
--- /dev/null
@@ -0,0 +1,14 @@
+obj = img2bin.o
+bin = img2bin
+
+root = ../..
+
+CFLAGS = -pedantic -Wall -g -I$(root)/libs/imago/src
+LDFLAGS = -L$(root)/libs/imago -limago
+
+$(bin): $(obj)
+       $(CC) -o $@ $(obj) $(LDFLAGS)
+
+.PHONY: clean
+clean:
+       rm -f $(obj) $(bin)
diff --git a/tools/img2bin/img2bin.c b/tools/img2bin/img2bin.c
new file mode 100644 (file)
index 0000000..af43128
--- /dev/null
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include "imago2.h"
+
+int proc_image(const char *fname);
+
+int main(int argc, char **argv)
+{
+       int i;
+
+       for(i=1; i<argc; i++) {
+               if(proc_image(argv[i]) == -1) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+int proc_image(const char *fname)
+{
+       int i, xsz, ysz, npixels, len;
+       unsigned char *pixels24, *sptr;
+       uint16_t *pixels16, *dptr;
+       char *outfname, *suffix;
+       FILE *out;
+
+       len = strlen(fname);
+       outfname = alloca(len + 4);
+       memcpy(outfname, fname, len + 1);
+       if((suffix = strrchr(outfname, '.')) && suffix > outfname) {
+               strcpy(suffix, ".img");
+       } else {
+               strcpy(outfname + len, ".img");
+       }
+
+       if(!(pixels24 = img_load_pixels(fname, &xsz, &ysz, IMG_FMT_RGB24))) {
+               fprintf(stderr, "failed to load image: %s\n", fname);
+               return -1;
+       }
+       npixels = xsz * ysz;
+       if(!(pixels16 = malloc(npixels * 2))) {
+               perror("failed to allocate output image buffer");
+               img_free_pixels(pixels24);
+               return -1;
+       }
+
+       if(!(out = fopen(outfname, "wb"))) {
+               fprintf(stderr, "failed to open %s for writing: %s\n", outfname, strerror(errno));
+               img_free_pixels(pixels24);
+               free(pixels16);
+               return -1;
+       }
+
+       sptr = pixels24;
+       dptr = pixels16;
+       for(i=0; i<npixels; i++) {
+               int r = *sptr++ >> 3;
+               int g = *sptr++ >> 2;
+               int b = *sptr++ >> 3;
+               *dptr++ = (r << 11) | (g << 5) | b;
+       }
+       img_free_pixels(pixels24);
+
+       fwrite(pixels16, 2, npixels, out);
+       fclose(out);
+       free(pixels16);
+       return 0;
+}
index 149abb9..25136ad 100755 (executable)
@@ -6,18 +6,30 @@ if [ ! -f tools/procdata ]; then
        exit 1
 fi
 
+# process embedded images
+if [ ! -f tools/img2bin/img2bin ]; then
+       make -C tools/img2bin/img2bin || exit 1
+fi
+alias img2bin=tools/img2bin/img2bin
+
+mkdir -p data
+if [ ! -f data/loading.img -o data/loading.png -nt data/loading.img ]; then
+       echo 'img2bin: loading'
+       img2bin data/loading.png || exit 1
+fi
+
+# process compiled sprites
 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
+       csprite -n cs_dbgfont -s 8x16 -conv565 -nasm -xor data/legible.fnt >cspr/dbgfont.asm || exit 1
 fi
 if [ ! -f cspr/confont.asm -o data/console.fnt -nt cspr/confont.asm ]; then
        echo 'csprite: confont'
-       csprite -n cs_confont -s 6x7 -pad 1 -conv565 -nasm data/console.fnt >cspr/confont.asm
+       csprite -n cs_confont -s 6x7 -pad 1 -conv565 -nasm data/console.fnt >cspr/confont.asm || exit 1
 fi
diff --git a/tools/scripts/pceminst b/tools/scripts/pceminst
new file mode 100755 (executable)
index 0000000..30244e2
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# NOTES:
+# assumes a PCem setup with a fat16 image mounted at /pcem_dos. fstab entry:
+#  /home/nuclear/.pcem/pentium_dos.img /pcem_dos msdos user,noauto,loop,fmask=0113,dmask=0002,gid=6,offset=32256 0 0
+
+mntpt=/pcem_dos
+do_umount=false
+
+if ! ( mount | grep pcem ); then
+       mount $mntpt || exit 1
+       do_umount=true
+fi
+
+tools/scripts/instdfs $mntpt/tmp
+
+if $do_umount; then
+       umount $mntpt
+fi
+sync