From 7cffbf057545fb303ad8f53e432ef42f7708e16d Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Mon, 23 Dec 2019 12:33:57 +0200 Subject: [PATCH] fixed bugs, added progress bar, and more --- .gitignore | 1 + GNUmakefile | 4 +++ Makefile | 3 ++ Makefile.wat | 2 +- README.md | 18 ++++++++++++ src/data.asm | 7 +++++ src/demo.c | 9 ++++++ src/dos/keyb.c | 2 ++ src/dos/main.c | 5 ++++ src/dos/timer.c | 13 ++++++++- src/gfxutil.c | 26 +++++++++++++++++ src/gfxutil.h | 3 ++ src/scr/hairball.c | 6 ++-- src/screen.c | 57 +++++++++++++++++++++++++++++++++++++ src/sdl/main.c | 70 +++++++++++++++++++++++++--------------------- src/sdl/timer.c | 5 ++++ src/timer.h | 2 ++ src/util.h | 6 ++++ tools/img2bin/Makefile | 14 ++++++++++ tools/img2bin/img2bin.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ tools/procdata | 18 ++++++++++-- tools/scripts/pceminst | 20 +++++++++++++ 22 files changed, 322 insertions(+), 40 deletions(-) create mode 100644 src/data.asm create mode 100644 tools/img2bin/Makefile create mode 100644 tools/img2bin/img2bin.c create mode 100755 tools/scripts/pceminst diff --git a/.gitignore b/.gitignore index ed1a77c..4aa79a5 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ data *.DJA tools/csprite/csprite cspr/ +tools/img2bin/img2bin diff --git a/GNUmakefile b/GNUmakefile index 511b0ad..057ccfb 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -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 diff --git a/Makefile b/Makefile index f3630fa..54e4148 100644 --- 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 diff --git a/Makefile.wat b/Makefile.wat index 1d0d7da..22e909d 100644 --- a/Makefile.wat +++ b/Makefile.wat @@ -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 diff --git a/README.md b/README.md index ec9721f..b3a41a1 100644 --- 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 index 0000000..26234fc --- /dev/null +++ b/src/data.asm @@ -0,0 +1,7 @@ + section .data + + global loading_pixels + global _loading_pixels +loading_pixels: +_loading_pixels: + incbin "data/loading.img" diff --git a/src/demo.c b/src/demo.c index 8ad984c..77c3e80 100644 --- a/src/demo.c +++ b/src/demo.c @@ -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(); diff --git a/src/dos/keyb.c b/src/dos/keyb.c index a13ef81..55b9013 100644 --- a/src/dos/keyb.c +++ b/src/dos/keyb.c @@ -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); } diff --git a/src/dos/main.c b/src/dos/main.c index 4dcca05..4d2f7fa 100644 --- a/src/dos/main.c +++ b/src/dos/main.c @@ -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; diff --git a/src/dos/timer.c b/src/dos/timer.c index dcf790c..d6c3b52 100644 --- a/src/dos/timer.c +++ b/src/dos/timer.c @@ -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); diff --git a/src/gfxutil.c b/src/gfxutil.c index 37eb4c5..a8d7edc 100644 --- a/src/gfxutil.c +++ b/src/gfxutil.c @@ -1,3 +1,4 @@ +#include #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 #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; iinit() == -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);*/ +} diff --git a/src/sdl/main.c b/src/sdl/main.c index fcaee9b..08bddf8 100644 --- a/src/sdl/main.c +++ b/src/sdl/main.c @@ -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; iw + 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; iw + 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) diff --git a/src/sdl/timer.c b/src/sdl/timer.c index 2193ddd..2f2993b 100644 --- a/src/sdl/timer.c +++ b/src/sdl/timer.c @@ -16,3 +16,8 @@ unsigned long get_msec(void) { return SDL_GetTicks() - start_time; } + +void sleep_msec(unsigned long msec) +{ + SDL_Delay(msec); +} diff --git a/src/timer.h b/src/timer.h index 1fa83c3..395381c 100644 --- a/src/timer.h +++ b/src/timer.h @@ -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 diff --git a/src/util.h b/src/util.h index 6d869eb..ce43bbe 100644 --- a/src/util.h +++ b/src/util.h @@ -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 index 0000000..c9423c3 --- /dev/null +++ b/tools/img2bin/Makefile @@ -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 index 0000000..af43128 --- /dev/null +++ b/tools/img2bin/img2bin.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include "imago2.h" + +int proc_image(const char *fname); + +int main(int argc, char **argv) +{ + int i; + + for(i=1; i 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> 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; +} diff --git a/tools/procdata b/tools/procdata index 149abb9..25136ad 100755 --- a/tools/procdata +++ b/tools/procdata @@ -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 index 0000000..30244e2 --- /dev/null +++ b/tools/scripts/pceminst @@ -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 -- 1.7.10.4