*.DJA
tools/csprite/csprite
cspr/
+tools/img2bin/img2bin
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
%.o: %.asm
nasm -f elf -o $@ $<
+src/data.o: src/data.asm $(bindata)
+
-include $(dep)
%.d: %.c
bin = demo.exe
asmsrc += cspr/dbgfont.asm cspr/confont.asm
+bindata = data/loading.img
ifeq ($(findstring COMMAND.COM, $(SHELL)), COMMAND.COM)
hostsys = dos
%.odj: %.asm
nasm -f coff -o $@ $<
+src/data.odj: src/data.asm $(bindata)
+
ifneq ($(hostsys), dos)
-include $(dep)
endif
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
- 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)
--- /dev/null
+ section .data
+
+ global loading_pixels
+ global _loading_pixels
+loading_pixels:
+_loading_pixels:
+ incbin "data/loading.img"
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;
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();
{
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);
}
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;
#include "pit8254.h"
#include "inttypes.h"
+#include "util.h"
#define PIT_TIMER_INTR 8
#define DOS_TIMER_INTR 0x1c
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;
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);
+#include <string.h>
#include "gfxutil.h"
#include "demo.h"
*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;
+ }
+
+}
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_ */
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;
#include <assert.h>
#include "screen.h"
#include "demo.h"
+#include "gfxutil.h"
+#include "timer.h"
#define DBG_SCRCHG \
do { \
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;
{
int i, idx = 0;
+ start_loadscr();
+
if(!(scr[idx++] = tunnel_screen())) {
return -1;
}
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;
}
}
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);*/
+}
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;
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;
}
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;
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:
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)
{
return SDL_GetTicks() - start_time;
}
+
+void sleep_msec(unsigned long msec)
+{
+ SDL_Delay(msec);
+}
void reset_timer(void);
unsigned long get_msec(void);
+void sleep_msec(unsigned long msec);
+
#ifdef __cplusplus
}
#endif
void debug_break(void);
#pragma aux debug_break = "int 3";
+
+void halt(void);
+#pragma aux halt = "hlt";
#endif
#ifdef __GNUC__
#define debug_break() \
asm volatile ("int $3")
+
+#define halt() \
+ asm volatile("hlt")
#endif
#ifdef _MSC_VER
--- /dev/null
+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)
--- /dev/null
+#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;
+}
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
--- /dev/null
+#!/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