forked from len0rd/rockbox
There are some real bugs in here, but we're drowning in warnings. Change-Id: I7c2c0eafc8426327521bdd8a3ac2d3742ac16864
1915 lines
50 KiB
C
1915 lines
50 KiB
C
/*
|
|
* An SDL replacement for BUILD's VESA code.
|
|
*
|
|
* Written by Ryan C. Gordon. (icculus@clutteredmind.org)
|
|
*
|
|
* Please do NOT harrass Ken Silverman about any code modifications
|
|
* (including this file) to BUILD.
|
|
*/
|
|
|
|
/*
|
|
* "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
|
|
* Ken Silverman's official web site: "http://www.advsys.net/ken"
|
|
* See the included license file "BUILDLIC.TXT" for license info.
|
|
* This file IS NOT A PART OF Ken Silverman's original release
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include "platform.h"
|
|
|
|
#include "lib/pluginlib_bmp.h"
|
|
#include "SDL_config.h"
|
|
|
|
#if (!defined PLATFORM_SUPPORTS_SDL)
|
|
#error This platform apparently does not use SDL. Do not compile this.
|
|
#endif
|
|
|
|
|
|
#define BUILD_NOMOUSEGRAB "BUILD_NOMOUSEGRAB"
|
|
#define BUILD_WINDOWED "BUILD_WINDOWED"
|
|
#define BUILD_SDLDEBUG "BUILD_SDLDEBUG"
|
|
#define BUILD_RENDERER "BUILD_RENDERER"
|
|
#define BUILD_GLLIBRARY "BUILD_GLLIBRARY"
|
|
#define BUILD_USERSCREENRES "BUILD_USERSCREENRES"
|
|
#define BUILD_MAXSCREENRES "BUILD_MAXSCREENRES"
|
|
#define BUILD_HALLOFMIRRORS "BUILD_HALLOFMIRRORS"
|
|
#define BUILD_GLDUMP "BUILD_GLDUMP"
|
|
#define BUILD_SDLJOYSTICK "BUILD_SDLJOYSTICK"
|
|
|
|
#include "SDL.h"
|
|
#include "build.h"
|
|
#include "display.h"
|
|
#include "fixedPoint_math.h"
|
|
#include "engine.h"
|
|
#include "network.h"
|
|
|
|
#include "mmulti_unstable.h"
|
|
#include "mmulti_stable.h"
|
|
#include "network.h"
|
|
#include "icon.h"
|
|
|
|
// NATIVE TIMER FUNCTION DECLARATION
|
|
/*
|
|
FCS: The timer section sadly uses Native high precision calls to implement timer functions.
|
|
QueryPerformanceFrequency and QueryPerformanceCounter
|
|
it seems SDL precision was not good enough (or rather using unaccurate OS functions) to replicate
|
|
a DOS timer.
|
|
*/
|
|
|
|
int TIMER_GetPlatformTicksInOneSecond(int64_t* t);
|
|
void TIMER_GetPlatformTicks(int64_t* t);
|
|
|
|
//END // NATIVE TIMER FUNCTION DECLARATION
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "draw.h"
|
|
#include "cache.h"
|
|
|
|
|
|
/*
|
|
* !!! remove the surface_end checks, for speed's sake. They are a
|
|
* !!! needed safety right now. --ryan.
|
|
*/
|
|
|
|
|
|
#define DEFAULT_MAXRESWIDTH 1600
|
|
#define DEFAULT_MAXRESHEIGHT 1200
|
|
|
|
|
|
#define UNLOCK_SURFACE_AND_RETURN if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); return;
|
|
|
|
|
|
/* !!! move these elsewhere? */
|
|
int32_t xres, yres, bytesperline, imageSize, maxpages;
|
|
uint8_t* frameplace;
|
|
|
|
//The frambuffer address
|
|
uint8_t* frameoffset;
|
|
uint8_t *screen, vesachecked;
|
|
int32_t buffermode, origbuffermode, linearmode;
|
|
uint8_t permanentupdate = 0, vgacompatible;
|
|
|
|
SDL_Surface *surface = NULL; /* This isn't static so that we can use it elsewhere AH */
|
|
|
|
static uint32_t sdl_flags = SDL_HWPALETTE;
|
|
static int32_t mouse_relative_x = 0;
|
|
static int32_t mouse_relative_y = 0;
|
|
static short mouse_buttons = 0;
|
|
static unsigned int lastkey = 0;
|
|
/* so we can make use of setcolor16()... - DDOI */
|
|
static uint8_t drawpixel_color=0;
|
|
|
|
static uint32_t scancodes[SDLK_LAST];
|
|
|
|
static int32_t last_render_ticks = 0;
|
|
int32_t total_render_time = 1;
|
|
int32_t total_rendered_frames = 0;
|
|
|
|
static char *titleNameLong = NULL;
|
|
static char *titleNameShort = NULL;
|
|
|
|
void restore256_palette (void);
|
|
void set16color_palette (void);
|
|
|
|
|
|
|
|
static void __append_sdl_surface_flag(SDL_Surface *_surface, char *str,
|
|
size_t strsize, Uint32 flag,
|
|
const char *flagstr)
|
|
{
|
|
if (_surface->flags & flag)
|
|
{
|
|
if ( (strlen(str) + strlen(flagstr)) >= (strsize - 1) )
|
|
strcpy(str + (strsize - 5), " ...");
|
|
else
|
|
strcat(str, flagstr);
|
|
} /* if */
|
|
}
|
|
|
|
|
|
#define append_sdl_surface_flag(a, b, c, fl) __append_sdl_surface_flag(a, b, c, fl, " " #fl)
|
|
#define print_tf_state(str, val) printf("%s: {%s}\n", str, (val) ? "true" : "false" )
|
|
|
|
static void output_surface_info(SDL_Surface *_surface)
|
|
{
|
|
const SDL_VideoInfo *info;
|
|
char f[256];
|
|
|
|
|
|
if (_surface == NULL)
|
|
{
|
|
printf("-WARNING- You've got a NULL screen surface!");
|
|
}
|
|
else
|
|
{
|
|
f[0] = '\0';
|
|
printf("screen surface is (%dx%dx%dbpp).\n",_surface->w, _surface->h, _surface->format->BitsPerPixel);
|
|
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SWSURFACE);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWSURFACE);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_ASYNCBLIT);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_ANYFORMAT);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWPALETTE);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_DOUBLEBUF);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_FULLSCREEN);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_OPENGL);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_OPENGLBLIT);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RESIZABLE);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_NOFRAME);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWACCEL);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SRCCOLORKEY);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RLEACCELOK);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RLEACCEL);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SRCALPHA);
|
|
append_sdl_surface_flag(_surface, f, sizeof (f), SDL_PREALLOC);
|
|
|
|
if (f[0] == '\0')
|
|
strcpy(f, " (none)");
|
|
|
|
printf("New vidmode flags:%s.\n", f);
|
|
|
|
info = SDL_GetVideoInfo();
|
|
assert(info != NULL);
|
|
/*
|
|
print_tf_state("hardware surface available", info->hw_available);
|
|
print_tf_state("window manager available", info->wm_available);
|
|
print_tf_state("accelerated hardware->hardware blits", info->blit_hw);
|
|
print_tf_state("accelerated hardware->hardware colorkey blits", info->blit_hw_CC);
|
|
print_tf_state("accelerated hardware->hardware alpha blits", info->blit_hw_A);
|
|
print_tf_state("accelerated software->hardware blits", info->blit_sw);
|
|
print_tf_state("accelerated software->hardware colorkey blits", info->blit_sw_CC);
|
|
print_tf_state("accelerated software->hardware alpha blits", info->blit_sw_A);
|
|
print_tf_state("accelerated color fills", info->blit_fill);
|
|
|
|
printf("video memory: (%d),\n", info->video_mem);
|
|
*/
|
|
}
|
|
}
|
|
|
|
|
|
static void output_driver_info(void)
|
|
{
|
|
char buffer[256];
|
|
|
|
if (SDL_VideoDriverName(buffer, sizeof (buffer)) == NULL){
|
|
printf("-WARNING- SDL_VideoDriverName() returned NULL!");
|
|
} /* if */
|
|
else
|
|
{
|
|
printf("Using SDL video driver \"%s\".", buffer);
|
|
} /* else */
|
|
} /* output_driver_info */
|
|
|
|
|
|
void* get_framebuffer(void){
|
|
return((Uint8 *) surface->pixels);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* !!! This is almost an entire copy of the original setgamemode().
|
|
* !!! Figure out what is needed for just 2D mode, and separate that
|
|
* !!! out. Then, place the original setgamemode() back into engine.c,
|
|
* !!! and remove our simple implementation (and this function.)
|
|
* !!! Just be sure to keep the non-DOS things, like the window's
|
|
* !!! titlebar caption. --ryan.
|
|
*/
|
|
static uint8_t screenalloctype = 255;
|
|
static void init_new_res_vars(int32_t davidoption)
|
|
{
|
|
int i = 0;
|
|
int j = 0;
|
|
|
|
setupmouse();
|
|
|
|
SDL_WM_SetCaption(titleNameLong, titleNameShort);
|
|
|
|
xdim = xres = surface->w;
|
|
ydim = yres = surface->h;
|
|
|
|
printf("init_new_res_vars %d %d\n",xdim,ydim);
|
|
|
|
bytesperline = surface->w;
|
|
vesachecked = 1;
|
|
vgacompatible = 1;
|
|
linearmode = 1;
|
|
qsetmode = surface->h;
|
|
activepage = visualpage = 0;
|
|
|
|
|
|
frameoffset = frameplace = (uint8_t*)surface->pixels;
|
|
|
|
if (screen != NULL)
|
|
{
|
|
if (screenalloctype == 0) kkfree((void *)screen);
|
|
if (screenalloctype == 1) suckcache((int32_t *)screen);
|
|
screen = NULL;
|
|
} /* if */
|
|
|
|
|
|
switch(vidoption)
|
|
{
|
|
case 1:i = xdim*ydim; break;
|
|
case 2: xdim = 320; ydim = 200; i = xdim*ydim; break;
|
|
|
|
default: assert(0);
|
|
}
|
|
j = ydim*4*sizeof(int32_t); /* Leave room for horizlookup&horizlookup2 */
|
|
|
|
if(horizlookup)
|
|
free(horizlookup);
|
|
|
|
if(horizlookup2)
|
|
free(horizlookup2);
|
|
|
|
horizlookup = (int32_t*)malloc(j);
|
|
horizlookup2 = (int32_t*)malloc(j);
|
|
|
|
j = 0;
|
|
|
|
//Build lookup table (X screespace -> frambuffer offset.
|
|
for(i = 0; i <= ydim; i++)
|
|
{
|
|
ylookup[i] = j;
|
|
j += bytesperline;
|
|
}
|
|
|
|
horizycent = ((ydim*4)>>1);
|
|
|
|
/* Force drawrooms to call dosetaspect & recalculate stuff */
|
|
oxyaspect = oxdimen = oviewingrange = -1;
|
|
|
|
//Let the Assembly module how many pixels to skip when drawing a column
|
|
setBytesPerLine(bytesperline);
|
|
|
|
|
|
setview(0L,0L,xdim-1,ydim-1);
|
|
|
|
setbrightness(curbrightness, palette);
|
|
|
|
if (searchx < 0) {
|
|
searchx = halfxdimen;
|
|
searchy = (ydimen>>1);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void go_to_new_vid_mode(int davidoption, int w, int h)
|
|
{
|
|
getvalidvesamodes();
|
|
SDL_ClearError();
|
|
// don't do SDL_SetVideoMode if SDL_WM_SetIcon not called. See sdl doc for SDL_WM_SetIcon
|
|
surface = SDL_SetVideoMode(w, h, 8, sdl_flags);
|
|
if (surface == NULL)
|
|
{
|
|
Error(EXIT_FAILURE, "BUILDSDL: Failed to set %dx%d video mode!\n"
|
|
"BUILDSDL: SDL_Error() says [%s].\n",
|
|
w, h, SDL_GetError());
|
|
} /* if */
|
|
|
|
output_surface_info(surface);
|
|
init_new_res_vars(davidoption); // dont be confused between vidoption (global) and davidoption
|
|
}
|
|
|
|
static __inline int sdl_mouse_button_filter(SDL_MouseButtonEvent const *event)
|
|
{
|
|
/*
|
|
* What bits BUILD expects:
|
|
* 0 left button pressed if 1
|
|
* 1 right button pressed if 1
|
|
* 2 middle button pressed if 1
|
|
*
|
|
* (That is, this is what Int 33h (AX=0x05) returns...)
|
|
*
|
|
* additionally bits 3&4 are set for the mouse wheel
|
|
*/
|
|
Uint8 button = event->button;
|
|
if (button >= sizeof (mouse_buttons) * 8)
|
|
return(0);
|
|
|
|
if (button == SDL_BUTTON_RIGHT)
|
|
button = SDL_BUTTON_MIDDLE;
|
|
else if (button == SDL_BUTTON_MIDDLE)
|
|
button = SDL_BUTTON_RIGHT;
|
|
|
|
if (((const SDL_MouseButtonEvent*)event)->state)
|
|
mouse_buttons |= 1<<(button-1);
|
|
else if (button != 4 && button != 5)
|
|
mouse_buttons ^= 1<<(button-1);
|
|
#if 0
|
|
Uint8 bmask = SDL_GetMouseState(NULL, NULL);
|
|
mouse_buttons = 0;
|
|
if (bmask & SDL_BUTTON_LMASK) mouse_buttons |= 1;
|
|
if (bmask & SDL_BUTTON_RMASK) mouse_buttons |= 2;
|
|
if (bmask & SDL_BUTTON_MMASK) mouse_buttons |= 4;
|
|
#endif
|
|
|
|
return(0);
|
|
} /* sdl_mouse_up_filter */
|
|
|
|
|
|
static int sdl_mouse_motion_filter(SDL_Event const *event)
|
|
{
|
|
if (surface == NULL)
|
|
return(0);
|
|
|
|
if (event->type == SDL_JOYBALLMOTION)
|
|
{
|
|
mouse_relative_x = event->jball.xrel/100;
|
|
mouse_relative_y = event->jball.yrel/100;
|
|
}
|
|
else
|
|
{
|
|
if (SDL_WM_GrabInput(SDL_GRAB_QUERY)==SDL_GRAB_ON)
|
|
{
|
|
mouse_relative_x += event->motion.xrel;
|
|
mouse_relative_y += event->motion.yrel;
|
|
//printf("sdl_mouse_motion_filter: mrx=%d, mry=%d, mx=%d, my=%d\n",
|
|
// mouse_relative_x, mouse_relative_y, event->motion.xrel, event->motion.yrel);
|
|
|
|
// mouse_relative_* is already reset in
|
|
// readmousexy(). It must not be
|
|
// reset here because calling this function does not mean
|
|
// we always handle the mouse.
|
|
// FIX_00001: Mouse speed is uneven and slower in windowed mode vs fullscreen mode.
|
|
}
|
|
else
|
|
mouse_relative_x = mouse_relative_y = 0;
|
|
}
|
|
|
|
return(0);
|
|
} /* sdl_mouse_motion_filter */
|
|
|
|
|
|
/*
|
|
* The windib driver can't alert us to the keypad enter key, which
|
|
* Ken's code depends on heavily. It sends it as the same key as the
|
|
* regular return key. These users will have to hit SHIFT-ENTER,
|
|
* which we check for explicitly, and give the engine a keypad enter
|
|
* enter event.
|
|
*/
|
|
static __inline int handle_keypad_enter_hack(const SDL_Event *event)
|
|
{
|
|
static int kp_enter_hack = 0;
|
|
int retval = 0;
|
|
|
|
if (event->key.keysym.sym == SDLK_RETURN)
|
|
{
|
|
if (event->key.state == SDL_PRESSED)
|
|
{
|
|
if (event->key.keysym.mod & KMOD_SHIFT)
|
|
{
|
|
kp_enter_hack = 1;
|
|
lastkey = scancodes[SDLK_KP_ENTER];
|
|
retval = 1;
|
|
} /* if */
|
|
} /* if */
|
|
|
|
else /* key released */
|
|
{
|
|
if (kp_enter_hack)
|
|
{
|
|
kp_enter_hack = 0;
|
|
lastkey = scancodes[SDLK_KP_ENTER];
|
|
retval = 1;
|
|
} /* if */
|
|
} /* if */
|
|
} /* if */
|
|
|
|
return(retval);
|
|
} /* handle_keypad_enter_hack */
|
|
|
|
void fullscreen_toggle_and_change_driver(void)
|
|
{
|
|
|
|
// FIX_00002: New Toggle Windowed/FullScreen system now simpler and will
|
|
// dynamically change for Windib or Directx driver. Windowed/Fullscreen
|
|
// toggle also made available from menu.
|
|
// Replace attempt_fullscreen_toggle(SDL_Surface **surface, Uint32 *flags)
|
|
|
|
int32_t x,y;
|
|
x = surface->w;
|
|
y = surface->h;
|
|
|
|
BFullScreen =!BFullScreen;
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
|
_platform_init(0, NULL, "Duke Nukem 3D", "Duke3D");
|
|
_setgamemode(ScreenMode,x,y);
|
|
//vscrn();
|
|
|
|
return;
|
|
}
|
|
|
|
static int sdl_key_filter(const SDL_Event *event)
|
|
{
|
|
int extended;
|
|
|
|
if ( (event->key.keysym.sym == SDLK_m) &&
|
|
(event->key.state == SDL_PRESSED) &&
|
|
(event->key.keysym.mod & KMOD_CTRL) )
|
|
{
|
|
|
|
|
|
// FIX_00005: Mouse pointer can be toggled on/off (see mouse menu or use CTRL-M)
|
|
// This is usefull to move the duke window when playing in window mode.
|
|
|
|
if (SDL_WM_GrabInput(SDL_GRAB_QUERY)==SDL_GRAB_ON)
|
|
{
|
|
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
|
SDL_ShowCursor(1);
|
|
}
|
|
else
|
|
{
|
|
SDL_WM_GrabInput(SDL_GRAB_ON);
|
|
SDL_ShowCursor(0);
|
|
}
|
|
|
|
return(0);
|
|
} /* if */
|
|
|
|
else if ( ( (event->key.keysym.sym == SDLK_RETURN) ||
|
|
(event->key.keysym.sym == SDLK_KP_ENTER) ) &&
|
|
(event->key.state == SDL_PRESSED) &&
|
|
(event->key.keysym.mod & KMOD_ALT) )
|
|
{ fullscreen_toggle_and_change_driver();
|
|
|
|
// hack to discard the ALT key...
|
|
lastkey=scancodes[SDLK_RALT]>>8; // extended
|
|
keyhandler();
|
|
lastkey=(scancodes[SDLK_RALT]&0xff)+0x80; // Simulating Key up
|
|
keyhandler();
|
|
lastkey=(scancodes[SDLK_LALT]&0xff)+0x80; // Simulating Key up (not extended)
|
|
keyhandler();
|
|
SDL_SetModState(KMOD_NONE); // SDL doesnt see we are releasing the ALT-ENTER keys
|
|
|
|
return(0);
|
|
}
|
|
|
|
if (!handle_keypad_enter_hack(event))
|
|
lastkey = scancodes[event->key.keysym.sym];
|
|
|
|
// printf("key.keysym.sym=%d\n", event->key.keysym.sym);
|
|
|
|
if (lastkey == 0x0000) /* No DOS equivalent defined. */
|
|
return(0);
|
|
|
|
extended = ((lastkey & 0xFF00) >> 8);
|
|
if (extended != 0)
|
|
{
|
|
lastkey = extended;
|
|
keyhandler();
|
|
lastkey = (scancodes[event->key.keysym.sym] & 0xFF);
|
|
} /* if */
|
|
|
|
if (event->key.state == SDL_RELEASED)
|
|
lastkey += 128; /* +128 signifies that the key is released in DOS. */
|
|
|
|
keyhandler();
|
|
return(0);
|
|
} /* sdl_key_filter */
|
|
|
|
|
|
static int root_sdl_event_filter(const SDL_Event *event)
|
|
{
|
|
switch (event->type)
|
|
{
|
|
case SDL_KEYUP:
|
|
// FIX_00003: Pause mode is now fully responsive - (Thx to Jonathon Fowler tips)
|
|
if(event->key.keysym.sym == SDLK_PAUSE)
|
|
break;
|
|
case SDL_KEYDOWN:
|
|
return(sdl_key_filter(event));
|
|
case SDL_JOYBUTTONDOWN:
|
|
case SDL_JOYBUTTONUP:
|
|
{
|
|
//Do Nothing
|
|
|
|
//printf("Joybutton UP/DOWN\n");
|
|
//return(sdl_joystick_button_filter((const SDL_MouseButtonEvent*)event));
|
|
return 0;
|
|
}
|
|
case SDL_JOYBALLMOTION:
|
|
case SDL_MOUSEMOTION:
|
|
return(sdl_mouse_motion_filter(event));
|
|
case SDL_MOUSEBUTTONUP:
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
return(sdl_mouse_button_filter((const SDL_MouseButtonEvent*)event));
|
|
case SDL_QUIT:
|
|
/* !!! rcg TEMP */
|
|
Error(EXIT_SUCCESS, "Exit through SDL\n");
|
|
default:
|
|
//printf("This event is not handled: %d\n",event->type);
|
|
break;
|
|
} /* switch */
|
|
|
|
return(1);
|
|
} /* root_sdl_event_filter */
|
|
|
|
|
|
static void handle_events(void)
|
|
{
|
|
SDL_Event event;
|
|
|
|
while(SDL_PollEvent(&event))
|
|
root_sdl_event_filter(&event);
|
|
} /* handle_events */
|
|
|
|
|
|
/* bleh...public version... */
|
|
void _handle_events(void)
|
|
{
|
|
handle_events();
|
|
} /* _handle_events */
|
|
|
|
|
|
static SDL_Joystick *joystick = NULL;
|
|
void _joystick_init(void)
|
|
{
|
|
const char *envr = getenv(BUILD_SDLJOYSTICK);
|
|
int favored = 0;
|
|
int numsticks;
|
|
int i;
|
|
|
|
if (joystick != NULL)
|
|
{
|
|
printf("Joystick appears to be already initialized.\n");
|
|
printf("...deinitializing for stick redetection...\n");
|
|
_joystick_deinit();
|
|
} /* if */
|
|
|
|
if ((envr != NULL) && (strcmp(envr, "none") == 0))
|
|
{
|
|
printf("Skipping joystick detection/initialization at user request\n");
|
|
return;
|
|
} /* if */
|
|
|
|
printf("Initializing SDL joystick subsystem...");
|
|
printf(" (export environment variable BUILD_SDLJOYSTICK=none to skip)\n");
|
|
|
|
if (SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_NOPARACHUTE) != 0)
|
|
{
|
|
printf("SDL_Init(SDL_INIT_JOYSTICK) failed: [%s].\n", SDL_GetError());
|
|
return;
|
|
} /* if */
|
|
|
|
numsticks = SDL_NumJoysticks();
|
|
printf("SDL sees %d joystick%s.\n", numsticks, numsticks == 1 ? "" : "s");
|
|
if (numsticks == 0)
|
|
return;
|
|
|
|
for (i = 0; i < numsticks; i++)
|
|
{
|
|
const char *stickname = SDL_JoystickName(i);
|
|
if ((envr != NULL) && (strcmp(envr, stickname) == 0))
|
|
favored = i;
|
|
|
|
printf("Stick #%d: [%s]\n", i, stickname);
|
|
} /* for */
|
|
|
|
printf("Using Stick #%d.", favored);
|
|
if ((envr == NULL) && (numsticks > 1))
|
|
printf("Set BUILD_SDLJOYSTICK to one of the above names to change.\n");
|
|
|
|
joystick = SDL_JoystickOpen(favored);
|
|
if (joystick == NULL)
|
|
{
|
|
printf("Joystick #%d failed to init: %s\n", favored, SDL_GetError());
|
|
return;
|
|
} /* if */
|
|
|
|
printf("Joystick initialized. %d axes, %d buttons, %d hats, %d balls.\n",
|
|
SDL_JoystickNumAxes(joystick), SDL_JoystickNumButtons(joystick),
|
|
SDL_JoystickNumHats(joystick), SDL_JoystickNumBalls(joystick));
|
|
|
|
SDL_JoystickEventState(SDL_QUERY);
|
|
} /* _joystick_init */
|
|
|
|
|
|
void _joystick_deinit(void)
|
|
{
|
|
if (joystick != NULL)
|
|
{
|
|
printf("Closing joystick device...\n");
|
|
SDL_JoystickClose(joystick);
|
|
printf("Joystick device closed. Deinitializing SDL subsystem...\n");
|
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
|
printf("SDL joystick subsystem deinitialized.\n");
|
|
joystick = NULL;
|
|
} /* if */
|
|
} /* _joystick_deinit */
|
|
|
|
|
|
int _joystick_update(void)
|
|
{
|
|
if (joystick == NULL)
|
|
return(0);
|
|
|
|
SDL_JoystickUpdate();
|
|
return(1);
|
|
} /* _joystick_update */
|
|
|
|
|
|
int _joystick_axis(int axis)
|
|
{
|
|
if (joystick == NULL)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
return(SDL_JoystickGetAxis(joystick, axis));
|
|
} /* _joystick_axis */
|
|
|
|
int _joystick_hat(int hat)
|
|
{
|
|
if (joystick == NULL)
|
|
{
|
|
return(-1);
|
|
}
|
|
|
|
return(SDL_JoystickGetHat(joystick, hat));
|
|
} /* _joystick_axis */
|
|
|
|
int _joystick_button(int button)
|
|
{
|
|
if (joystick == NULL)
|
|
return(0);
|
|
|
|
return(SDL_JoystickGetButton(joystick, button) != 0);
|
|
} /* _joystick_button */
|
|
|
|
|
|
uint8_t _readlastkeyhit(void)
|
|
{
|
|
return(lastkey);
|
|
} /* _readlastkeyhit */
|
|
|
|
|
|
|
|
#if (!defined __DATE__)
|
|
#define __DATE__ "a long, int32_t time ago"
|
|
#endif
|
|
|
|
static void output_sdl_versions(void)
|
|
{
|
|
const SDL_version *linked_ver = SDL_Linked_Version();
|
|
SDL_version compiled_ver;
|
|
|
|
SDL_VERSION(&compiled_ver);
|
|
|
|
printf("SDL display driver for the BUILD engine initializing.\n");
|
|
printf(" sdl_driver.c by Ryan C. Gordon (icculus@clutteredmind.org).\n");
|
|
printf("Compiled %s against SDL version %d.%d.%d ...\n", __DATE__,
|
|
compiled_ver.major, compiled_ver.minor, compiled_ver.patch);
|
|
printf("Linked SDL version is %d.%d.%d ...\n",
|
|
linked_ver->major, linked_ver->minor, linked_ver->patch);
|
|
} /* output_sdl_versions */
|
|
|
|
|
|
/* lousy -ansi flag. :) */
|
|
static char *string_dupe(const char *str)
|
|
{
|
|
char *retval = malloc(strlen(str) + 1);
|
|
if (retval != NULL)
|
|
strcpy(retval, str);
|
|
return(retval);
|
|
} /* string_dupe */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void _platform_init(int argc, char **argv, const char *title, const char *iconName)
|
|
{
|
|
int i;
|
|
int64_t timeElapsed;
|
|
char dummyString[4096];
|
|
|
|
// FIX_00061: "ERROR: Two players have the same random ID" too frequent cuz of internet windows times
|
|
TIMER_GetPlatformTicks(&timeElapsed);
|
|
srand(timeElapsed&0xFFFFFFFF);
|
|
|
|
Setup_UnstableNetworking();
|
|
|
|
// Look through the command line args
|
|
for(i = 0; i < argc; i++)
|
|
{
|
|
if(argv[i][0] == '-' )
|
|
{
|
|
if(strcmpi(argv[i], "-netmode_stable") == 0)
|
|
{
|
|
//fullscreen = 1;
|
|
//TODO:
|
|
//TODO ( "[Todo: handle -netmode <int>]" )
|
|
Setup_StableNetworking();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO) == -1){
|
|
Error(EXIT_FAILURE, "BUILDSDL: SDL_Init() failed!\nBUILDSDL: SDL_GetError() says \"%s\".\n", SDL_GetError());
|
|
}
|
|
|
|
|
|
// Set up the correct renderer
|
|
// Becarfull setenv can't reach dll in VC++
|
|
// A way to proceed is to integrate the SDL libs
|
|
// in the exe instead.
|
|
|
|
// FIX_00004: SDL.dll and SDL_Mixer.dll are now integrated within the exe
|
|
// (this also makes the Windib/Directx driver switching easier with SDL)
|
|
|
|
// This requires to recompile the whole sdl and sdl mixer with the lib
|
|
// switch instead of the default dll switch.
|
|
|
|
putenv("SDL_VIDEO_CENTERED=1");
|
|
|
|
if (title == NULL)
|
|
title = "BUILD";
|
|
|
|
if (iconName == NULL)
|
|
iconName = "BUILD";
|
|
|
|
titleNameLong = string_dupe(title);
|
|
titleNameShort = string_dupe(iconName);
|
|
|
|
sdl_flags = BFullScreen ? SDL_FULLSCREEN : 0;
|
|
|
|
sdl_flags |= SDL_HWPALETTE;
|
|
|
|
|
|
memset(scancodes, '\0', sizeof (scancodes));
|
|
scancodes[SDLK_ESCAPE] = 0x01;
|
|
scancodes[SDLK_1] = 0x02;
|
|
scancodes[SDLK_2] = 0x03;
|
|
scancodes[SDLK_3] = 0x04;
|
|
scancodes[SDLK_4] = 0x05;
|
|
scancodes[SDLK_5] = 0x06;
|
|
scancodes[SDLK_6] = 0x07;
|
|
scancodes[SDLK_7] = 0x08;
|
|
scancodes[SDLK_8] = 0x09;
|
|
scancodes[SDLK_9] = 0x0A;
|
|
scancodes[SDLK_0] = 0x0B;
|
|
scancodes[SDLK_MINUS] = 0x0C; /* was 0x4A */
|
|
scancodes[SDLK_EQUALS] = 0x0D; /* was 0x4E */
|
|
scancodes[SDLK_BACKSPACE] = 0x0E;
|
|
scancodes[SDLK_TAB] = 0x0F;
|
|
scancodes[SDLK_q] = 0x10;
|
|
scancodes[SDLK_w] = 0x11;
|
|
scancodes[SDLK_e] = 0x12;
|
|
scancodes[SDLK_r] = 0x13;
|
|
scancodes[SDLK_t] = 0x14;
|
|
scancodes[SDLK_y] = 0x15;
|
|
scancodes[SDLK_u] = 0x16;
|
|
scancodes[SDLK_i] = 0x17;
|
|
scancodes[SDLK_o] = 0x18;
|
|
scancodes[SDLK_p] = 0x19;
|
|
scancodes[SDLK_LEFTBRACKET] = 0x1A;
|
|
scancodes[SDLK_RIGHTBRACKET] = 0x1B;
|
|
scancodes[SDLK_RETURN] = 0x1C;
|
|
scancodes[SDLK_LCTRL] = 0x1D;
|
|
scancodes[SDLK_a] = 0x1E;
|
|
scancodes[SDLK_s] = 0x1F;
|
|
scancodes[SDLK_d] = 0x20;
|
|
scancodes[SDLK_f] = 0x21;
|
|
scancodes[SDLK_g] = 0x22;
|
|
scancodes[SDLK_h] = 0x23;
|
|
scancodes[SDLK_j] = 0x24;
|
|
scancodes[SDLK_k] = 0x25;
|
|
scancodes[SDLK_l] = 0x26;
|
|
scancodes[SDLK_SEMICOLON] = 0x27;
|
|
scancodes[SDLK_QUOTE] = 0x28;
|
|
scancodes[SDLK_BACKQUOTE] = 0x29;
|
|
scancodes[SDLK_LSHIFT] = 0x2A;
|
|
scancodes[SDLK_BACKSLASH] = 0x2B;
|
|
scancodes[SDLK_z] = 0x2C;
|
|
scancodes[SDLK_x] = 0x2D;
|
|
scancodes[SDLK_c] = 0x2E;
|
|
scancodes[SDLK_v] = 0x2F;
|
|
scancodes[SDLK_b] = 0x30;
|
|
scancodes[SDLK_n] = 0x31;
|
|
scancodes[SDLK_m] = 0x32;
|
|
scancodes[SDLK_COMMA] = 0x33;
|
|
scancodes[SDLK_PERIOD] = 0x34;
|
|
scancodes[SDLK_SLASH] = 0x35;
|
|
scancodes[SDLK_RSHIFT] = 0x36;
|
|
scancodes[SDLK_KP_MULTIPLY] = 0x37;
|
|
scancodes[SDLK_LALT] = 0x38;
|
|
scancodes[SDLK_SPACE] = 0x39;
|
|
scancodes[SDLK_CAPSLOCK] = 0x3A;
|
|
scancodes[SDLK_F1] = 0x3B;
|
|
scancodes[SDLK_F2] = 0x3C;
|
|
scancodes[SDLK_F3] = 0x3D;
|
|
scancodes[SDLK_F4] = 0x3E;
|
|
scancodes[SDLK_F5] = 0x3F;
|
|
scancodes[SDLK_F6] = 0x40;
|
|
scancodes[SDLK_F7] = 0x41;
|
|
scancodes[SDLK_F8] = 0x42;
|
|
scancodes[SDLK_F9] = 0x43;
|
|
scancodes[SDLK_F10] = 0x44;
|
|
scancodes[SDLK_NUMLOCK] = 0x45;
|
|
scancodes[SDLK_SCROLLOCK] = 0x46;
|
|
scancodes[SDLK_KP7] = 0x47;
|
|
scancodes[SDLK_KP8] = 0x48;
|
|
scancodes[SDLK_KP9] = 0x49;
|
|
scancodes[SDLK_KP_MINUS] = 0x4A;
|
|
scancodes[SDLK_KP4] = 0x4B;
|
|
scancodes[SDLK_KP5] = 0x4C;
|
|
scancodes[SDLK_KP6] = 0x4D;
|
|
scancodes[SDLK_KP_PLUS] = 0x4E;
|
|
scancodes[SDLK_KP1] = 0x4F;
|
|
scancodes[SDLK_KP2] = 0x50;
|
|
scancodes[SDLK_KP3] = 0x51;
|
|
scancodes[SDLK_KP0] = 0x52;
|
|
scancodes[SDLK_KP_PERIOD] = 0x53;
|
|
scancodes[SDLK_F11] = 0x57;
|
|
scancodes[SDLK_F12] = 0x58;
|
|
scancodes[SDLK_PAUSE] = 0x59; /* SBF - technically incorrect */
|
|
|
|
scancodes[SDLK_KP_ENTER] = 0xE01C;
|
|
scancodes[SDLK_RCTRL] = 0xE01D;
|
|
scancodes[SDLK_KP_DIVIDE] = 0xE035;
|
|
scancodes[SDLK_PRINT] = 0xE037; /* SBF - technically incorrect */
|
|
scancodes[SDLK_SYSREQ] = 0xE037; /* SBF - for windows... */
|
|
scancodes[SDLK_RALT] = 0xE038;
|
|
scancodes[SDLK_HOME] = 0xE047;
|
|
scancodes[SDLK_UP] = 0xE048;
|
|
scancodes[SDLK_PAGEUP] = 0xE049;
|
|
scancodes[SDLK_LEFT] = 0xE04B;
|
|
scancodes[SDLK_RIGHT] = 0xE04D;
|
|
scancodes[SDLK_END] = 0xE04F;
|
|
scancodes[SDLK_DOWN] = 0xE050;
|
|
scancodes[SDLK_PAGEDOWN] = 0xE051;
|
|
scancodes[SDLK_INSERT] = 0xE052;
|
|
scancodes[SDLK_DELETE] = 0xE053;
|
|
|
|
|
|
|
|
output_sdl_versions();
|
|
output_driver_info();
|
|
|
|
|
|
printf("Video Driver: '%s'.\n", SDL_VideoDriverName(dummyString, 20));
|
|
|
|
}
|
|
|
|
// Capture BMP of the current frame
|
|
int screencapture(char *filename, uint8_t inverseit)
|
|
{
|
|
// FIX_00006: better naming system for screenshots + message when pic is taken.
|
|
// Use ./screenshots folder. Screenshot code rerwritten. Faster and
|
|
// makes smaller files. Doesn't freeze or lag the game anymore.
|
|
|
|
SDL_SaveBMP(surface, filename);
|
|
return 0;
|
|
} /* screencapture */
|
|
|
|
|
|
void setvmode(int mode)
|
|
{
|
|
|
|
if (mode == 0x3) /* text mode. */
|
|
{
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
|
return;
|
|
} else
|
|
printf("setvmode(0x%x) is unsupported in SDL driver.\n", mode);
|
|
|
|
}
|
|
|
|
int32_t _setgamemode(uint8_t davidoption, int32_t daxdim, int32_t daydim)
|
|
{
|
|
int validated, i;
|
|
SDL_Surface *image;
|
|
Uint32 colorkey;
|
|
|
|
// Install icon
|
|
image = SDL_LoadBMP_RW(SDL_RWFromMem(iconBMP, iconBMP_size), 1);
|
|
colorkey = 0; // index in this image to be transparent
|
|
SDL_SetColorKey(image, SDL_SRCCOLORKEY, colorkey);
|
|
SDL_WM_SetIcon(image,NULL);
|
|
|
|
if (daxdim > MAXXDIM || daydim > MAXYDIM)
|
|
{
|
|
printf("Resolution %dx%d is too high. Changed to %dx%d\n", daxdim, daydim, MAXXDIM,MAXYDIM);
|
|
daxdim = MAXXDIM;
|
|
daydim = MAXYDIM;
|
|
}
|
|
|
|
getvalidvesamodes();
|
|
|
|
validated = 0;
|
|
for(i=0; i<validmodecnt; i++){
|
|
if(validmodexdim[i] == daxdim && validmodeydim[i] == daydim)
|
|
validated = 1;
|
|
}
|
|
|
|
if(!validated){
|
|
printf("Resolution %dx%d unsupported. Changed to 640x480\n", daxdim, daydim);
|
|
daxdim = LCD_WIDTH;
|
|
daydim = LCD_HEIGHT;
|
|
}
|
|
|
|
go_to_new_vid_mode((int) davidoption, daxdim, daydim);
|
|
|
|
qsetmode = 200;
|
|
last_render_ticks = getticks();
|
|
|
|
return(0);
|
|
} /* setgamemode */
|
|
|
|
|
|
static int get_dimensions_from_str(const char *str, int32_t *_w, int32_t *_h)
|
|
{
|
|
char *xptr = NULL;
|
|
char *ptr = NULL;
|
|
int32_t w = -1;
|
|
int32_t h = -1;
|
|
|
|
if (str == NULL)
|
|
return(0);
|
|
|
|
xptr = strchr(str, 'x');
|
|
if (xptr == NULL)
|
|
return(0);
|
|
|
|
w = strtol(str, &ptr, 10);
|
|
if (ptr != xptr)
|
|
return(0);
|
|
|
|
xptr++;
|
|
h = strtol(xptr, &ptr, 10);
|
|
if ( (*xptr == '\0') || (*ptr != '\0') )
|
|
return(0);
|
|
|
|
if ((w <= 1) || (h <= 1))
|
|
return(0);
|
|
|
|
if (_w != NULL)
|
|
*_w = w;
|
|
|
|
if (_h != NULL)
|
|
*_h = h;
|
|
|
|
return(1);
|
|
} /* get_dimensions_from_str */
|
|
|
|
|
|
static __inline void get_max_screen_res(int32_t *max_w, int32_t *max_h)
|
|
{
|
|
int32_t w = DEFAULT_MAXRESWIDTH;
|
|
int32_t h = DEFAULT_MAXRESHEIGHT;
|
|
const char *envr = getenv(BUILD_MAXSCREENRES);
|
|
|
|
if (envr != NULL)
|
|
{
|
|
if (!get_dimensions_from_str(envr, &w, &h))
|
|
{
|
|
printf("User's resolution ceiling [%s] is bogus!\n", envr);
|
|
w = DEFAULT_MAXRESWIDTH;
|
|
h = DEFAULT_MAXRESHEIGHT;
|
|
} /* if */
|
|
} /* if */
|
|
|
|
if (max_w != NULL)
|
|
*max_w = w;
|
|
|
|
if (max_h != NULL)
|
|
*max_h = h;
|
|
}
|
|
|
|
|
|
static void add_vesa_mode(const char *typestr, int w, int h)
|
|
{
|
|
//printf("Adding %s resolution (%dx%d).\n", typestr, w, h);
|
|
validmode[validmodecnt] = validmodecnt;
|
|
validmodexdim[validmodecnt] = w;
|
|
validmodeydim[validmodecnt] = h;
|
|
validmodecnt++;
|
|
} /* add_vesa_mode */
|
|
|
|
|
|
/* Let the user specify a specific mode via environment variable. */
|
|
static __inline void add_user_defined_resolution(void)
|
|
{
|
|
int32_t w;
|
|
int32_t h;
|
|
const char *envr = getenv(BUILD_USERSCREENRES);
|
|
|
|
/* rockbox hack */
|
|
add_vesa_mode("rockbox", LCD_WIDTH, LCD_HEIGHT);
|
|
add_vesa_mode("rockbox", LCD_HEIGHT, LCD_WIDTH);
|
|
|
|
|
|
if (envr == NULL)
|
|
return;
|
|
|
|
if (get_dimensions_from_str(envr, &w, &h))
|
|
add_vesa_mode("user defined", w, h);
|
|
else
|
|
printf("User defined resolution [%s] is bogus!\n", envr);
|
|
} /* add_user_defined_resolution */
|
|
|
|
|
|
static __inline SDL_Rect **get_physical_resolutions(void)
|
|
{
|
|
const SDL_VideoInfo *vidInfo = SDL_GetVideoInfo();
|
|
SDL_Rect **modes = SDL_ListModes(vidInfo->vfmt, sdl_flags | SDL_FULLSCREEN);
|
|
if (modes == NULL)
|
|
{
|
|
sdl_flags &= ~SDL_FULLSCREEN;
|
|
modes = SDL_ListModes(vidInfo->vfmt, sdl_flags); /* try without fullscreen. */
|
|
if (modes == NULL)
|
|
modes = (SDL_Rect **) -1; /* fuck it. */
|
|
} /* if */
|
|
|
|
if (modes == (SDL_Rect **) -1)
|
|
printf("Couldn't get any physical resolutions.\n");
|
|
else
|
|
{
|
|
printf("Highest physical resolution is (%dx%d).\n",
|
|
modes[0]->w, modes[0]->h);
|
|
} /* else */
|
|
|
|
return(modes);
|
|
} /* get_physical_resolutions */
|
|
|
|
|
|
static void remove_vesa_mode(int index, const char *reason)
|
|
{
|
|
int i;
|
|
|
|
assert(index < validmodecnt);
|
|
//printf("Removing resolution #%d, %dx%d [%s].\n",index, validmodexdim[index], validmodeydim[index], reason);
|
|
|
|
for (i = index; i < validmodecnt - 1; i++)
|
|
{
|
|
validmode[i] = validmode[i + 1];
|
|
validmodexdim[i] = validmodexdim[i + 1];
|
|
validmodeydim[i] = validmodeydim[i + 1];
|
|
} /* for */
|
|
|
|
validmodecnt--;
|
|
} /* remove_vesa_mode */
|
|
|
|
|
|
static __inline void cull_large_vesa_modes(void)
|
|
{
|
|
int32_t max_w;
|
|
int32_t max_h;
|
|
int i;
|
|
|
|
get_max_screen_res(&max_w, &max_h);
|
|
printf("Setting resolution ceiling to (%dx%d).\n", max_w, max_h);
|
|
|
|
for (i = 0; i < validmodecnt; i++)
|
|
{
|
|
if ((validmodexdim[i] > max_w) || (validmodeydim[i] > max_h))
|
|
{
|
|
remove_vesa_mode(i, "above resolution ceiling");
|
|
i--; /* list shrinks. */
|
|
} /* if */
|
|
} /* for */
|
|
} /* cull_large_vesa_modes */
|
|
|
|
|
|
static __inline void cull_duplicate_vesa_modes(void)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
for (i = 0; i < validmodecnt; i++){
|
|
for (j = i + 1; j < validmodecnt; j++){
|
|
if ( (validmodexdim[i] == validmodexdim[j]) &&(validmodeydim[i] == validmodeydim[j]) ){
|
|
remove_vesa_mode(j, "duplicate");
|
|
j--; /* list shrinks. */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#define swap_macro(tmp, x, y) { tmp = x; x = y; y = tmp; }
|
|
|
|
/* be sure to call cull_duplicate_vesa_modes() before calling this. */
|
|
static __inline void sort_vesa_modelist(void)
|
|
{
|
|
int i;
|
|
int sorted;
|
|
int32_t tmp;
|
|
|
|
do
|
|
{
|
|
sorted = 1;
|
|
for (i = 0; i < validmodecnt - 1; i++)
|
|
{
|
|
if ( (validmodexdim[i] >= validmodexdim[i+1]) &&
|
|
(validmodeydim[i] >= validmodeydim[i+1]) )
|
|
{
|
|
sorted = 0;
|
|
swap_macro(tmp, validmode[i], validmode[i+1]);
|
|
swap_macro(tmp, validmodexdim[i], validmodexdim[i+1]);
|
|
swap_macro(tmp, validmodeydim[i], validmodeydim[i+1]);
|
|
} /* if */
|
|
} /* for */
|
|
} while (!sorted);
|
|
} /* sort_vesa_modelist */
|
|
|
|
|
|
static __inline void cleanup_vesa_modelist(void)
|
|
{
|
|
cull_large_vesa_modes();
|
|
cull_duplicate_vesa_modes();
|
|
sort_vesa_modelist();
|
|
} /* cleanup_vesa_modelist */
|
|
|
|
|
|
static __inline void output_vesa_modelist(void)
|
|
{
|
|
char buffer[256];
|
|
char numbuf[20];
|
|
int i;
|
|
|
|
buffer[0] = '\0';
|
|
|
|
for (i = 0; i < validmodecnt; i++)
|
|
{
|
|
sprintf(numbuf, " (%dx%d)",(int32_t) validmodexdim[i], (int32_t) validmodeydim[i]);
|
|
|
|
if ( (strlen(buffer) + strlen(numbuf)) >= (sizeof (buffer) - 1) )
|
|
strcpy(buffer + (sizeof (buffer) - 5), " ...");
|
|
else
|
|
strcat(buffer, numbuf);
|
|
} /* for */
|
|
|
|
printf("Final sorted modelist:%s", buffer);
|
|
}
|
|
|
|
|
|
void getvalidvesamodes(void)
|
|
{
|
|
static int already_checked = 0;
|
|
int i;
|
|
SDL_Rect **modes = NULL;
|
|
int stdres[][2] = {
|
|
{320, 200}, {640, 350}, {640, 480},
|
|
{800, 600}, {1024, 768}
|
|
};
|
|
|
|
if (already_checked)
|
|
return;
|
|
|
|
already_checked = 1;
|
|
validmodecnt = 0;
|
|
vidoption = 1; /* !!! tmp */
|
|
|
|
/* fill in the standard resolutions... */
|
|
for (i = 0; i < sizeof (stdres) / sizeof (stdres[0]); i++)
|
|
add_vesa_mode("standard", stdres[i][0], stdres[i][1]);
|
|
|
|
/* Anything the hardware can specifically do is added now... */
|
|
modes = get_physical_resolutions();
|
|
for (i = 0; (modes != (SDL_Rect **) -1) && (modes[i] != NULL); i++)
|
|
add_vesa_mode("physical", modes[i]->w, modes[i]->h);
|
|
|
|
/* Now add specific resolutions that the user wants... */
|
|
add_user_defined_resolution();
|
|
|
|
/* get rid of dupes and bogus resolutions... */
|
|
cleanup_vesa_modelist();
|
|
|
|
/* print it out for debugging purposes... */
|
|
output_vesa_modelist();
|
|
}
|
|
|
|
uint8_t lastPalette[768];
|
|
void WriteTranslucToFile(void){
|
|
|
|
uint8_t buffer[65535*4];
|
|
uint8_t tga_header[18];
|
|
uint8_t* transPointer = transluc;
|
|
uint8_t* bufferPointer = buffer;
|
|
int i;
|
|
FILE* file;
|
|
|
|
for (i=0; i < 65535; i++) {
|
|
|
|
bufferPointer[0] = (lastPalette[(*transPointer)*3+0]) / 63.0 * 255;
|
|
bufferPointer[1] = (lastPalette[(*transPointer)*3+1]) / 63.0 * 255;
|
|
bufferPointer[2] = (lastPalette[(*transPointer)*3+2]) / 63.0 * 255;
|
|
bufferPointer[3] = 255;
|
|
|
|
printf("%d,",*transPointer);
|
|
if (i%255 ==0)
|
|
printf("\n");
|
|
|
|
transPointer +=1;
|
|
bufferPointer+=4;
|
|
}
|
|
|
|
|
|
|
|
file = fopen("/transluc.tga", "w");
|
|
|
|
memset(tga_header, 0, 18);
|
|
tga_header[2] = 2;
|
|
tga_header[12] = (256 & 0x00FF);
|
|
tga_header[13] = (256 & 0xFF00) / 256;
|
|
tga_header[14] = (256 & 0x00FF) ;
|
|
tga_header[15] =(256 & 0xFF00) / 256;
|
|
tga_header[16] = 32 ;
|
|
|
|
fwrite(&tga_header, 18, sizeof(uint8_t), file);
|
|
fwrite(buffer, 65535, 4, file);
|
|
fclose(file);
|
|
}
|
|
|
|
void WritePaletteToFile(uint8_t* palette,const char* filename,int width, int height){
|
|
|
|
uint8_t tga_header[18];
|
|
uint8_t* buffer;
|
|
uint8_t* palettePointer = palette;
|
|
uint8_t* bufferPointer ;
|
|
int i;
|
|
|
|
FILE* file = fopen(filename, "w");
|
|
|
|
|
|
memset(tga_header, 0, 18);
|
|
tga_header[2] = 2;
|
|
tga_header[12] = (width & 0x00FF);
|
|
tga_header[13] = (width & 0xFF00) / 256;
|
|
tga_header[14] = (height & 0x00FF) ;
|
|
tga_header[15] =(height & 0xFF00) / 256;
|
|
tga_header[16] = 32 ;
|
|
|
|
fwrite(&tga_header, 18, sizeof(uint8_t), file);
|
|
|
|
bufferPointer = buffer = malloc(width*height*4);
|
|
|
|
for (i = 0 ; i < width*height ; i++)
|
|
{
|
|
bufferPointer[0] = palettePointer[0] / 63.0 * 255;
|
|
bufferPointer[1] = palettePointer[1] / 63.0 * 255;
|
|
bufferPointer[2] = palettePointer[2] / 63.0 * 255;
|
|
bufferPointer[3] = 255;
|
|
|
|
bufferPointer += 4;
|
|
palettePointer+= 3;
|
|
}
|
|
|
|
fwrite(buffer, width*height, 4, file);
|
|
fclose(file);
|
|
|
|
free(buffer);
|
|
}
|
|
|
|
|
|
void WriteLastPaletteToFile(void){
|
|
WritePaletteToFile(lastPalette,"lastPalette.tga",16,16);
|
|
}
|
|
|
|
int VBE_setPalette(uint8_t *palettebuffer)
|
|
/*
|
|
* (From Ken's docs:)
|
|
* Set (num) palette palette entries starting at (start)
|
|
* palette entries are in a 4-byte format in this order:
|
|
* 0: Blue (0-63)
|
|
* 1: Green (0-63)
|
|
* 2: Red (0-63)
|
|
* 3: Reserved
|
|
*
|
|
* Naturally, the bytes are in the reverse order that SDL wants them...
|
|
* More importantly, SDL wants the color elements in a range from 0-255,
|
|
* so we do a conversion.
|
|
*/
|
|
{
|
|
SDL_Color fmt_swap[256];
|
|
SDL_Color *sdlp = fmt_swap;
|
|
uint8_t *p = palettebuffer;
|
|
int i;
|
|
//static updated=0;
|
|
|
|
//if (updated >=1 )
|
|
// return ;
|
|
|
|
//WritePaletteToFile(palettebuffer,"lastPalette.tga",16,16);
|
|
//updated++;
|
|
|
|
|
|
//CODE EXPLORATION
|
|
//Used only to write the last palette to file.
|
|
memcpy(lastPalette, palettebuffer, 768);
|
|
|
|
for (i = 0; i < 256; i++){
|
|
/* doesn't map perfectly */
|
|
sdlp->b = (Uint8) (*p << 2) | (*p >> 4);
|
|
p++;
|
|
sdlp->g = (Uint8) (*p << 2) | (*p >> 4);
|
|
p++;
|
|
sdlp->r = (Uint8) (*p << 2) | (*p >> 4);
|
|
p++;
|
|
sdlp->unused = *p++; /* This byte is unused in BUILD, too. */
|
|
sdlp++;
|
|
}
|
|
|
|
return(SDL_SetColors(surface, fmt_swap, 0, 256));
|
|
}
|
|
|
|
|
|
int VBE_getPalette(int32_t start, int32_t num, uint8_t *palettebuffer)
|
|
{
|
|
SDL_Color *sdlp = surface->format->palette->colors + start;
|
|
uint8_t *p = palettebuffer + (start * 4);
|
|
int i;
|
|
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
*p++ = (Uint8) ((((float) sdlp->b) / 255.0) * 63.0);
|
|
*p++ = (Uint8) ((((float) sdlp->g) / 255.0) * 63.0);
|
|
*p++ = (Uint8) ((((float) sdlp->r) / 255.0) * 63.0);
|
|
*p++ = sdlp->unused; /* This byte is unused in both SDL and BUILD. */
|
|
sdlp++;
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
void _uninitengine(void)
|
|
{
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
|
} /* _uninitengine */
|
|
|
|
|
|
|
|
|
|
int setupmouse(void)
|
|
{
|
|
|
|
SDL_Event event;
|
|
|
|
if (surface == NULL)
|
|
return(0);
|
|
|
|
SDL_WM_GrabInput(SDL_GRAB_ON);
|
|
SDL_ShowCursor(0);
|
|
|
|
mouse_relative_x = mouse_relative_y = 0;
|
|
|
|
/*
|
|
* this global usually gets set by BUILD, but it's a one-shot
|
|
* deal, and we may not have an SDL surface at that point. --ryan.
|
|
*/
|
|
moustat = 1;
|
|
|
|
// FIX_00063: Duke's angle changing or incorrect when using toggle fullscreen/window mode
|
|
while(SDL_PollEvent(&event)); // Empying the various pending events (especially the mouse one)
|
|
|
|
//SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
|
|
|
|
return(1);
|
|
} /* setupmouse */
|
|
|
|
|
|
void readmousexy(short *x, short *y)
|
|
{
|
|
if (x)
|
|
*x = mouse_relative_x << 2;
|
|
if (y)
|
|
*y = mouse_relative_y << 2;
|
|
|
|
mouse_relative_x = mouse_relative_y = 0;
|
|
} /* readmousexy */
|
|
|
|
|
|
void readmousebstatus(short *bstatus)
|
|
{
|
|
if (bstatus)
|
|
*bstatus = mouse_buttons;
|
|
|
|
// special wheel treatment: make it like a button click
|
|
if(mouse_buttons&8)
|
|
mouse_buttons ^= 8;
|
|
if(mouse_buttons&16)
|
|
mouse_buttons ^= 16;
|
|
|
|
} /* readmousebstatus */
|
|
|
|
|
|
void _updateScreenRect(int32_t x, int32_t y, int32_t w, int32_t h)
|
|
{
|
|
SDL_UpdateRect(surface, x, y, w, h);
|
|
}
|
|
|
|
//int counter= 0 ;
|
|
//char bmpName[256];
|
|
void _nextpage(void)
|
|
|
|
{
|
|
Uint32 ticks;
|
|
|
|
_handle_events();
|
|
|
|
|
|
SDL_UpdateRect(surface, 0, 0, 0, 0);
|
|
|
|
//sprintf(bmpName,"%d.bmp",counter++);
|
|
//SDL_SaveBMP(surface,bmpName);
|
|
|
|
|
|
//if (CLEAR_FRAMEBUFFER)
|
|
// SDL_FillRect(surface,NULL,0);
|
|
|
|
ticks = getticks();
|
|
total_render_time = (ticks - last_render_ticks);
|
|
if (total_render_time > 1000){
|
|
total_rendered_frames = 0;
|
|
total_render_time = 1;
|
|
last_render_ticks = ticks;
|
|
}
|
|
total_rendered_frames++;
|
|
}
|
|
|
|
|
|
uint8_t readpixel(uint8_t * offset)
|
|
{
|
|
return *offset;
|
|
}
|
|
|
|
void drawpixel(uint8_t * location, uint8_t pixel)
|
|
{
|
|
*location = pixel;
|
|
}
|
|
|
|
/* Fix this up The Right Way (TM) - DDOI */
|
|
void setcolor16(uint8_t col)
|
|
{
|
|
drawpixel_color = col;
|
|
}
|
|
|
|
void drawpixel16(int32_t offset)
|
|
{
|
|
drawpixel((uint8_t*)surface->pixels + offset, drawpixel_color);
|
|
} /* drawpixel16 */
|
|
|
|
|
|
void fillscreen16(int32_t offset, int32_t color, int32_t blocksize)
|
|
{
|
|
Uint8 *surface_end;
|
|
Uint8 *wanted_end;
|
|
Uint8 *pixels;
|
|
|
|
if (SDL_MUSTLOCK(surface))
|
|
SDL_LockSurface(surface);
|
|
|
|
pixels = get_framebuffer();
|
|
|
|
/* Make this function pageoffset aware - DDOI */
|
|
if (!pageoffset) {
|
|
offset = offset << 3;
|
|
offset += 640*336;
|
|
}
|
|
|
|
surface_end = (pixels + (surface->w * surface->h)) - 1;
|
|
wanted_end = (pixels + offset) + blocksize;
|
|
|
|
if (offset < 0)
|
|
offset = 0;
|
|
|
|
if (wanted_end > surface_end)
|
|
blocksize = ((uint32_t) surface_end) - ((uint32_t) pixels + offset);
|
|
|
|
memset(pixels + offset, (int) color, blocksize);
|
|
|
|
if (SDL_MUSTLOCK(surface))
|
|
SDL_UnlockSurface(surface);
|
|
|
|
_nextpage();
|
|
} /* fillscreen16 */
|
|
|
|
|
|
/* Most of this line code is taken from Abrash's "Graphics Programming Blackbook".
|
|
Remember, sharing code is A Good Thing. AH */
|
|
static __inline void DrawHorizontalRun (uint8_t **ScreenPtr, int XAdvance, int RunLength, uint8_t Color)
|
|
{
|
|
int i;
|
|
uint8_t *WorkingScreenPtr = *ScreenPtr;
|
|
|
|
for (i=0; i<RunLength; i++)
|
|
{
|
|
*WorkingScreenPtr = Color;
|
|
WorkingScreenPtr += XAdvance;
|
|
}
|
|
WorkingScreenPtr += surface->w;
|
|
*ScreenPtr = WorkingScreenPtr;
|
|
}
|
|
|
|
static __inline void DrawVerticalRun (uint8_t **ScreenPtr, int XAdvance, int RunLength, uint8_t Color)
|
|
{
|
|
int i;
|
|
uint8_t *WorkingScreenPtr = *ScreenPtr;
|
|
|
|
for (i=0; i<RunLength; i++)
|
|
{
|
|
*WorkingScreenPtr = Color;
|
|
WorkingScreenPtr += surface->w;
|
|
}
|
|
WorkingScreenPtr += XAdvance;
|
|
*ScreenPtr = WorkingScreenPtr;
|
|
}
|
|
|
|
void drawline16(int32_t XStart, int32_t YStart, int32_t XEnd, int32_t YEnd, uint8_t Color)
|
|
{
|
|
int Temp, AdjUp, AdjDown, ErrorTerm, XAdvance, XDelta, YDelta;
|
|
int WholeStep, InitialPixelCount, FinalPixelCount, i, RunLength;
|
|
uint8_t *ScreenPtr;
|
|
int32_t dx, dy;
|
|
|
|
if (SDL_MUSTLOCK(surface))
|
|
SDL_LockSurface(surface);
|
|
|
|
dx = XEnd-XStart;
|
|
dy = YEnd-YStart;
|
|
|
|
//Analyse the slope
|
|
if (dx >= 0)
|
|
{
|
|
if ((XStart > 639) || (XEnd < 0)) return;
|
|
if (XStart < 0) { if (dy) YStart += scale(0-XStart,dy,dx); XStart = 0; }
|
|
if (XEnd > 639) { if (dy) YEnd += scale(639-XEnd,dy,dx); XEnd = 639; }
|
|
}
|
|
else
|
|
{
|
|
if ((XEnd > 639) || (XStart < 0)) return;
|
|
if (XEnd < 0) { if (dy) YEnd += scale(0-XEnd,dy,dx); XEnd = 0; }
|
|
if (XStart > 639) { if (dy) YStart += scale(639-XStart,dy,dx); XStart = 639; }
|
|
}
|
|
if (dy >= 0)
|
|
{
|
|
if ((YStart >= ydim16) || (YEnd < 0)) return;
|
|
if (YStart < 0) { if (dx) XStart += scale(0-YStart,dx,dy); YStart = 0; }
|
|
if (YEnd >= ydim16) { if (dx) XEnd += scale(ydim16-1-YEnd,dx,dy); YEnd = ydim16-1; }
|
|
}
|
|
else
|
|
{
|
|
if ((YEnd >= ydim16) || (YStart < 0)) return;
|
|
if (YEnd < 0) { if (dx) XEnd += scale(0-YEnd,dx,dy); YEnd = 0; }
|
|
if (YStart >= ydim16) { if (dx) XStart += scale(ydim16-1-YStart,dx,dy); YStart = ydim16-1; }
|
|
}
|
|
|
|
/* Make sure the status bar border draws correctly - DDOI */
|
|
if (!pageoffset) { YStart += 336; YEnd += 336; }
|
|
|
|
/* We'll always draw top to bottom */
|
|
if (YStart > YEnd) {
|
|
Temp = YStart;
|
|
YStart = YEnd;
|
|
YEnd = Temp;
|
|
Temp = XStart;
|
|
XStart = XEnd;
|
|
XEnd = Temp;
|
|
}
|
|
|
|
/* Point to the bitmap address first pixel to draw */
|
|
ScreenPtr = (uint8_t *) (get_framebuffer()) + XStart + (surface->w * YStart);
|
|
|
|
/* Figure out whether we're going left or right, and how far we're going horizontally */
|
|
if ((XDelta = XEnd - XStart) < 0)
|
|
{
|
|
XAdvance = (-1);
|
|
XDelta = -XDelta;
|
|
} else {
|
|
XAdvance = 1;
|
|
}
|
|
|
|
/* Figure out how far we're going vertically */
|
|
YDelta = YEnd - YStart;
|
|
|
|
/* Special cases: Horizontal, vertical, and diagonal lines */
|
|
if (XDelta == 0)
|
|
{
|
|
for (i=0; i <= YDelta; i++)
|
|
{
|
|
*ScreenPtr = Color;
|
|
ScreenPtr += surface->w;
|
|
}
|
|
|
|
UNLOCK_SURFACE_AND_RETURN;
|
|
}
|
|
if (YDelta == 0)
|
|
{
|
|
for (i=0; i <= XDelta; i++)
|
|
{
|
|
*ScreenPtr = Color;
|
|
ScreenPtr += XAdvance;
|
|
}
|
|
UNLOCK_SURFACE_AND_RETURN;
|
|
}
|
|
if (XDelta == YDelta)
|
|
{
|
|
for (i=0; i <= XDelta; i++)
|
|
{
|
|
*ScreenPtr = Color;
|
|
ScreenPtr += XAdvance + surface->w;
|
|
}
|
|
UNLOCK_SURFACE_AND_RETURN;
|
|
}
|
|
|
|
/* Determine whether the line is X or Y major, and handle accordingly */
|
|
if (XDelta >= YDelta) /* X major line */
|
|
{
|
|
WholeStep = XDelta / YDelta;
|
|
AdjUp = (XDelta % YDelta) * 2;
|
|
AdjDown = YDelta * 2;
|
|
ErrorTerm = (XDelta % YDelta) - (YDelta * 2);
|
|
|
|
InitialPixelCount = (WholeStep / 2) + 1;
|
|
FinalPixelCount = InitialPixelCount;
|
|
|
|
if ((AdjUp == 0) && ((WholeStep & 0x01) == 0)) InitialPixelCount--;
|
|
if ((WholeStep & 0x01) != 0) ErrorTerm += YDelta;
|
|
|
|
DrawHorizontalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
|
|
|
|
for (i=0; i<(YDelta-1); i++)
|
|
{
|
|
RunLength = WholeStep;
|
|
if ((ErrorTerm += AdjUp) > 0)
|
|
{
|
|
RunLength ++;
|
|
ErrorTerm -= AdjDown;
|
|
}
|
|
|
|
DrawHorizontalRun(&ScreenPtr, XAdvance, RunLength, Color);
|
|
}
|
|
|
|
DrawHorizontalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
|
|
|
|
UNLOCK_SURFACE_AND_RETURN;
|
|
} else { /* Y major line */
|
|
WholeStep = YDelta / XDelta;
|
|
AdjUp = (YDelta % XDelta) * 2;
|
|
AdjDown = XDelta * 2;
|
|
ErrorTerm = (YDelta % XDelta) - (XDelta * 2);
|
|
InitialPixelCount = (WholeStep / 2) + 1;
|
|
FinalPixelCount = InitialPixelCount;
|
|
|
|
if ((AdjUp == 0) && ((WholeStep & 0x01) == 0)) InitialPixelCount --;
|
|
if ((WholeStep & 0x01) != 0) ErrorTerm += XDelta;
|
|
|
|
DrawVerticalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
|
|
|
|
for (i=0; i<(XDelta-1); i++)
|
|
{
|
|
RunLength = WholeStep;
|
|
if ((ErrorTerm += AdjUp) > 0)
|
|
{
|
|
RunLength ++;
|
|
ErrorTerm -= AdjDown;
|
|
}
|
|
|
|
DrawVerticalRun(&ScreenPtr, XAdvance, RunLength, Color);
|
|
}
|
|
|
|
DrawVerticalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
|
|
UNLOCK_SURFACE_AND_RETURN;
|
|
}
|
|
} /* drawline16 */
|
|
|
|
|
|
void clear2dscreen(void)
|
|
{
|
|
SDL_Rect rect;
|
|
|
|
rect.x = rect.y = 0;
|
|
rect.w = surface->w;
|
|
|
|
if (qsetmode == 350)
|
|
rect.h = 350;
|
|
else if (qsetmode == 480)
|
|
{
|
|
if (ydim16 <= 336)
|
|
rect.h = 336;
|
|
else
|
|
rect.h = 480;
|
|
} /* else if */
|
|
|
|
SDL_FillRect(surface, &rect, 0);
|
|
} /* clear2dscreen */
|
|
|
|
|
|
void _idle(void)
|
|
{
|
|
if (surface != NULL)
|
|
_handle_events();
|
|
SDL_Delay(1);
|
|
} /* _idle */
|
|
|
|
void *_getVideoBase(void)
|
|
{
|
|
return((void *) surface->pixels);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// TIMER
|
|
//=================================================================================================
|
|
|
|
|
|
|
|
|
|
// FIX_00007: game speed corrected. The game speed is now as the real
|
|
// DOS duke3d. Unloading a full 200 bullet pistol must take 45.1 sec.
|
|
// SDL timer was not fast/accurate enough and was slowing down the gameplay,
|
|
// so bad
|
|
|
|
|
|
static int64_t timerfreq=0;
|
|
static int32_t timerlastsample=0;
|
|
static int timerticspersec=0;
|
|
static void (*usertimercallback)(void) = NULL;
|
|
|
|
// This timer stuff is all Ken's idea.
|
|
|
|
//
|
|
// installusertimercallback() -- set up a callback function to be called when the timer is fired
|
|
//
|
|
void (*installusertimercallback(void (*callback)(void)))(void)
|
|
{
|
|
void (*oldtimercallback)(void);
|
|
|
|
oldtimercallback = usertimercallback;
|
|
usertimercallback = callback;
|
|
|
|
return oldtimercallback;
|
|
}
|
|
|
|
|
|
/*
|
|
inittimer() -- initialise timer
|
|
FCS: The tickspersecond parameter is a ratio value that helps replicating
|
|
oldschool DOS tick per seconds.
|
|
|
|
The way the timer work is:
|
|
float newSystemTickPerSecond = [0,1]
|
|
tickPerSecond on a DOS system = tickspersecond * newSystemTickPerSecond ;
|
|
*/
|
|
|
|
int inittimer(int tickspersecond)
|
|
{
|
|
int64_t t;
|
|
|
|
|
|
if (timerfreq) return 0; // already installed
|
|
|
|
//printf("Initialising timer, with tickPerSecond=%d\n",tickspersecond);
|
|
|
|
// OpenWatcom seems to want us to query the value into a local variable
|
|
// instead of the global 'timerfreq' or else it gets pissed with an
|
|
// access violation
|
|
if (!TIMER_GetPlatformTicksInOneSecond(&t)) {
|
|
printf("Failed fetching timer frequency\n");
|
|
return -1;
|
|
}
|
|
timerfreq = t;
|
|
timerticspersec = tickspersecond;
|
|
TIMER_GetPlatformTicks(&t);
|
|
timerlastsample = (int32_t)(t*timerticspersec / timerfreq);
|
|
|
|
usertimercallback = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// uninittimer() -- shut down timer
|
|
//
|
|
void uninittimer(void)
|
|
{
|
|
if (!timerfreq) return;
|
|
|
|
timerfreq=0;
|
|
timerticspersec = 0;
|
|
}
|
|
|
|
//
|
|
// sampletimer() -- update totalclock
|
|
//
|
|
void sampletimer(void)
|
|
{
|
|
int64_t i;
|
|
int32_t n;
|
|
|
|
if (!timerfreq) return;
|
|
|
|
TIMER_GetPlatformTicks(&i);
|
|
|
|
|
|
n = (int32_t)(i*timerticspersec / timerfreq) - timerlastsample;
|
|
if (n>0) {
|
|
totalclock += n;
|
|
timerlastsample += n;
|
|
}
|
|
|
|
if (usertimercallback) for (; n>0; n--) usertimercallback();
|
|
}
|
|
|
|
|
|
/*
|
|
getticks() -- returns the windows ticks count
|
|
FCS: This seeems to be only used in the multiplayer code
|
|
*/
|
|
uint32_t getticks(void)
|
|
{
|
|
int64_t i;
|
|
TIMER_GetPlatformTicks(&i);
|
|
return (uint32_t)(i*(int32_t)(1000)/timerfreq);
|
|
}
|
|
|
|
|
|
//
|
|
// gettimerfreq() -- returns the number of ticks per second the timer is configured to generate
|
|
//
|
|
int gettimerfreq(void)
|
|
{
|
|
return timerticspersec;
|
|
}
|
|
|
|
|
|
|
|
void initkeys(void)
|
|
{
|
|
/* does nothing in SDL. Key input handling is set up elsewhere. */
|
|
/* !!! why not here? */
|
|
}
|
|
|
|
void uninitkeys(void)
|
|
{
|
|
/* does nothing in SDL. Key input handling is set up elsewhere. */
|
|
}
|
|
|
|
int TIMER_GetPlatformTicksInOneSecond(int64_t* t)
|
|
{
|
|
*t = 1000;
|
|
return 1;
|
|
}
|
|
|
|
void TIMER_GetPlatformTicks(int64_t* t)
|
|
{
|
|
*t = SDL_GetTicks();
|
|
}
|
|
/* end of sdl_driver.c ... */
|