From: John Tsiombikas Date: Fri, 5 Jun 2020 13:39:37 +0000 (+0300) Subject: started backporting the eradicate code X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=commitdiff_plain;h=93f68e445b0a4f10f2b15383aafed8a216a4a228;ds=sidebyside started backporting the eradicate code --- diff --git a/src/dos/audos.c b/src/dos/audos.c new file mode 100644 index 0000000..513bf89 --- /dev/null +++ b/src/dos/audos.c @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include "audio.h" +#include "midasdll.h" + +#define SET_MUS_VOL(vol) \ + do { \ + int mv = (vol) * vol_master >> 10; \ + MIDASsetMusicVolume(modplay, mv ? mv + 1 : 0); \ + } while(0) + +extern int force_snd_config; + +static MIDASmodulePlayHandle modplay; +static struct au_module *curmod; + +static int vol_master, vol_mus, vol_sfx; + +int au_init(void) +{ + modplay = 0; + curmod = 0; + vol_master = vol_mus = vol_sfx = 255; + + MIDASstartup(); + + if(force_snd_config || (!MIDASloadConfig("sound.cfg") && !MIDASdetectSoundCard())) { + if(MIDASconfig()) { + if(!MIDASsaveConfig("sound.cfg")) { + fprintf(stderr, "failed to save sound card configuration\n"); + } + } + } + + MIDASinit(); + + MIDASstartBackgroundPlay(0); + return 0; +} + +void au_shutdown(void) +{ + if(curmod) { + au_stop_module(curmod); + } + MIDASstopBackgroundPlay(); + MIDASclose(); +} + +struct au_module *au_load_module(const char *fname) +{ + static MIDASmoduleInfo info; + struct au_module *mod; + char *name, *end; + + if(!(mod = malloc(sizeof *mod))) { + fprintf(stderr, "au_load_module: failed to allocate module\n"); + return 0; + } + + if(!(mod->impl = MIDASloadModule((char*)fname))) { + fprintf(stderr, "au_load_module: failed to load module: %s\n", fname); + free(mod); + return 0; + } + + name = 0; + if(MIDASgetModuleInfo(mod->impl, &info)) { + name = info.songName; + end = name + strlen(name) - 1; + while(end >= name && isspace(*end)) { + *end-- = 0; + } + if(!*name) name = 0; + } + + if(!name) { + /* fallback to using the filename */ + if((name = strrchr(fname, '/')) || (name = strrchr(fname, '\\'))) { + name++; + } else { + name = (char*)fname; + } + } + + if(!(mod->name = malloc(strlen(name) + 1))) { + fprintf(stderr, "au_load_module: mod->name malloc failed\n"); + MIDASfreeModule(mod->impl); + return 0; + } + strcpy(mod->name, name); + + printf("loaded module \"%s\" (%s)\n", name, fname); + return mod; +} + +void au_free_module(struct au_module *mod) +{ + if(!mod) return; + + if(mod == curmod) { + au_stop_module(curmod); + } + MIDASfreeModule(mod->impl); + free(mod->name); + free(mod); +} + +int au_play_module(struct au_module *mod) +{ + if(curmod) { + if(curmod == mod) return 0; + au_stop_module(curmod); + } + + if(!(modplay = MIDASplayModule(mod->impl, 1))) { + fprintf(stderr, "au_play_module: failed to play module: %s\n", mod->name); + return -1; + } + SET_MUS_VOL(vol_mus); + curmod = mod; + return 0; +} + +void au_update(void) +{ +} + +int au_stop_module(struct au_module *mod) +{ + if(mod && curmod != mod) return -1; + if(!curmod) return -1; + + MIDASstopModule(modplay); + curmod = 0; + return 0; +} + +int au_module_state(struct au_module *mod) +{ + if(mod) { + return curmod == mod ? AU_PLAYING : AU_STOPPED; + } + return curmod ? AU_PLAYING : AU_STOPPED; +} + +int au_volume(int vol) +{ + AU_VOLADJ(vol_master, vol); + if(vol != vol_master) { + vol_master = vol; + + au_sfx_volume(vol_sfx); + au_music_volume(vol_mus); + } + return vol_master; +} + +int au_sfx_volume(int vol) +{ + AU_VOLADJ(vol_sfx, vol); + vol_sfx = vol; + + /* TODO set sfx volume */ + return vol_sfx; +} + + +int au_music_volume(int vol) +{ + AU_VOLADJ(vol_mus, vol); + vol_mus = vol; + + if(curmod) { + SET_MUS_VOL(vol); + } + return vol_mus; +} + +/* when using MIDAS, we can't access the PIT directly, so we don't build timer.c + * and implement all the timer functions here, using MIDAS callbacks + */ +static volatile unsigned long ticks; +static unsigned long tick_interval; + +static void MIDAS_CALL midas_timer(void) +{ + ticks++; +} + +/* macro to divide and round to the nearest integer */ +#define DIV_ROUND(a, b) \ + ((a) / (b) + ((a) % (b)) / ((b) / 2)) + +void init_timer(int res_hz) +{ + MIDASsetTimerCallbacks(res_hz * 1000, 0, midas_timer, 0, 0); + tick_interval = DIV_ROUND(1000, res_hz); +} + +void reset_timer(void) +{ + ticks = 0; +} + +unsigned long get_msec(void) +{ + return ticks * tick_interval; +} diff --git a/src/dos/gfx.c b/src/dos/gfx.c index 5252cbc..1f9b727 100644 --- a/src/dos/gfx.c +++ b/src/dos/gfx.c @@ -1,34 +1,54 @@ #include +#include #include +#include "demo.h" +#include "cdpmi.h" #include "gfx.h" #include "vbe.h" #include "vga.h" -#include "cdpmi.h" +#include "util.h" + +#define SAME_BPP(a, b) \ + ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \ + ((a) == 32 && (b) == 24) || ((a) == 24 && (b) == 32)) -#define SAME_BPP(a, b) \ - ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \ - ((a) == 32 && (b) == 24) || ((a) == 24 && (b) == 32)) +void (*blit_frame)(void*, int); + +static void blit_frame_lfb(void *pixels, int vsync); +static void blit_frame_banked(void *pixels, int vsync); +static uint32_t calc_mask(int sz, int pos); + +static struct video_mode *vmodes; +static int num_vmodes; static int vbe_init_ver; static struct vbe_info vbe; -static int mode, pgsize, fbsize; -static struct vbe_mode_info mode_info; +/* current mode */ +static struct video_mode *curmode; static void *vpgaddr[2]; -static int fbidx; -static int pgcount; +static int frontidx, backidx; +static int pgcount, pgsize, fbsize; + -static int init_vbe(void) +int init_video(void) { - int i, num; + int i, num, max_modes; + struct video_mode *vmptr; if(vbe_info(&vbe) == -1) { fprintf(stderr, "failed to retrieve VBE information\n"); return -1; } - vbe_print_info(stdout, &vbe); + num_vmodes = 0; + max_modes = 64; + if(!(vmodes = malloc(max_modes * sizeof *vmodes))) { + fprintf(stderr, "failed to allocate video modes list\n"); + return -1; + } + num = vbe_num_modes(&vbe); for(i=0; i= max_modes) { + int newmax = max_modes ? (max_modes << 1) : 16; + if(!(vmptr = realloc(vmodes, newmax * sizeof *vmodes))) { + fprintf(stderr, "failed to grow video mode list (%d)\n", newmax); + free(vmodes); + return -1; + } + vmodes = vmptr; + max_modes = newmax; + } + + vmptr = vmodes + num_vmodes++; + memset(vmptr, 0, sizeof *vmptr); + vmptr->mode = vbe.modes[i]; + vmptr->xsz = minf.xres; + vmptr->ysz = minf.yres; + vmptr->bpp = minf.bpp; + vmptr->pitch = minf.scanline_bytes; + if(minf.mem_model == VBE_TYPE_DIRECT) { + vmptr->rbits = minf.rsize; + vmptr->gbits = minf.gsize; + vmptr->bbits = minf.bsize; + vmptr->rshift = minf.rpos; + vmptr->gshift = minf.gpos; + vmptr->bshift = minf.bpos; + vmptr->rmask = calc_mask(minf.rsize, minf.rpos); + vmptr->gmask = calc_mask(minf.gsize, minf.gpos); + vmptr->bmask = calc_mask(minf.bsize, minf.bpos); + vmptr->bpp = vmptr->rbits + vmptr->gbits + vmptr->bbits; + } + if(minf.attr & VBE_ATTR_LFB) { + vmptr->fb_addr = minf.fb_addr; + } else { + vmptr->bank_size = (uint32_t)minf.bank_size * 1024; + if(!vmptr->bank_size) { + vmptr->bank_size = 65536; + } + } + vmptr->max_pages = minf.num_img_pages; + printf("%04x: ", vbe.modes[i]); vbe_print_mode_info(stdout, &minf); } @@ -45,73 +106,134 @@ static int init_vbe(void) return 0; } -void *set_video_mode(int xsz, int ysz, int bpp, int nbuf) +void cleanup_video(void) { - int i, nmodes; - int best_match_mode = -1; - struct vbe_mode_info minf; + free(vmodes); +} - if(!vbe_init_ver) { - if(init_vbe() == -1) { - fprintf(stderr, "failed to initialize VBE\n"); - return 0; - } - if(vbe_init_ver < 2) { - fprintf(stderr, "VBE >= 2.0 required\n"); - return 0; - } +struct video_mode *video_modes(void) +{ + return vmodes; +} + +int num_video_modes(void) +{ + return num_vmodes; +} + +struct video_mode *get_video_mode(int idx) +{ + if(idx == VMODE_CURRENT) { + return curmode; } + return vmodes + idx; +} - mode = -1; - nmodes = vbe_num_modes(&vbe); - for(i=0; ixsz != xsz || vm->ysz != ysz) continue; + if(SAME_BPP(vm->bpp, bpp)) { + best = i; } + if(vm->bpp == bpp) break; + } + + if(best == -1) { + fprintf(stderr, "failed to find video mode %dx%d %d bpp)\n", xsz, ysz, bpp); + return -1; } + return best; +} + +int find_video_mode(int mode) +{ + int i; + struct video_mode *vm; - if(mode == -1) { - if(best_match_mode == -1) { - fprintf(stderr, "failed to find requested video mode (%dx%d %d bpp)\n", xsz, ysz, bpp); + vm = vmodes; + for(i=0; imode == mode) return i; + } + return -1; +} + +void *set_video_mode(int idx, int nbuf) +{ + unsigned int mode; + struct video_mode *vm = vmodes + idx; + + if(curmode == vm) return vpgaddr[0]; + + printf("setting video mode %x (%dx%d %d bpp)\n", (unsigned int)vm->mode, + vm->xsz, vm->ysz, vm->bpp); + fflush(stdout); + + mode = vm->mode | VBE_MODE_LFB; + if(vbe_setmode(mode) == -1) { + mode = vm->mode; + if(vbe_setmode(mode) == -1) { + fprintf(stderr, "failed to set video mode %x\n", (unsigned int)vm->mode); return 0; } - mode = best_match_mode; + printf("Warning: failed to get a linear framebuffer. falling back to banked mode\n"); } - vbe_mode_info(mode, &mode_info); - printf("setting video mode %x: (%dx%d %d)\n", (unsigned int)mode, mode_info.xres, - mode_info.yres, mode_info.bpp); - - if(vbe_setmode(mode | VBE_MODE_LFB) == -1) { - fprintf(stderr, "failed to set video mode\n"); - return 0; + /* unmap previous video memory mapping, if there was one (switching modes) */ + if(vpgaddr[0] && vpgaddr[0] != (void*)0xa0000) { + dpmi_munmap(vpgaddr[0]); + vpgaddr[0] = vpgaddr[1] = 0; } + curmode = vm; if(nbuf < 1) nbuf = 1; if(nbuf > 2) nbuf = 2; - pgcount = nbuf > mode_info.num_img_pages ? mode_info.num_img_pages : nbuf; - - pgsize = mode_info.xres * mode_info.yres * (bpp / 8); + pgcount = nbuf > vm->max_pages ? vm->max_pages : nbuf; + pgsize = vm->ysz * vm->pitch; fbsize = pgcount * pgsize; - vpgaddr[0] = (void*)dpmi_mmap(mode_info.fb_addr, fbsize); - memset(vpgaddr[0], 0xaa, fbsize); + printf("pgcount: %d, pgsize: %d, fbsize: %d\n", pgcount, pgsize, fbsize); + printf("phys addr: %p\n", (void*)vm->fb_addr); + fflush(stdout); + + if(vm->fb_addr) { + vpgaddr[0] = (void*)dpmi_mmap(vm->fb_addr, fbsize); + if(!vpgaddr[0]) { + fprintf(stderr, "failed to map framebuffer (phys: %lx, size: %d)\n", + (unsigned long)vm->fb_addr, fbsize); + set_text_mode(); + return 0; + } + memset(vpgaddr[0], 0xaa, pgsize); + + if(pgcount > 1) { + vpgaddr[1] = (char*)vpgaddr[0] + pgsize; + backidx = 1; + page_flip(FLIP_NOW); /* start with the second page visible */ + } else { + frontidx = backidx = 0; + vpgaddr[1] = 0; + } + + blit_frame = blit_frame_lfb; - if(pgcount > 1) { - vpgaddr[1] = (char*)vpgaddr[0] + pgsize; - fbidx = 1; - page_flip(FLIP_NOW); /* start with the second page visible */ } else { - fbidx = 0; + vpgaddr[0] = (void*)0xa0000; vpgaddr[1] = 0; + + blit_frame = blit_frame_banked; + } + + /* allocate main memory framebuffer */ + if(resizefb(vm->xsz, vm->ysz, vm->bpp) == -1) { + fprintf(stderr, "failed to allocate %dx%d (%d bpp) framebuffer\n", vm->xsz, + vm->ysz, vm->bpp); + set_text_mode(); + return 0; } return vpgaddr[0]; @@ -119,7 +241,14 @@ void *set_video_mode(int xsz, int ysz, int bpp, int nbuf) int set_text_mode(void) { + /* unmap previous video memory mapping, if there was one (switching modes) */ + if(vpgaddr[0] && vpgaddr[0] != (void*)0xa0000) { + dpmi_munmap(vpgaddr[0]); + vpgaddr[0] = vpgaddr[1] = 0; + } + vga_setmode(3); + curmode = 0; return 0; } @@ -130,8 +259,52 @@ void *page_flip(int vsync) return vpgaddr[0]; } - vbe_swap(fbidx ? pgsize : 0, vsync ? VBE_SWAP_VBLANK : VBE_SWAP_NOW); - fbidx = (fbidx + 1) & 1; + vbe_swap(backidx ? pgsize : 0, vsync ? VBE_SWAP_VBLANK : VBE_SWAP_NOW); + frontidx = backidx; + backidx = (backidx + 1) & 1; + + return vpgaddr[backidx]; +} + + +static void blit_frame_lfb(void *pixels, int vsync) +{ + if(show_fps) dbg_fps(pixels); + if(vsync) wait_vsync(); + memcpy64(vpgaddr[frontidx], pixels, pgsize >> 3); +} + +static void blit_frame_banked(void *pixels, int vsync) +{ + int i, sz, offs; + unsigned int pending; + unsigned char *pptr = pixels; + + if(show_fps) dbg_fps(pixels); + + if(vsync) wait_vsync(); + + /* assume initial window offset at 0 */ + offs = 0; + pending = pgsize; + while(pending > 0) { + sz = pending > curmode->bank_size ? curmode->bank_size : pending; + //memcpy64((void*)0xa0000, pptr, sz >> 3); + memcpy((void*)0xa0000, pptr, sz); + pptr += sz; + pending -= sz; + vbe_setwin(0, ++offs); + } + + vbe_setwin(0, 0); +} - return vpgaddr[fbidx]; +static uint32_t calc_mask(int sz, int pos) +{ + int i; + uint32_t mask = 0; + while(sz-- > 0) { + mask = (mask << 1) | 1; + } + return mask << pos; } diff --git a/src/dos/gfx.h b/src/dos/gfx.h index 10d6e0b..1f5d90c 100644 --- a/src/dos/gfx.h +++ b/src/dos/gfx.h @@ -1,17 +1,38 @@ #ifndef GFX_H_ #define GFX_H_ +#include "inttypes.h" + +struct video_mode { + uint16_t mode; + short xsz, ysz, bpp, pitch; + short rbits, gbits, bbits; + short rshift, gshift, bshift; + uint32_t rmask, gmask, bmask; + uint32_t fb_addr; + short max_pages; + uint32_t bank_size; +}; + #ifdef __cplusplus extern "C" { #endif -void *set_video_mode(int xsz, int ysz, int bpp, int nbuf); -int set_text_mode(void); +int init_video(void); +void cleanup_video(void); -int get_color_depth(void); -int get_color_bits(int *rbits, int *gbits, int *bbits); -int get_color_shift(int *rshift, int *gshift, int *bshift); -int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask); +struct video_mode *video_modes(void); +int num_video_modes(void); + +#define VMODE_CURRENT (-1) +struct video_mode *get_video_mode(int idx); + +int match_video_mode(int xsz, int ysz, int bpp); +int find_video_mode(int mode); + +/* argument is the mode list index [0, nmodes-1] */ +void *set_video_mode(int idx, int nbuf); +int set_text_mode(void); void set_palette(int idx, int r, int g, int b); @@ -21,6 +42,7 @@ enum { }; /* page flip and return pointer to the start of the display area (front buffer) */ void *page_flip(int vsync); +extern void (*blit_frame)(void *pixels, int vsync); #ifdef __WATCOMC__ void wait_vsync(void); diff --git a/src/dos/inttypes.h b/src/dos/inttypes.h index 4d40ee2..da3cddc 100644 --- a/src/dos/inttypes.h +++ b/src/dos/inttypes.h @@ -18,8 +18,7 @@ along with this program. If not, see . #ifndef INT_TYPES_H_ #define INT_TYPES_H_ -/*#if defined(__WATCOMC__) && __WATCOMC__ < 0x1200*/ -#if defined(__DOS__) || defined(__MSDOS__) +#if defined(__WATCOMC__) && __WATCOMC__ < 1200 typedef char int8_t; typedef short int16_t; typedef long int32_t; diff --git a/src/dos/keyb.c b/src/dos/keyb.c index 55b9013..ac200b3 100644 --- a/src/dos/keyb.c +++ b/src/dos/keyb.c @@ -214,12 +214,18 @@ static void INTERRUPT kbintr() { unsigned char code; int key, c, press; + static int ext; code = inp(KB_PORT); - if(code >= 128) { + if(code == 0xe0) { + ext = 1; + goto eoi; + } + + if(code & 0x80) { press = 0; - code -= 128; + code &= 0x7f; if(num_pressed > 0) { num_pressed--; @@ -230,8 +236,14 @@ static void INTERRUPT kbintr() num_pressed++; } - key = scantbl[code]; - c = (keystate[KB_LSHIFT] | keystate[KB_RSHIFT]) ? scantbl_shift[code] : key; + if(ext) { + key = scantbl_ext[code]; + c = key; + ext = 0; + } else { + key = scantbl[code]; + c = (keystate[KB_LSHIFT] | keystate[KB_RSHIFT]) ? scantbl_shift[code] : key; + } if(press) { /* append to buffer */ @@ -251,5 +263,6 @@ static void INTERRUPT kbintr() /* and update keystate table */ keystate[key] = press; +eoi: outp(PIC1_CMD_PORT, OCW2_EOI); /* send end-of-interrupt */ } diff --git a/src/dos/main.c b/src/dos/main.c index 5d840b1..7535681 100644 --- a/src/dos/main.c +++ b/src/dos/main.c @@ -1,62 +1,61 @@ #include #include -#include #include -#include -#include -#include #include "demo.h" #include "keyb.h" -#include "mouse.h" #include "timer.h" #include "gfx.h" -#include "vmath.h" -#include "sball.h" -#include "cfgopt.h" #include "logger.h" -#include "tinyfps.h" #include "cdpmi.h" - -#undef NOKEYB +#include "audio.h" static int handle_sball_event(sball_event *ev); static void recalc_sball_matrix(float *xform); static int quit; -static long fbsize; + +int force_snd_config; static int use_sball; static vec3_t pos = {0, 0, 0}; static quat_t rot = {0, 0, 0, 1}; + int main(int argc, char **argv) { + int i; + int vmidx, status = 0; + + for(i=1; imotion.motion[0]) #define TY(ev) ((ev)->motion.motion[1]) #define TZ(ev) ((ev)->motion.motion[2]) diff --git a/src/dos/scancode.h b/src/dos/scancode.h index 48f8a0b..b0e398c 100644 --- a/src/dos/scancode.h +++ b/src/dos/scancode.h @@ -45,3 +45,17 @@ static int scantbl_shift[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70 - 7f */ }; + + +/* extended scancodes, after the 0xe0 prefix */ +static int scantbl_ext[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\r', KB_RCTRL, 0, 0, /* 10 - 1f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2f */ + 0, 0, 0, 0, 0, KB_NUM_MINUS, 0, KB_SYSRQ, KB_RALT, 0, 0, 0, 0, 0, 0, 0, /* 30 - 3f */ + 0, 0, 0, 0, 0, 0, 0, KB_HOME, KB_UP, KB_PGUP, 0, KB_LEFT, 0, KB_RIGHT, 0, KB_END, /* 40 - 4f */ + KB_DOWN, KB_PGDN, KB_INSERT, KB_DEL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50 - 5f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 - 7f */ +}; + diff --git a/src/dos/timer.c b/src/dos/timer.c index d6c3b52..2440bd5 100644 --- a/src/dos/timer.c +++ b/src/dos/timer.c @@ -1,3 +1,8 @@ +/* for sound we use MIDAS, which takes over the PIT and we can't use it + * therefore only compile this file for NO_SOUND builds. + */ +#ifdef NO_SOUND + #include #include #include @@ -174,3 +179,5 @@ static void INTERRUPT timer_irq() /* send EOI to the PIC */ outp(PIC1_CMD, OCW2_EOI); } + +#endif /* NO_SOUND */ diff --git a/src/dos/vbe.c b/src/dos/vbe.c index 3ada182..05a5883 100644 --- a/src/dos/vbe.c +++ b/src/dos/vbe.c @@ -29,10 +29,10 @@ static int cur_pitch; int vbe_info(struct vbe_info *info) { - int i, num; void *lowbuf; uint16_t seg, sel; uint16_t *modeptr; + uint32_t offs; struct dpmi_regs regs = {0}; assert(sizeof *info == 512); @@ -63,7 +63,23 @@ int vbe_info(struct vbe_info *info) FIXPTR(info->product); FIXPTR(info->revstr); FIXPTR(info->modes); - FIXPTR(info->accel_modes); + /* implementations without the accel capability, will use the space taken + * by the accel_modes pointer for other data (probably video modes). We + * need to check for the capability before "fixing" this pointer, otherwise + * we'll shuffle random data. + */ + if(info->caps & VBE_ACCEL) { + FIXPTR(info->accel_modes); + } + + /* info->modes should be pointing somewhere at the end of the original + * low memory buffer. make it point at the same offset in the info + * buffer where we copied everything instead. + */ + offs = (char*)info->modes - (char*)lowbuf; + if(offs < sizeof *info) { /* this should always be true */ + info->modes = (uint16_t*)((char*)info + offs); + } modeptr = info->modes; while(*modeptr != 0xffff) { @@ -96,7 +112,6 @@ int vbe_num_modes(struct vbe_info *info) int vbe_mode_info(int mode, struct vbe_mode_info *minf) { - int i, num; void *lowbuf; uint16_t seg, sel; struct dpmi_regs regs = {0}; @@ -191,6 +206,8 @@ void vbe_print_mode_info(FILE *fp, struct vbe_mode_info *minf) if(minf->attr & VBE_ATTR_LFB) { fprintf(fp, " lfb@%lx", (unsigned long)minf->fb_addr); + } else { + fprintf(fp, " %xkb/bank", (unsigned int)minf->bank_size); } fprintf(fp, " ["); diff --git a/src/dos/watdpmi.c b/src/dos/watdpmi.c new file mode 100644 index 0000000..04d7b94 --- /dev/null +++ b/src/dos/watdpmi.c @@ -0,0 +1,59 @@ +#ifdef __WATCOMC__ +#include "cdpmi.h" + +void dpmi_real_int(int inum, struct dpmi_real_regs *regs) +{ + unsigned char int_num = (unsigned char)inum; + __asm { + mov eax, 0x300 + mov edi, regs + mov bl, int_num + mov bh, 0 + xor ecx, ecx + int 0x31 + } +} + +void *dpmi_mmap(uint32_t phys_addr, unsigned int size) +{ + uint16_t mem_high, mem_low; + uint16_t phys_high = phys_addr >> 16; + uint16_t phys_low = phys_addr & 0xffff; + uint16_t size_high = size >> 16; + uint16_t size_low = size & 0xffff; + unsigned int err, res = 0; + + __asm { + mov eax, 0x800 + mov bx, phys_high + mov cx, phys_low + mov si, size_high + mov di, size_low + int 0x31 + add res, 1 + mov err, eax + mov mem_high, bx + mov mem_low, cx + } + + if(res == 2) { + return 0; + } + return (void*)(((uint32_t)mem_high << 16) | ((uint32_t)mem_low)); +} + +void dpmi_munmap(void *addr) +{ + uint16_t mem_high = (uint32_t)addr >> 16; + uint16_t mem_low = (uint16_t)addr; + + __asm { + mov eax, 0x801 + mov bx, mem_high + mov cx, mem_low + int 0x31 + } +} +#else +int stop_gcc_crying_about_empty_translation_units = 0; +#endif /* __WATCOM__ */