From 57348c2e13f4de9e49f8428b9fec3f47f863a257 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Fri, 15 Nov 2019 04:57:54 +0200 Subject: [PATCH] more vbe --- src/3dgfx.c | 15 ++-- src/dos/vbe.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/dos/vbe.h | 41 ++++++++++ 3 files changed, 302 insertions(+), 7 deletions(-) diff --git a/src/3dgfx.c b/src/3dgfx.c index fb24c43..6737094 100644 --- a/src/3dgfx.c +++ b/src/3dgfx.c @@ -586,21 +586,22 @@ void g3d_normal(float x, float y, float z) } #define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x))) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) void g3d_color3b(unsigned char r, unsigned char g, unsigned char b) { - st->imm_curv.r = CLAMP(r, 0, 255); - st->imm_curv.g = CLAMP(g, 0, 255); - st->imm_curv.b = CLAMP(b, 0, 255); + st->imm_curv.r = MIN(r, 255); + st->imm_curv.g = MIN(g, 255); + st->imm_curv.b = MIN(b, 255); st->imm_curv.a = 255; } void g3d_color4b(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - st->imm_curv.r = CLAMP(r, 0, 255); - st->imm_curv.g = CLAMP(g, 0, 255); - st->imm_curv.b = CLAMP(b, 0, 255); - st->imm_curv.a = CLAMP(a, 0, 255); + st->imm_curv.r = MIN(r, 255); + st->imm_curv.g = MIN(g, 255); + st->imm_curv.b = MIN(b, 255); + st->imm_curv.a = MIN(a, 255); } void g3d_color3f(float r, float g, float b) diff --git a/src/dos/vbe.c b/src/dos/vbe.c index 72f4b51..f4fabdf 100644 --- a/src/dos/vbe.c +++ b/src/dos/vbe.c @@ -23,6 +23,10 @@ #define NMODES(inf) *(uint16_t*)((inf)->sig) #define NACCMODES(inf) *(uint16_t*)((inf)->sig + 2) +static int cur_pitch; +/* TODO update cur_pitch on mode-change and on setscanlen */ + + int vbe_info(struct vbe_info *info) { int i, num; @@ -248,3 +252,252 @@ int vbe_setmode_crtc(uint16_t mode, struct vbe_crtc_info *crtc) } return 0; } + +int vbe_getmode(void) +{ + struct dpmi_regs regs = {0}; + + regs.eax = 0x4f03; + dpmi_int(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + return regs.ebx & 0xffff; +} + +int vbe_state_size(unsigned int flags) +{ + struct dpmi_regs regs = {0}; + + regs.eax = 0x4f04; + regs.edx = 0; + regs.ecx = flags; + dpmi_int(0x10, ®s); + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + return (regs.ebx & 0xffff) * 64; +} + +int vbe_save(void *stbuf, int sz, unsigned int flags) +{ + void *lowbuf; + uint16_t seg, sel; + struct dpmi_regs regs = {0}; + + if(!(seg = dpmi_alloc((sz + 15) / 16, &sel))) { + return -1; + } + lowbuf = (void*)((uint32_t)seg << 4); + + regs.eax = 0x4f04; + regs.edx = 1; /* save */ + regs.ecx = flags; + regs.es = seg; + dpmi_int(0x10, ®s); + if((regs.eax & 0xffff) != 0x4f) { + dpmi_free(sel); + return -1; + } + + memcpy(stbuf, lowbuf, sz); + dpmi_free(sel); + return 0; +} + +int vbe_restore(void *stbuf, int sz, unsigned int flags) +{ + void *lowbuf; + uint16_t seg, sel; + struct dpmi_regs regs = {0}; + + if(!(seg = dpmi_alloc((sz + 15) / 16, &sel))) { + return -1; + } + lowbuf = (void*)((uint32_t)seg << 4); + + memcpy(lowbuf, stbuf, sz); + + regs.eax = 0x4f04; + regs.edx = 2; /* restore */ + regs.ecx = flags; + regs.es = seg; + dpmi_int(0x10, ®s); + dpmi_free(sel); + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + return 0; +} + +int vbe_setwin(int wid, int pos) +{ + struct dpmi_regs regs; + + if(wid & ~1) return -1; + + regs.eax = 0x4f05; + regs.ebx = wid; + regs.edx = pos; + dpmi_int(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + return 0; +} + +int vbe_getwin(int wid) +{ + struct dpmi_regs regs; + + if(wid & ~1) return -1; + + regs.eax = 0x4f05; + regs.ebx = wid; + dpmi_int(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + + return regs.edx & 0xffff; +} + +int vbe_setscanlen(int len_pix) +{ + struct dpmi_regs regs; + + regs.eax = 0x4f06; + regs.ebx = 0; /* set scanline length in pixels */ + regs.ecx = len_pix; + dpmi_int(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + + return regs.ecx; +} + +int vbe_getscanlen(void) +{ + struct dpmi_regs regs; + + regs.eax = 0x4f06; + regs.ebx = 1; /* get scanline length */ + dpmi_int(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + return regs.ecx; +} + +int vbe_getpitch(void) +{ + struct dpmi_regs regs; + + regs.eax = 0x4f06; + regs.ebx = 1; /* get scanline length */ + dpmi_int(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + return regs.ebx; +} + +int vbe_scanline_info(struct vbe_scanline_info *sinf) +{ + struct dpmi_regs regs; + + regs.eax = 0x4f06; + regs.ebx = 1; /* get scanline length */ + dpmi_int(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + + sinf->size = regs.ebx & 0xffff; + sinf->num_pixels = regs.ecx & 0xffff; + sinf->max_scanlines = regs.edx & 0xffff; + return 0; +} + +enum { + SDISP_SET = 0x00, + SDISP_GET = 0x01, + SDISP_ALTSET = 0x02, + SDISP_SET_STEREO = 0x03, + SDISP_GETSCHED = 0x04, + SDISP_STEREO_ON = 0x05, + SDISP_STEREO_OFF = 0x06, + SDISP_SET_VBLANK = 0x80, + SDISP_ALTSET_VBLANK = 0x82, + SDISP_SET_STEREO_VBLANK = 0x83 +}; + +int vbe_setdisp(int x, int y, int when) +{ + struct dpmi_regs regs; + + regs.eax = 0x4f07; + regs.ebx = (when == VBE_SWAP_VBLANK) ? SDISP_SET_VBLANK : SDISP_SET; + regs.ecx = x; + regs.edx = y; + dpmi_int(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + return 0; +} + +int vbe_swap(uint32_t voffs, int when) +{ + struct dpmi_regs regs; + int op; + + switch(when) { + case VBE_SWAP_ASYNC: + op = SDISP_ALTSET; + break; + + case VBE_SWAP_NOW: + /* XXX is this the only way? */ + return vbe_setdisp(voffs % cur_pitch, voffs / cur_pitch, when); + + case VBE_SWAP_VBLANK: + default: + op = SDISP_ALTSET_VBLANK; + break; + } + + + regs.eax = 0x4f07; + regs.ebx = op; + regs.ecx = voffs; + dpmi_int(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + return 0; +} + +int vbe_swap_pending(void) +{ + struct dpmi_regs regs; + + regs.eax = 0x4f07; + regs.ebx = SDISP_GETSCHED; + dpmi_int(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + return 0; + } + return regs.ecx; +} diff --git a/src/dos/vbe.h b/src/dos/vbe.h index 1236b28..84044e3 100644 --- a/src/dos/vbe.h +++ b/src/dos/vbe.h @@ -77,6 +77,13 @@ struct vbe_crtc_info { } PACKED; #pragma pack (pop) +/* returned by vbe_scanline_info() */ +struct vbe_scanline_info { + int size; + int num_pixels; + int max_scanlines; +}; + enum { VBE_8BIT_DAC = 0x01, VBE_NON_VGA = 0x02, @@ -188,6 +195,21 @@ enum { VBE_CRTC_VSYNC_NEG = 0x08 }; +enum { + VBE_STATE_CTRLHW = 0x01, + VBE_STATE_BIOS = 0x02, + VBE_STATE_DAC = 0x04, + VBE_STATE_REGS = 0x08, + + VBE_STATE_ALL = 0xffff +}; + +enum { + VBE_SWAP_NOW, + VBE_SWAP_VBLANK, + VBE_SWAP_ASYNC /* schedule swap and return (triple-buffering) */ +}; + int vbe_info(struct vbe_info *info); int vbe_num_modes(struct vbe_info *info); int vbe_mode_info(int mode, struct vbe_mode_info *minf); @@ -197,5 +219,24 @@ void vbe_print_mode_info(FILE *fp, struct vbe_mode_info *minf); int vbe_setmode(uint16_t mode); int vbe_setmode_crtc(uint16_t mode, struct vbe_crtc_info *crtc); +int vbe_getmode(void); + +int vbe_state_size(unsigned int flags); +int vbe_save(void *stbuf, int sz, unsigned int flags); +int vbe_restore(void *stbuf, int sz, unsigned int flags); + +int vbe_setwin(int wid, int pos); +int vbe_getwin(int wid); + +/* returns the actual length in pixels, which might not be what was requested */ +int vbe_setscanlen(int len_pix); +int vbe_getscanlen(void); +int vbe_getpitch(void); +int vbe_scanline_info(struct vbe_scanline_info *sinf); + +int vbe_setdisp(int x, int y, int when); +int vbe_swap(uint32_t voffs, int when); +int vbe_swap_pending(void); /* 0: not pending (done) or error, 1: pending swap */ +/* TODO add stereo swap */ #endif /* VBE_H_ */ -- 1.7.10.4