nuclear@0: /* nuclear@0: 256-color 3D graphics hack for real-mode DOS. nuclear@0: Copyright (C) 2011 John Tsiombikas nuclear@0: nuclear@0: This program is free software: you can redistribute it and/or modify nuclear@0: it under the terms of the GNU General Public License as published by nuclear@0: the Free Software Foundation, either version 3 of the License, or nuclear@0: (at your option) any later version. nuclear@0: nuclear@0: This program is distributed in the hope that it will be useful, nuclear@0: but WITHOUT ANY WARRANTY; without even the implied warranty of nuclear@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nuclear@0: GNU General Public License for more details. nuclear@0: nuclear@0: You should have received a copy of the GNU General Public License nuclear@0: along with this program. If not, see . nuclear@0: */ nuclear@0: nuclear@0: /* This file implements all calls made to dos-specific code using SDL nuclear@0: * Don't ask why ... nuclear@0: */ nuclear@0: nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include "vga.h" nuclear@0: #include "conio.h" nuclear@0: #include "mouse.h" nuclear@0: #include "timer.h" nuclear@0: nuclear@0: static void proc_events(void); nuclear@0: nuclear@0: /* ----- graphics (vga.c implementation) ----- */ nuclear@0: static SDL_Surface *fbsurf; nuclear@0: nuclear@0: #define DOUBLESZ (fbsurf->w != 320) nuclear@0: nuclear@0: void set_video_mode(int mode) nuclear@0: { nuclear@0: int resx = 320, resy = 200; nuclear@9: unsigned int sdl_flags = SDL_HWPALETTE; nuclear@0: nuclear@0: if(getenv("DOSEMU_DOUBLESIZE")) { nuclear@0: resx *= 2; nuclear@0: resy *= 2; nuclear@0: } nuclear@0: nuclear@9: if(getenv("DOSEMU_FULLSCREEN")) { nuclear@9: sdl_flags |= SDL_FULLSCREEN; nuclear@9: } nuclear@9: nuclear@0: switch(mode) { nuclear@0: case 0x13: nuclear@0: SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); nuclear@9: if(!(fbsurf = SDL_SetVideoMode(resx, resy, 8, sdl_flags))) { nuclear@0: fprintf(stderr, "failed to set video mode\n"); nuclear@0: abort(); nuclear@0: } nuclear@0: SDL_ShowCursor(0); nuclear@11: SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); nuclear@0: break; nuclear@0: nuclear@0: case 3: nuclear@0: SDL_ShowCursor(1); nuclear@11: SDL_EnableKeyRepeat(0, 0); nuclear@0: SDL_Quit(); nuclear@0: break; nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void set_palette(unsigned char c, unsigned char r, unsigned char g, unsigned char b) nuclear@0: { nuclear@0: SDL_Color col; nuclear@0: col.r = r; nuclear@0: col.g = g; nuclear@0: col.b = b; nuclear@0: nuclear@0: if(SDL_SetPalette(fbsurf, SDL_LOGPAL | SDL_PHYSPAL, &col, c, 1) != 1) { nuclear@0: fprintf(stderr, "set_palette failed to set the required color\n"); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void copy_frame(unsigned char *frame) nuclear@0: { nuclear@0: if(SDL_MUSTLOCK(fbsurf)) { nuclear@0: SDL_LockSurface(fbsurf); nuclear@0: } nuclear@0: nuclear@0: if(DOUBLESZ) { nuclear@0: int i, j; nuclear@0: Uint16 *dest = fbsurf->pixels; nuclear@0: nuclear@0: for(i=0; i<200; i++) { nuclear@0: for(j=0; j<320; j++) { nuclear@0: Uint16 twopix = ((Uint16)*frame << 8) | (Uint16)*frame; nuclear@0: dest[j] = dest[j + 320] = twopix; nuclear@0: frame++; nuclear@0: } nuclear@0: dest += fbsurf->pitch; nuclear@0: } nuclear@0: } else { nuclear@0: memcpy(fbsurf->pixels, frame, 64000); nuclear@0: } nuclear@0: nuclear@0: if(SDL_MUSTLOCK(fbsurf)) { nuclear@0: SDL_UnlockSurface(fbsurf); nuclear@0: } nuclear@0: SDL_Flip(fbsurf); nuclear@0: } nuclear@0: nuclear@0: void wait_vsync(void) nuclear@0: { nuclear@0: } nuclear@0: nuclear@0: /* ----- event handling (conio.h) ----- */ nuclear@0: static SDL_Event *keybev; nuclear@0: static int mousex, mousey, bnmask; nuclear@0: nuclear@0: int kbhit(void) nuclear@0: { nuclear@0: if(!keybev) { nuclear@0: proc_events(); nuclear@0: } nuclear@0: return keybev != 0; nuclear@0: } nuclear@0: nuclear@9: int getch(void) nuclear@0: { nuclear@9: int res; nuclear@0: nuclear@0: while(!keybev) { nuclear@0: SDL_Event ev; nuclear@0: SDL_WaitEvent(&ev); nuclear@0: SDL_PushEvent(&ev); nuclear@0: proc_events(); nuclear@0: } nuclear@0: res = keybev->key.keysym.sym; nuclear@0: keybev = 0; nuclear@0: return res; nuclear@0: } nuclear@0: nuclear@0: /* mouse handling (mouse.c implementation) */ nuclear@0: int have_mouse(void) nuclear@0: { nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: int read_mouse(int *xp, int *yp) nuclear@0: { nuclear@0: if(xp) *xp = mousex; nuclear@0: if(yp) *yp = mousey; nuclear@0: return bnmask; nuclear@0: } nuclear@0: nuclear@0: static void proc_events(void) nuclear@0: { nuclear@0: static SDL_Event ev; nuclear@0: nuclear@0: while(SDL_PollEvent(&ev)) { nuclear@0: switch(ev.type) { nuclear@0: case SDL_KEYDOWN: nuclear@0: keybev = &ev; nuclear@0: return; nuclear@0: nuclear@0: case SDL_MOUSEMOTION: nuclear@0: mousex = ev.motion.x; nuclear@0: mousey = ev.motion.y; nuclear@0: nuclear@0: if(DOUBLESZ) { nuclear@0: mousex /= 2; nuclear@0: mousey /= 2; nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case SDL_MOUSEBUTTONDOWN: nuclear@0: case SDL_MOUSEBUTTONUP: nuclear@0: { nuclear@0: int mask = 0; nuclear@0: switch(ev.button.button) { nuclear@0: case SDL_BUTTON_LEFT: nuclear@0: mask = MOUSE_LEFT; nuclear@0: break; nuclear@0: case SDL_BUTTON_MIDDLE: nuclear@0: mask = MOUSE_MIDDLE; nuclear@0: break; nuclear@0: case SDL_BUTTON_RIGHT: nuclear@0: mask = MOUSE_RIGHT; nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: if(!mask) { nuclear@0: break; nuclear@0: } nuclear@0: nuclear@0: if(ev.button.state == SDL_PRESSED) { nuclear@0: bnmask |= mask; nuclear@0: } else { nuclear@0: bnmask &= ~mask; nuclear@0: } nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: /* ---- timer.c implementation ---- */ nuclear@0: static Uint32 start_time; nuclear@0: nuclear@0: void init_timer(int res_hz) nuclear@0: { nuclear@0: reset_timer(); nuclear@0: } nuclear@0: nuclear@0: void reset_timer(void) nuclear@0: { nuclear@0: start_time = SDL_GetTicks(); nuclear@0: } nuclear@0: nuclear@0: unsigned long get_msec(void) nuclear@0: { nuclear@0: return (unsigned long)(SDL_GetTicks() - start_time); nuclear@0: }