--- /dev/null
+this file exists only to force this directory in the repo
fprintf(stderr, "failed to allocate G3D context\n");
return -1;
}
+ st->opt = G3D_CLIP_FRUSTUM;
st->fill_mode = POLYFILL_FLAT;
for(i=0; i<G3D_NUM_MATRICES; i++) {
g3d_viewport(0, 0, width, height);
}
+/* set the framebuffer pointer, without resetting the size */
+void g3d_framebuffer_addr(void *pixels)
+{
+ st->pixels = pixels;
+ pfill_fb.pixels = pixels;
+}
+
void g3d_viewport(int x, int y, int w, int h)
{
st->vport[0] = x;
}
/* clipping */
- for(i=0; i<6; i++) {
- memcpy(tmpv, v, vnum * sizeof *v);
-
- if(clip_frustum(v, &vnum, tmpv, vnum, i) < 0) {
- /* polygon completely outside of view volume. discard */
- vnum = 0;
- break;
+ if(st->opt & G3D_CLIP_FRUSTUM) {
+ for(i=0; i<6; i++) {
+ memcpy(tmpv, v, vnum * sizeof *v);
+
+ if(clip_frustum(v, &vnum, tmpv, vnum, i) < 0) {
+ /* polygon completely outside of view volume. discard */
+ vnum = 0;
+ break;
+ }
}
- }
- if(!vnum) continue;
+ if(!vnum) continue;
+ }
for(i=0; i<vnum; i++) {
if(v[i].w != 0.0f) {
/* g3d_enable/g3d_disable bits */
enum {
- G3D_CULL_FACE = 0x0001,
- G3D_DEPTH_TEST = 0x0002, /* XXX not implemented */
- G3D_LIGHTING = 0x0004,
- G3D_LIGHT0 = 0x0008,
- G3D_LIGHT1 = 0x0010,
- G3D_LIGHT2 = 0x0020,
- G3D_LIGHT3 = 0x0040,
- G3D_TEXTURE = 0x0080,
- G3D_BLEND = 0x0100,
- G3D_TEXTURE_GEN = 0x0200,
+ G3D_CULL_FACE = 0x000001,
+ G3D_DEPTH_TEST = 0x000002, /* XXX not implemented */
+ G3D_LIGHTING = 0x000004,
+ G3D_LIGHT0 = 0x000008,
+ G3D_LIGHT1 = 0x000010,
+ G3D_LIGHT2 = 0x000020,
+ G3D_LIGHT3 = 0x000040,
+ G3D_TEXTURE = 0x000080,
+ G3D_BLEND = 0x000100,
+ G3D_TEXTURE_GEN = 0x000200,
+ G3D_CLIP_FRUSTUM = 0x000800,/* when disabled, don't clip against the frustum */
+ G3D_CLIP_PLANE0 = 0x001000, /* user-defined 3D clipping planes XXX not impl. */
+ G3D_CLIP_PLANE1 = 0x002000,
+ G3D_CLIP_PLANE2 = 0x004000,
+ G3D_CLIP_PLANE3 = 0x008000,
G3D_ALL = 0x7fffffff
};
void g3d_destroy(void);
void g3d_framebuffer(int width, int height, void *pixels);
+void g3d_framebuffer_addr(void *pixels);
void g3d_viewport(int x, int y, int w, int h);
void g3d_enable(unsigned int opt);
#include "tinyfps.h"
#include "util.h"
-int fb_width = 320;
-int fb_height = 240;
+#define FB_WIDTH 320
+#define FB_HEIGHT 240
+
+int fb_width = FB_WIDTH;
+int fb_height = FB_HEIGHT;
int fb_bpp = 16;
uint16_t *fb_pixels, *vmem_back, *vmem_front;
unsigned long time_msec;
scr_update();
scr_draw();
+ draw_mouse_pointer(vmem_front);
+
++nframes;
}
+
+
+#define DEST(x, y) dest[(y) * FB_WIDTH + (x)]
+void draw_mouse_pointer(uint16_t *fb)
+{
+ uint16_t *dest = fb + mouse_y * FB_WIDTH + mouse_x;
+ int ylines = FB_HEIGHT - mouse_y;
+
+ switch(ylines) {
+ default:
+ case 10:
+ DEST(0, 9) = 0xffff;
+ case 9:
+ DEST(0, 8) = 0xffff;
+ DEST(1, 8) = 0xffff;
+ case 8:
+ DEST(0, 7) = 0xffff;
+ DEST(2, 7) = 0xffff;
+ DEST(1, 7) = 0;
+ case 7:
+ DEST(6, 6) = 0xffff;
+ DEST(0, 6) = 0xffff;
+ DEST(3, 6) = 0xffff;
+ DEST(4, 6) = 0xffff;
+ DEST(5, 6) = 0xffff;
+ DEST(1, 6) = 0;
+ DEST(2, 6) = 0;
+ case 6:
+ DEST(5, 5) = 0xffff;
+ DEST(0, 5) = 0xffff;
+ DEST(1, 5) = 0;
+ DEST(2, 5) = 0;
+ DEST(3, 5) = 0;
+ DEST(4, 5) = 0;
+ case 5:
+ DEST(4, 4) = 0xffff;
+ DEST(0, 4) = 0xffff;
+ DEST(1, 4) = 0;
+ DEST(2, 4) = 0;
+ DEST(3, 4) = 0;
+ case 4:
+ DEST(3, 3) = 0xffff;
+ DEST(0, 3) = 0xffff;
+ DEST(1, 3) = 0;
+ DEST(2, 3) = 0;
+ case 3:
+ DEST(2, 2) = 0xffff;
+ DEST(0, 2) = 0xffff;
+ DEST(1, 2) = 0;
+ case 2:
+ DEST(1, 1) = 0xffff;
+ DEST(0, 1) = 0xffff;
+ case 1:
+ DEST(0, 0) = 0xffff;
+ }
+}
+
static void change_screen(int idx)
{
printf("change screen %d\n", idx);
int dy = mouse_y - prev_my;
if(dx || dy) {
- if(mouse_bmask & MOUSE_LEFT) {
+ if(mouse_bmask & MOUSE_BN_LEFT) {
float p = *phi;
*theta += dx * 1.0;
p += dy * 1.0;
if(p > 90) p = 90;
*phi = p;
}
- if(mouse_bmask & MOUSE_RIGHT) {
+ if(mouse_bmask & MOUSE_BN_RIGHT) {
*dist += dy * 0.5;
if(*dist < 0) *dist = 0;
}
}
}
+
prev_mx = mouse_x;
prev_my = mouse_y;
prev_bmask = mouse_bmask;
extern unsigned int mouse_bmask;
enum {
- MOUSE_LEFT = 1,
- MOUSE_RIGHT = 2,
- MOUSE_MIDDLE = 4
+ MOUSE_BN_LEFT = 1,
+ MOUSE_BN_RIGHT = 2,
+ MOUSE_BN_MIDDLE = 4
};
extern float sball_matrix[16];
/* call each frame to get 3D viewing spherical coordinates */
void mouse_orbit_update(float *theta, float *phi, float *dist);
+void draw_mouse_pointer(uint16_t *fb);
+
#endif /* DEMO_H_ */
-#ifndef GFX_H_
-#define GFX_H_
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include "gfx.h"
#include "vbe.h"
#include "cdpmi.h"
static struct vbe_mode_info *mode_info;
static int pal_bits = 6;
+static void *vpgaddr[2];
+
+
void *set_video_mode(int xsz, int ysz, int bpp)
{
int i;
static uint16_t *modes;
uint16_t best = 0;
- unsigned int fbsize;
+ unsigned int fbsize, pgsize;
#ifdef __DJGPP__
__djgpp_nearptr_enable();
}
*/
- fbsize = xsz * ysz * mode_info->num_img_pages * (bpp / CHAR_BIT);
- return (void*)dpmi_mmap(mode_info->fb_addr, fbsize);
+ printf("avail video pages: %d\n", mode_info->num_img_pages);
+ printf("bytes per scanline: %d (%d pixels)\n", vbe_get_scanlen(VBE_SCANLEN_BYTES),
+ vbe_get_scanlen(VBE_SCANLEN_PIXELS));
+
+ pgsize = xsz * ysz * (bpp / CHAR_BIT);
+ fbsize = mode_info->num_img_pages * pgsize;
+ vpgaddr[0] = (void*)dpmi_mmap(mode_info->fb_addr, fbsize);
+
+ if(mode_info->num_img_pages > 1) {
+ vpgaddr[1] = (char*)vpgaddr[0] + pgsize;
+ } else {
+ vpgaddr[1] = 0;
+ }
+ return vpgaddr[0];
}
int set_text_mode(void)
vbe_set_palette(idx, col, 1, pal_bits);
}
+void *page_flip(int vsync)
+{
+ static int frame;
+ void *nextaddr;
+ int y, when, bufidx;
+
+ if(!vpgaddr[1]) {
+ /* page flipping not supported */
+ return 0;
+ }
+
+ bufidx = ++frame & 1;
+
+ y = bufidx ? mode_info->yres : 0;
+ nextaddr = vpgaddr[bufidx];
+
+ when = vsync ? VBE_SET_DISP_START_VBLANK : VBE_SET_DISP_START_NOW;
+ if(vbe_set_disp_start(0, y, when) == -1) {
+ return 0;
+ }
+
+ if(vsync == FLIP_VBLANK_WAIT) {
+ wait_vsync();
+ }
+ return nextaddr;
+}
+
static unsigned int make_mask(int sz, int pos)
{
unsigned int i, mask = 0;
}
return mask << pos;
}
-
-
-#endif /* GFX_H_ */
void set_palette(int idx, int r, int g, int b);
+enum {
+ FLIP_NOW,
+ FLIP_VBLANK,
+ FLIP_VBLANK_WAIT
+};
+/* page flip and return pointer to the start of the display area (front buffer) */
+void *page_flip(int vsync);
+
#ifdef __WATCOMC__
void wait_vsync(void);
#pragma aux wait_vsync = \
#include <math.h>
#include <string.h>
#include <limits.h>
+#include <assert.h>
#include <conio.h>
#include "demo.h"
#include "keyb.h"
return 1;
}
- if(!(vmem_front = set_video_mode(fb_width, fb_height, fb_bpp))) {
+ if(!(vmem_back = set_video_mode(fb_width, fb_height, fb_bpp))) {
return 1;
}
- /* TODO implement multiple video memory pages for flipping */
- vmem_back = vmem_front;
+ if(!(vmem_front = page_flip(FLIP_NOW))) {
+ fprintf(stderr, "page flipping not supported. falling back to double buffering\n");
+ vmem_front = vmem_back;
+ } else {
+ assert(vmem_back != vmem_front);
+ }
if(demo_init(argc, argv) == -1) {
set_text_mode();
void swap_buffers(void *pixels)
{
- /* TODO implement page flipping */
if(pixels) {
+ /* just memcpy to the front buffer */
if(opt.vsync) {
wait_vsync();
}
drawFps(pixels);
memcpy(vmem_front, pixels, fbsize);
+
} else {
- drawFps(vmem_back);
+ /* attempt page flipping */
+ void *next;
- if(opt.vsync) {
- wait_vsync();
+ drawFps(vmem_back);
+ if((next = page_flip(opt.vsync ? FLIP_VBLANK_WAIT : FLIP_NOW))) {
+ assert(next == vmem_back);
+ vmem_back = vmem_front;
+ vmem_front = next;
+ } else {
+ /* failed to page flip, assume we drew in the front buffer then
+ * and just wait for vsync if necessary
+ */
+ if(opt.vsync) {
+ wait_vsync();
+ }
}
}
}
}
}
+int vbe_set_disp_start(int x, int y, int when)
+{
+ struct dpmi_real_regs regs;
+
+ memset(®s, 0, sizeof regs);
+ regs.eax = 0x4f07;
+ regs.ebx = when & 0xffff;
+ regs.ecx = x & 0xffff;
+ regs.edx = y & 0xffff;
+ dpmi_real_int(0x10, ®s);
+
+ if(regs.eax == 0x100) {
+ return -1;
+ }
+ return 0;
+}
+
+int vbe_set_scanlen(int len, int mode)
+{
+ struct dpmi_real_regs regs;
+
+ memset(®s, 0, sizeof regs);
+ regs.eax = 0x4f06;
+ regs.ebx = mode;
+ regs.ecx = len & 0xffff;
+ dpmi_real_int(0x10, ®s);
+
+ if(regs.eax == 0x100) {
+ return -1;
+ }
+ return regs.ecx & 0xffff;
+}
+
+int vbe_get_scanlen(int mode)
+{
+ int res;
+ struct dpmi_real_regs regs;
+
+ memset(®s, 0, sizeof regs);
+ regs.eax = 0x4f06;
+ regs.ebx = 1;
+ dpmi_real_int(0x10, ®s);
+
+ if(regs.eax == 0x100) {
+ return -1;
+ }
+
+ if(mode == VBE_SCANLEN_PIXELS) {
+ res = regs.ecx & 0xffff;
+ } else {
+ res = regs.ebx & 0xffff;
+ }
+ return res;
+}
+
+
static unsigned int get_mask(int sz, int pos)
{
unsigned int i, mask = 0;
int vbe_set_palette_bits(int bits);
void vbe_set_palette(int idx, int *col, int count, int bits);
+#define VBE_SET_DISP_START_NOW 0
+#define VBE_SET_DISP_START_VBLANK 0x80
+int vbe_set_disp_start(int x, int y, int when);
+
+#define VBE_SCANLEN_PIXELS 0
+#define VBE_SCANLEN_BYTES 2
+int vbe_set_scanlen(int len, int mode);
+int vbe_get_scanlen(int mode);
+
void print_mode_info(FILE *fp, struct vbe_mode_info *modei);
#endif /* VBE_H_ */
#include <stdlib.h>
#include "music.h"
+
+#ifndef NO_MUSIC
#include "mikmod.h"
#ifdef __WATCOMC__
ML_RegisterLoader(&load_xm);
}
#endif
+
+#else /* NO_MUSIC */
+
+int music_open(const char *fname)
+{
+ return 0;
+}
+
+void music_close(void)
+{
+}
+
+void music_play(void)
+{
+}
+
+void music_stop(void)
+{
+}
+
+void music_update(void)
+{
+}
+
+#endif
if(pv[i].y > pv[botidx].y) botidx = i;
}
+ int winding = 0;
+ for(i=0; i<nverts; i++) {
+ int next = NEXTIDX(i);
+ winding += (pv[next].x - pv[i].x) * (pv[next].y + pv[i].y);
+ }
+
/* +1 to avoid crashing due to off-by-one rounding errors in the rasterization */
left = alloca((pfill_fb.height + 1) * sizeof *left);
right = alloca((pfill_fb.height + 1) * sizeof *right);
if(idx < sltop) sltop = idx;
/*}*/
} else {
- struct pvertex *edge = y0 > y1 ? left : right;
- uint32_t res = SCANEDGE(pv + i, pv + next, edge);
- uint32_t tmp = (res >> 16) & 0xffff;
+ struct pvertex *edge;
+ uint32_t res, tmp;
+
+ if(winding < 0) {
+ edge = y0 > y1 ? left : right;
+ } else {
+ edge = y0 > y1 ? right : left;
+ }
+ res = SCANEDGE(pv + i, pv + next, edge);
+ tmp = (res >> 16) & 0xffff;
if(tmp > slbot) slbot = tmp;
if((tmp = res & 0xffff) < sltop) {
sltop = tmp;
return 1;
}
SDL_WM_SetCaption("dosdemo/SDL", 0);
+ SDL_ShowCursor(0);
time_msec = 0;
if(demo_init(argc, argv) == -1) {
{
switch(sdlbn) {
case SDL_BUTTON_LEFT:
- return MOUSE_LEFT;
+ return MOUSE_BN_LEFT;
case SDL_BUTTON_RIGHT:
- return MOUSE_RIGHT;
+ return MOUSE_BN_RIGHT;
case SDL_BUTTON_MIDDLE:
- return MOUSE_MIDDLE;
+ return MOUSE_BN_MIDDLE;
default:
break;
}