mirror of
https://github.com/Pecusx/libretro-atari800.git
synced 2026-05-21 21:33:56 +02:00
initial commit
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* sdl/init.c - SDL library specific port code - initialisation routines
|
||||
*
|
||||
* Copyright (c) 2012 Tomasz Krasuski
|
||||
* Copyright (C) 2012 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Atari800 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "sdl/init.h"
|
||||
#include "atari.h"
|
||||
#include "log.h"
|
||||
#include "platform.h"
|
||||
|
||||
int SDL_INIT_Initialise(void)
|
||||
{
|
||||
if (SDL_Init(0) != 0) {
|
||||
Log_print("SDL_Init FAILED: %s", SDL_GetError());
|
||||
Log_flushlog();
|
||||
return FALSE;
|
||||
}
|
||||
atexit(SDL_Quit);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SDL_INIT_Exit(void)
|
||||
{
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
double PLATFORM_Time(void)
|
||||
{
|
||||
return SDL_GetTicks() * 1e-3;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef SDL_INIT_H_
|
||||
#define SDL_INIT_H_
|
||||
|
||||
int SDL_INIT_Initialise(void);
|
||||
void SDL_INIT_Exit(void);
|
||||
|
||||
#endif /* SDL_INIT_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,16 @@
|
||||
#ifndef SDL_INPUT_H_
|
||||
#define SDL_INPUT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int SDL_INPUT_ReadConfig(char *option, char *parameters);
|
||||
void SDL_INPUT_WriteConfig(FILE *fp);
|
||||
|
||||
int SDL_INPUT_Initialise(int *argc, char *argv[]);
|
||||
void SDL_INPUT_Exit(void);
|
||||
/* Restarts input after e.g. exiting the console monitor. */
|
||||
void SDL_INPUT_Restart(void);
|
||||
|
||||
void SDL_INPUT_Mouse(void);
|
||||
|
||||
#endif /* SDL_INPUT_H_ */
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* sdl/main.c - SDL library specific port code - main interface
|
||||
*
|
||||
* Copyright (c) 2001-2002 Jacek Poplawski
|
||||
* Copyright (C) 2001-2014 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Atari800 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
Thanks to David Olofson for scaling tips!
|
||||
|
||||
TODO:
|
||||
- implement all Atari800 parameters
|
||||
- turn off fullscreen when error happen
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <SDL.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Atari800 includes */
|
||||
#include "atari.h"
|
||||
#include "../input.h"
|
||||
#include "log.h"
|
||||
#include "monitor.h"
|
||||
#include "platform.h"
|
||||
#ifdef SOUND
|
||||
#include "../sound.h"
|
||||
#endif
|
||||
#ifdef USE_UI_BASIC_ONSCREEN_KEYBOARD
|
||||
#include "akey.h"
|
||||
#include "ui_basic.h"
|
||||
#endif
|
||||
#include "videomode.h"
|
||||
#include "sdl/video.h"
|
||||
#include "sdl/input.h"
|
||||
|
||||
int PLATFORM_Configure(char *option, char *parameters)
|
||||
{
|
||||
return SDL_VIDEO_ReadConfig(option, parameters) ||
|
||||
SDL_INPUT_ReadConfig(option, parameters);
|
||||
}
|
||||
|
||||
void PLATFORM_ConfigSave(FILE *fp)
|
||||
{
|
||||
SDL_VIDEO_WriteConfig(fp);
|
||||
SDL_INPUT_WriteConfig(fp);
|
||||
}
|
||||
|
||||
int PLATFORM_Initialise(int *argc, char *argv[])
|
||||
{
|
||||
int i, j;
|
||||
int help_only = FALSE;
|
||||
|
||||
for (i = j = 1; i < *argc; i++) {
|
||||
if (strcmp(argv[i], "-help") == 0) {
|
||||
help_only = TRUE;
|
||||
}
|
||||
argv[j++] = argv[i];
|
||||
}
|
||||
*argc = j;
|
||||
|
||||
if (!help_only) {
|
||||
i = SDL_INIT_JOYSTICK
|
||||
#if HAVE_WINDOWS_H
|
||||
/* Timers are used to avoid one Windows 7 glitch, see src/sdl/input.c */
|
||||
| SDL_INIT_TIMER
|
||||
#endif /* HAVE_WINDOWS_H */
|
||||
;
|
||||
if (SDL_InitSubSystem(i) != 0) {
|
||||
Log_print("SDL_InitSubSystem FAILED: %s", SDL_GetError());
|
||||
Log_flushlog();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!SDL_VIDEO_Initialise(argc, argv)
|
||||
#ifdef SOUND
|
||||
|| !Sound_Initialise(argc, argv)
|
||||
#endif
|
||||
|| !SDL_INPUT_Initialise(argc, argv))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int PLATFORM_Exit(int run_monitor)
|
||||
{
|
||||
SDL_INPUT_Exit();
|
||||
/* If the SDL window was left not closed, it would be unusable and hanging
|
||||
for the time the monitor is active. Also, with SDL_VIDEODRIVER=directx all
|
||||
keyboard presses in console would be still fetched by the SDL window after
|
||||
leaving the monitor. To avoid the problems, close the video subsystem. */
|
||||
SDL_VIDEO_Exit();
|
||||
Log_flushlog();
|
||||
|
||||
if (run_monitor) {
|
||||
#ifdef SOUND
|
||||
Sound_Pause();
|
||||
#endif
|
||||
if (MONITOR_Run()) {
|
||||
/* Reinitialise the SDL subsystem. */
|
||||
#ifdef MONITOR_BREAK
|
||||
if (!MONITOR_break_step) /*Do not initialise videomode when stepping through code */
|
||||
#endif
|
||||
{
|
||||
SDL_VIDEO_InitSDL();
|
||||
SDL_INPUT_Restart();
|
||||
/* This call reopens the SDL window. */
|
||||
VIDEOMODE_Update();
|
||||
}
|
||||
#ifdef SOUND
|
||||
Sound_Continue();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_WINDOWS_H
|
||||
static BOOL CtrlHandler(DWORD fdwCtrlType)
|
||||
{
|
||||
switch (fdwCtrlType)
|
||||
{
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
/* Perform a normal exit. */
|
||||
Atari800_Exit(FALSE);
|
||||
case CTRL_C_EVENT:
|
||||
/* Ctrl+C is handled in atari.c */
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_WINDOWS_H */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if HAVE_WINDOWS_H
|
||||
/* Handle Windows console signals myself. If not, then closing
|
||||
the console window would cause emulator crash due to the sound
|
||||
subsystem being active. */
|
||||
if(!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
|
||||
Log_print("ERROR: Could not set console control handler");
|
||||
return 1;
|
||||
}
|
||||
#endif /* HAVE_WINDOWS_H */
|
||||
|
||||
/* initialise Atari800 core */
|
||||
if (!Atari800_Initialise(&argc, argv))
|
||||
return 3;
|
||||
|
||||
/* main loop */
|
||||
for (;;) {
|
||||
INPUT_key_code = PLATFORM_Keyboard();
|
||||
#ifdef USE_UI_BASIC_ONSCREEN_KEYBOARD
|
||||
if (INPUT_key_code == AKEY_KEYB) {
|
||||
Sound_Pause();
|
||||
UI_BASIC_in_kbui = TRUE;
|
||||
INPUT_key_code = UI_BASIC_OnScreenKeyboard(NULL, 0);
|
||||
UI_BASIC_in_kbui = FALSE;
|
||||
switch (INPUT_key_code) {
|
||||
case AKEY_OPTION: INPUT_key_consol &= (~INPUT_CONSOL_OPTION); break;
|
||||
case AKEY_SELECT: INPUT_key_consol &= (~INPUT_CONSOL_SELECT); break;
|
||||
case AKEY_START: INPUT_key_consol &= (~INPUT_CONSOL_START); break;
|
||||
}
|
||||
|
||||
Sound_Continue();
|
||||
}
|
||||
#endif
|
||||
SDL_INPUT_Mouse();
|
||||
Atari800_Frame();
|
||||
if (Atari800_display_screen)
|
||||
PLATFORM_DisplayScreen();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
vim:ts=4:sw=4:
|
||||
*/
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* sdl/palette.c - SDL library specific port code - table of display palettes
|
||||
*
|
||||
* Copyright (c) 2010 Tomasz Krasuski
|
||||
* Copyright (C) 2010 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Atari800 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "sdl/palette.h"
|
||||
#include "af80.h"
|
||||
#include "bit3.h"
|
||||
#include "config.h"
|
||||
#include "colours.h"
|
||||
#include "videomode.h"
|
||||
|
||||
SDL_PALETTE_tab_t const SDL_PALETTE_tab[VIDEOMODE_MODE_SIZE] = {
|
||||
{ Colours_table, 256 } /* Standard display */
|
||||
#if NTSC_FILTER
|
||||
,{ Colours_table, 256 } /* NTSC filter */
|
||||
#endif
|
||||
#ifdef XEP80_EMULATION
|
||||
,{ Colours_table, 256 } /* XEP80 also uses the standard palette */
|
||||
#endif
|
||||
#ifdef PBI_PROTO80
|
||||
,{ Colours_table, 256 } /* So does PBI Proto80 */
|
||||
#endif
|
||||
#ifdef AF80
|
||||
,{ AF80_palette, 16 } /* AF80 */
|
||||
#endif
|
||||
#ifdef BIT3
|
||||
,{ BIT3_palette, 2 } /* BIT3 */
|
||||
#endif
|
||||
};
|
||||
|
||||
SDL_PALETTE_buffer_t SDL_PALETTE_buffer;
|
||||
|
||||
void SDL_PALETTE_Calculate32_A8R8G8B8(void *dest, int const *palette, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
((Uint32 *)dest)[i] = 0xff000000 | palette[i];
|
||||
}
|
||||
}
|
||||
void SDL_PALETTE_Calculate32_B8G8R8A8(void *dest, int const *palette, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
int rgb = palette[i];
|
||||
((Uint32 *)dest)[i] = 0xff | ((rgb & 0x00ff0000) >> 8) | ((rgb & 0x0000ff00) << 8) | ((rgb & 0x000000ff) << 24);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_PALETTE_Calculate16_R5G6B5(void *dest, int const *palette, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
int rgb = palette[i];
|
||||
((Uint16 *)dest)[i] = ((rgb & 0x00f80000) >> 8) | ((rgb & 0x0000fc00) >> 5) | ((rgb & 0x000000f8) >> 3);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_PALETTE_Calculate16_B5G6R5(void *dest, int const *palette, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
int rgb = palette[i];
|
||||
((Uint16 *)dest)[i] = ((rgb & 0x00f80000) >> 19) | ((rgb & 0x0000fc00) >> 5) | ((rgb & 0x000000f8) << 8);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef SDL_PALETTE_H_
|
||||
#define SDL_PALETTE_H_
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "videomode.h"
|
||||
|
||||
typedef struct SDL_PALETTE_tab_t {
|
||||
int *palette;
|
||||
int size;
|
||||
} SDL_PALETTE_tab_t;
|
||||
|
||||
/* Contains pointers to palettes used by various display modes, and their sizes.
|
||||
The table is indexed by a VIDEOMODE_MODE_t value. */
|
||||
extern SDL_PALETTE_tab_t const SDL_PALETTE_tab[VIDEOMODE_MODE_SIZE];
|
||||
|
||||
typedef union SDL_PALETTE_buffer_t {
|
||||
Uint16 bpp16[256]; /* 16-bit palette */
|
||||
Uint32 bpp32[256]; /* 32-bit palette */
|
||||
|
||||
} SDL_PALETTE_buffer_t;
|
||||
|
||||
/* Holds all palette values for the currently-used pixel format (BGR, RGB,
|
||||
ARGB etc.) */
|
||||
extern SDL_PALETTE_buffer_t SDL_PALETTE_buffer;
|
||||
|
||||
void SDL_PALETTE_Calculate32_A8R8G8B8(void *dest, int const *palette, int size);
|
||||
void SDL_PALETTE_Calculate32_B8G8R8A8(void *dest, int const *palette, int size);
|
||||
void SDL_PALETTE_Calculate16_R5G6B5(void *dest, int const *palette, int size);
|
||||
void SDL_PALETTE_Calculate16_B5G6R5(void *dest, int const *palette, int size);
|
||||
|
||||
#endif /* SDL_PALETTE_H_ */
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* sdl/sound.c - SDL library specific port code - sound output
|
||||
*
|
||||
* Copyright (c) 2001-2002 Jacek Poplawski
|
||||
* Copyright (C) 2001-2013 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Atari800 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "atari.h"
|
||||
#include "log.h"
|
||||
#include "platform.h"
|
||||
#include "sound.h"
|
||||
|
||||
static void SoundCallback(void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
Sound_Callback(stream, len);
|
||||
}
|
||||
|
||||
int PLATFORM_SoundSetup(Sound_setup_t *setup)
|
||||
{
|
||||
SDL_AudioSpec desired;
|
||||
|
||||
if (Sound_enabled)
|
||||
SDL_CloseAudio();
|
||||
else if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) {
|
||||
Log_print("SDL_INIT_AUDIO FAILED: %s", SDL_GetError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
desired.freq = setup->freq;
|
||||
desired.format = setup->sample_size == 2 ? AUDIO_S16SYS : AUDIO_U8;
|
||||
desired.channels = setup->channels;
|
||||
|
||||
if (setup->buffer_frames == 0)
|
||||
/* Set buffer_frames automatically. */
|
||||
setup->buffer_frames = setup->freq / 50;
|
||||
|
||||
setup->buffer_frames = Sound_NextPow2(setup->buffer_frames);
|
||||
|
||||
desired.samples = setup->buffer_frames;
|
||||
desired.callback = SoundCallback;
|
||||
desired.userdata = NULL;
|
||||
|
||||
if (SDL_OpenAudio(&desired, NULL) < 0) {
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
return FALSE;
|
||||
}
|
||||
setup->buffer_frames = desired.samples;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void PLATFORM_SoundExit(void)
|
||||
{
|
||||
SDL_CloseAudio();
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
}
|
||||
|
||||
void PLATFORM_SoundPause(void)
|
||||
{
|
||||
SDL_PauseAudio(1);
|
||||
}
|
||||
|
||||
void PLATFORM_SoundContinue(void)
|
||||
{
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
|
||||
void PLATFORM_SoundLock(void)
|
||||
{
|
||||
SDL_LockAudio();
|
||||
}
|
||||
|
||||
void PLATFORM_SoundUnlock(void)
|
||||
{
|
||||
SDL_UnlockAudio();
|
||||
}
|
||||
@@ -0,0 +1,924 @@
|
||||
/*
|
||||
* sdl/video.c - SDL library specific port code - video display
|
||||
*
|
||||
* Copyright (c) 2001-2002 Jacek Poplawski
|
||||
* Copyright (C) 2001-2010 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Atari800 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "af80.h"
|
||||
#include "bit3.h"
|
||||
#include "artifact.h"
|
||||
#include "atari.h"
|
||||
#include "colours.h"
|
||||
#include "config.h"
|
||||
#include "filter_ntsc.h"
|
||||
#include "log.h"
|
||||
#ifdef PAL_BLENDING
|
||||
#include "pal_blending.h"
|
||||
#endif /* PAL_BLENDING */
|
||||
#include "pbi_proto80.h"
|
||||
#include "platform.h"
|
||||
#include "screen.h"
|
||||
#include "util.h"
|
||||
#include "videomode.h"
|
||||
#include "xep80.h"
|
||||
|
||||
#include "sdl/input.h"
|
||||
#include "sdl/palette.h"
|
||||
#include "sdl/video.h"
|
||||
#include "sdl/video_sw.h"
|
||||
#if HAVE_OPENGL
|
||||
#include "sdl/video_gl.h"
|
||||
#endif
|
||||
|
||||
/* This value must be set during initialisation, because on Windows BPP
|
||||
autodetection works only before the first call to SDL_SetVideoMode(). */
|
||||
int SDL_VIDEO_native_bpp;
|
||||
|
||||
int SDL_VIDEO_scanlines_percentage = 5;
|
||||
int SDL_VIDEO_interpolate_scanlines = TRUE;
|
||||
int SDL_VIDEO_width;
|
||||
int SDL_VIDEO_height;
|
||||
|
||||
VIDEOMODE_MODE_t SDL_VIDEO_current_display_mode = VIDEOMODE_MODE_NORMAL;
|
||||
|
||||
SDL_Surface *SDL_VIDEO_screen = NULL;
|
||||
|
||||
/* Desktop screen resolution is stored here on initialisation. */
|
||||
static VIDEOMODE_resolution_t desktop_resolution;
|
||||
|
||||
#if HAVE_OPENGL
|
||||
int SDL_VIDEO_opengl_available;
|
||||
int SDL_VIDEO_opengl = FALSE;
|
||||
/* Was OpenGL active previously? */
|
||||
static int currently_opengl = FALSE;
|
||||
#endif
|
||||
int SDL_VIDEO_vsync = FALSE;
|
||||
int SDL_VIDEO_vsync_available;
|
||||
|
||||
static int window_maximised = FALSE;
|
||||
|
||||
#if HAVE_WINDOWS_H
|
||||
/* Contains TRUE if the user chose a video backend by setting
|
||||
the SDL_VIDEODRIVER environment variable. */
|
||||
static int user_video_driver = FALSE;
|
||||
#endif /* HAVE_WINDOWS_H */
|
||||
|
||||
void SDL_VIDEO_UpdatePaletteLookup(VIDEOMODE_MODE_t mode, int bpp_32)
|
||||
{
|
||||
#ifdef PAL_BLENDING
|
||||
if (mode == VIDEOMODE_MODE_NORMAL && ARTIFACT_mode == ARTIFACT_PAL_BLEND)
|
||||
PAL_BLENDING_UpdateLookup();
|
||||
else
|
||||
#endif /* PAL_BLENDING */
|
||||
#ifdef NTSC_FILTER
|
||||
if (mode != VIDEOMODE_MODE_NTSC_FILTER)
|
||||
#endif
|
||||
{
|
||||
void *dest;
|
||||
if (bpp_32)
|
||||
dest = SDL_PALETTE_buffer.bpp32;
|
||||
else
|
||||
dest = SDL_PALETTE_buffer.bpp16;
|
||||
PLATFORM_MapRGB(dest, SDL_PALETTE_tab[mode].palette, SDL_PALETTE_tab[mode].size);
|
||||
}
|
||||
}
|
||||
|
||||
void PLATFORM_PaletteUpdate(void)
|
||||
{
|
||||
#ifdef NTSC_FILTER
|
||||
if (SDL_VIDEO_current_display_mode == VIDEOMODE_MODE_NTSC_FILTER)
|
||||
FILTER_NTSC_Update(FILTER_NTSC_emu);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if HAVE_OPENGL
|
||||
if (SDL_VIDEO_opengl)
|
||||
SDL_VIDEO_GL_PaletteUpdate();
|
||||
else
|
||||
#endif
|
||||
SDL_VIDEO_SW_PaletteUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void PLATFORM_GetPixelFormat(PLATFORM_pixel_format_t *format)
|
||||
{
|
||||
#if HAVE_OPENGL
|
||||
if (SDL_VIDEO_opengl)
|
||||
SDL_VIDEO_GL_GetPixelFormat(format);
|
||||
else
|
||||
#endif
|
||||
SDL_VIDEO_SW_GetPixelFormat(format);
|
||||
}
|
||||
|
||||
void PLATFORM_MapRGB(void *dest, int const *palette, int size)
|
||||
{
|
||||
#if HAVE_OPENGL
|
||||
if (SDL_VIDEO_opengl)
|
||||
SDL_VIDEO_GL_MapRGB(dest, palette, size);
|
||||
else
|
||||
#endif
|
||||
SDL_VIDEO_SW_MapRGB(dest, palette, size);
|
||||
}
|
||||
|
||||
#ifdef NTSC_FILTER
|
||||
static void UpdateNtscFilter(VIDEOMODE_MODE_t mode)
|
||||
{
|
||||
if (mode != VIDEOMODE_MODE_NTSC_FILTER && FILTER_NTSC_emu != NULL) {
|
||||
/* Turning filter off */
|
||||
FILTER_NTSC_Delete(FILTER_NTSC_emu);
|
||||
FILTER_NTSC_emu = NULL;
|
||||
#if HAVE_OPENGL
|
||||
if (SDL_VIDEO_opengl)
|
||||
SDL_VIDEO_GL_PaletteUpdate();
|
||||
else
|
||||
#endif
|
||||
SDL_VIDEO_SW_PaletteUpdate();
|
||||
}
|
||||
else if (mode == VIDEOMODE_MODE_NTSC_FILTER && FILTER_NTSC_emu == NULL) {
|
||||
/* Turning filter on */
|
||||
FILTER_NTSC_emu = FILTER_NTSC_New();
|
||||
FILTER_NTSC_Update(FILTER_NTSC_emu);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void PLATFORM_SetVideoMode(VIDEOMODE_resolution_t const *res, int windowed, VIDEOMODE_MODE_t mode, int rotate90)
|
||||
{
|
||||
/* In SDL there's really no way to determine if a window is maximised. So we use a method
|
||||
that's not 100% sure: if we notice, that the windows's horizontal size equals desktop
|
||||
resolution, then we assume that the window is maximised. This works at least on Windows
|
||||
and Linux/KDE. */
|
||||
window_maximised = windowed && res->width == desktop_resolution.width;
|
||||
|
||||
#if HAVE_WINDOWS_H
|
||||
/* On Windows, choose Windib or DirectX backend when switching between
|
||||
fullscreen<->windowed. */
|
||||
if (!user_video_driver &&
|
||||
SDL_VIDEO_screen != NULL &&
|
||||
((SDL_VIDEO_screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) == windowed) {
|
||||
if (windowed)
|
||||
SDL_putenv("SDL_VIDEODRIVER=windib");
|
||||
else
|
||||
SDL_putenv("SDL_VIDEODRIVER=directx");
|
||||
/* SDL_VIDEODRIVER is only used when initialising the video subsystem. */
|
||||
SDL_VIDEO_ReinitSDL();
|
||||
}
|
||||
#if HAVE_OPENGL
|
||||
/* Reinitialise the video subsystem when switching between software<->OpenGL
|
||||
to avoid various SDL glitches and segfaults that might appear depending on
|
||||
the type of graphics hardware. */
|
||||
else if (SDL_VIDEO_screen != NULL && SDL_VIDEO_opengl != currently_opengl)
|
||||
SDL_VIDEO_ReinitSDL();
|
||||
#endif /* HAVE_OPENGL */
|
||||
#endif /* HAVE_WINDOWS_H */
|
||||
|
||||
#if HAVE_OPENGL
|
||||
if (SDL_VIDEO_opengl) {
|
||||
if (!currently_opengl)
|
||||
SDL_VIDEO_screen = NULL;
|
||||
/* Switching to OpenGL can fail when the host machine doesn't
|
||||
support it. If so, revert to software mode. */
|
||||
if (!SDL_VIDEO_GL_SetVideoMode(res, windowed, mode, rotate90)) {
|
||||
SDL_VIDEO_GL_Cleanup();
|
||||
SDL_VIDEO_screen = NULL;
|
||||
SDL_VIDEO_opengl = SDL_VIDEO_opengl_available = FALSE;
|
||||
VIDEOMODE_Update();
|
||||
}
|
||||
} else {
|
||||
if (currently_opengl) {
|
||||
SDL_VIDEO_GL_Cleanup();
|
||||
SDL_VIDEO_screen = NULL;
|
||||
}
|
||||
SDL_VIDEO_SW_SetVideoMode(res, windowed, mode, rotate90);
|
||||
}
|
||||
currently_opengl = SDL_VIDEO_opengl;
|
||||
#else
|
||||
SDL_VIDEO_SW_SetVideoMode(res, windowed, mode, rotate90);
|
||||
#endif
|
||||
SDL_VIDEO_current_display_mode = mode;
|
||||
#ifdef NTSC_FILTER
|
||||
UpdateNtscFilter(mode);
|
||||
#endif
|
||||
PLATFORM_DisplayScreen();
|
||||
|
||||
/* For unknown reason (maybe window manager-related), when SDL_SetVideoMode
|
||||
is called twice without calling SDL_PollEvent in between, SDL may throw
|
||||
an SDL_VIDEORESIZE event. (Happens on KDE4 in windowed mode during
|
||||
initialisation of the XEP80 handler (TV system = PAL), when it switches
|
||||
between 60Hz and 50Hz modes rapidly). If this event was processed, it
|
||||
would cause another screen resize, resulting in invalid window size. To
|
||||
avoid the glitch, we ignore all pending SDL_VIDEORESIZE events after
|
||||
each screen resize. */
|
||||
for (;;) {
|
||||
SDL_Event event;
|
||||
int found = FALSE;
|
||||
SDL_PumpEvents();
|
||||
while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_VIDEORESIZE)) > 0)
|
||||
found = TRUE;
|
||||
if (!found)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VIDEOMODE_resolution_t *PLATFORM_AvailableResolutions(unsigned int *size)
|
||||
{
|
||||
SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
|
||||
VIDEOMODE_resolution_t *resolutions;
|
||||
unsigned int num_modes;
|
||||
unsigned int i;
|
||||
if (modes == (SDL_Rect**)0)
|
||||
return NULL;
|
||||
if (modes == (SDL_Rect**)-1) {
|
||||
resolutions = (VIDEOMODE_resolution_t *)Util_malloc(sizeof(VIDEOMODE_resolution_t));
|
||||
resolutions[0].width = 336;
|
||||
resolutions[0].height = 240;
|
||||
*size = 1;
|
||||
return resolutions;
|
||||
}
|
||||
/* Determine number of available modes. */
|
||||
for (num_modes = 0; modes[num_modes] != NULL; ++num_modes);
|
||||
|
||||
resolutions = (VIDEOMODE_resolution_t *)Util_malloc(num_modes * sizeof(VIDEOMODE_resolution_t));
|
||||
for (i = 0; i < num_modes; i++) {
|
||||
resolutions[i].width = modes[i]->w;
|
||||
resolutions[i].height = modes[i]->h;
|
||||
}
|
||||
*size = num_modes;
|
||||
|
||||
return resolutions;
|
||||
}
|
||||
|
||||
VIDEOMODE_resolution_t *PLATFORM_DesktopResolution(void)
|
||||
{
|
||||
/* FIXME: This function should always return the current desktop
|
||||
resolution, not a resolution stored on initialisation. */
|
||||
return &desktop_resolution;
|
||||
}
|
||||
|
||||
int PLATFORM_SupportsVideomode(VIDEOMODE_MODE_t mode, int stretch, int rotate90)
|
||||
{
|
||||
#if HAVE_OPENGL
|
||||
if (SDL_VIDEO_opengl)
|
||||
return SDL_VIDEO_GL_SupportsVideomode(mode, stretch, rotate90);
|
||||
else
|
||||
#endif
|
||||
return SDL_VIDEO_SW_SupportsVideomode(mode, stretch, rotate90);
|
||||
}
|
||||
|
||||
int PLATFORM_WindowMaximised(void)
|
||||
{
|
||||
return window_maximised;
|
||||
}
|
||||
|
||||
void PLATFORM_DisplayScreen(void)
|
||||
{
|
||||
#if HAVE_OPENGL
|
||||
if (SDL_VIDEO_opengl)
|
||||
SDL_VIDEO_GL_DisplayScreen();
|
||||
else
|
||||
#endif
|
||||
SDL_VIDEO_SW_DisplayScreen();
|
||||
}
|
||||
|
||||
int SDL_VIDEO_ReadConfig(char *option, char *parameters)
|
||||
{
|
||||
if (strcmp(option, "SCANLINES_PERCENTAGE") == 0) {
|
||||
int value = Util_sscandec(parameters);
|
||||
if (value < 0 || value > 100)
|
||||
return FALSE;
|
||||
else {
|
||||
SDL_VIDEO_scanlines_percentage = value;
|
||||
}
|
||||
}
|
||||
else if (strcmp(option, "INTERPOLATE_SCANLINES") == 0)
|
||||
return (SDL_VIDEO_interpolate_scanlines = Util_sscanbool(parameters)) != -1;
|
||||
else if (strcmp(option, "VIDEO_VSYNC") == 0)
|
||||
return (SDL_VIDEO_vsync = Util_sscanbool(parameters)) != -1;
|
||||
#if HAVE_OPENGL
|
||||
else if (strcmp(option, "VIDEO_ACCEL") == 0)
|
||||
return (currently_opengl = SDL_VIDEO_opengl = Util_sscanbool(parameters)) != -1;
|
||||
else if (SDL_VIDEO_GL_ReadConfig(option, parameters)) {
|
||||
}
|
||||
#endif /* HAVE_OPENGL */
|
||||
else if (SDL_VIDEO_SW_ReadConfig(option, parameters)) {
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SDL_VIDEO_WriteConfig(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "SCANLINES_PERCENTAGE=%d\n", SDL_VIDEO_scanlines_percentage);
|
||||
fprintf(fp, "INTERPOLATE_SCANLINES=%d\n", SDL_VIDEO_interpolate_scanlines);
|
||||
fprintf(fp, "VIDEO_VSYNC=%d\n", SDL_VIDEO_vsync);
|
||||
#if HAVE_OPENGL
|
||||
fprintf(fp, "VIDEO_ACCEL=%d\n", SDL_VIDEO_opengl);
|
||||
SDL_VIDEO_GL_WriteConfig(fp);
|
||||
#endif
|
||||
SDL_VIDEO_SW_WriteConfig(fp);
|
||||
}
|
||||
|
||||
void SDL_VIDEO_InitSDL(void)
|
||||
{
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
|
||||
Log_print("SDL_INIT_VIDEO FAILED: %s", SDL_GetError());
|
||||
Log_flushlog();
|
||||
exit(-1);
|
||||
}
|
||||
/* SDL_WM_SetIcon("/usr/local/atari800/atarixe.ICO"), NULL); */
|
||||
SDL_WM_SetCaption(Atari800_TITLE, "Atari800");
|
||||
|
||||
/* Get the desktop resolution */
|
||||
{
|
||||
SDL_VideoInfo const * const info = SDL_GetVideoInfo();
|
||||
desktop_resolution.width = info->current_w;
|
||||
desktop_resolution.height = info->current_h;
|
||||
SDL_VIDEO_native_bpp = info->vfmt->BitsPerPixel;
|
||||
}
|
||||
|
||||
#if HAVE_OPENGL
|
||||
SDL_VIDEO_GL_InitSDL();
|
||||
if (!SDL_VIDEO_opengl_available)
|
||||
currently_opengl = SDL_VIDEO_opengl = FALSE;
|
||||
#endif
|
||||
|
||||
SDL_EnableUNICODE(1);
|
||||
}
|
||||
|
||||
void SDL_VIDEO_QuitSDL(void)
|
||||
{
|
||||
if (SDL_VIDEO_screen != NULL) {
|
||||
#if HAVE_OPENGL
|
||||
if (currently_opengl)
|
||||
SDL_VIDEO_GL_Cleanup();
|
||||
#endif
|
||||
SDL_VIDEO_screen = NULL;
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_ReinitSDL(void)
|
||||
{
|
||||
SDL_VIDEO_QuitSDL();
|
||||
/* At this moment the SDL window gets destroyed but for any pressed key no SDL_KEY_UP
|
||||
event is received. We have to flush the input state manually. */
|
||||
SDL_INPUT_Restart();
|
||||
SDL_VIDEO_InitSDL();
|
||||
}
|
||||
|
||||
int SDL_VIDEO_Initialise(int *argc, char *argv[])
|
||||
{
|
||||
int i, j;
|
||||
int help_only = FALSE;
|
||||
|
||||
for (i = j = 1; i < *argc; i++) {
|
||||
int i_a = (i + 1 < *argc); /* is argument available? */
|
||||
int a_m = FALSE; /* error, argument missing! */
|
||||
if (strcmp(argv[i], "-scanlines") == 0) {
|
||||
if (i_a) {
|
||||
SDL_VIDEO_scanlines_percentage = Util_sscandec(argv[++i]);
|
||||
}
|
||||
else a_m = TRUE;
|
||||
}
|
||||
else if (strcmp(argv[i], "-scanlinesint") == 0)
|
||||
SDL_VIDEO_interpolate_scanlines = TRUE;
|
||||
else if (strcmp(argv[i], "-no-scanlinesint") == 0)
|
||||
SDL_VIDEO_interpolate_scanlines = FALSE;
|
||||
#if HAVE_OPENGL
|
||||
else if (strcmp(argv[i], "-video-accel") == 0)
|
||||
currently_opengl = SDL_VIDEO_opengl = TRUE;
|
||||
else if (strcmp(argv[i], "-no-video-accel") == 0)
|
||||
currently_opengl = SDL_VIDEO_opengl = FALSE;
|
||||
#endif /* HAVE_OPENGL */
|
||||
else if (strcmp(argv[i], "-vsync") == 0)
|
||||
SDL_VIDEO_vsync = TRUE;
|
||||
else if (strcmp(argv[i], "-no-vsync") == 0)
|
||||
SDL_VIDEO_vsync = FALSE;
|
||||
else {
|
||||
if (strcmp(argv[i], "-help") == 0) {
|
||||
help_only = TRUE;
|
||||
Log_print("\t-scanlines Set visibility of scanlines (0..100)");
|
||||
Log_print("\t-scanlinesint Enable scanlines interpolation");
|
||||
Log_print("\t-no-scanlinesint Disable scanlines interpolation");
|
||||
#if HAVE_OPENGL
|
||||
Log_print("\t-video-accel Use hardware video acceleration");
|
||||
Log_print("\t-no-video-accel Don't use hardware video acceleration");
|
||||
#endif /* HAVE_OPENGL */
|
||||
Log_print("\t-vsync Synchronize display to vertical retrace");
|
||||
Log_print("\t-no-vsync Don't synchronize display to vertical retrace");
|
||||
}
|
||||
argv[j++] = argv[i];
|
||||
}
|
||||
|
||||
if (a_m) {
|
||||
Log_print("Missing argument for '%s'", argv[i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
*argc = j;
|
||||
|
||||
if (!SDL_VIDEO_SW_Initialise(argc, argv)
|
||||
#if HAVE_OPENGL
|
||||
|| !SDL_VIDEO_GL_Initialise(argc, argv)
|
||||
#endif
|
||||
)
|
||||
return FALSE;
|
||||
|
||||
if (!help_only) {
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
/* On Windows the DirectX SDL backend is glitchy in windowed modes, but allows
|
||||
for vertical synchronisation in fullscreen modes. Unless the user specified
|
||||
his own backend, use DirectX in fullscreen modes and Windib in windowed modes. */
|
||||
if (SDL_getenv("SDL_VIDEODRIVER") != NULL)
|
||||
user_video_driver = TRUE;
|
||||
else if (VIDEOMODE_windowed)
|
||||
SDL_putenv("SDL_VIDEODRIVER=windib");
|
||||
else
|
||||
SDL_putenv("SDL_VIDEODRIVER=directx");
|
||||
#endif /* HAVE_WINDOWS_H */
|
||||
SDL_VIDEO_InitSDL();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SDL_VIDEO_Exit(void)
|
||||
{
|
||||
SDL_VIDEO_QuitSDL();
|
||||
#ifdef NTSC_FILTER
|
||||
if (FILTER_NTSC_emu)
|
||||
#endif
|
||||
{
|
||||
/* Turning filter off */
|
||||
FILTER_NTSC_Delete(FILTER_NTSC_emu);
|
||||
FILTER_NTSC_emu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitNormal8(Uint32 *dest, Uint8 *src, int pitch, int width, int height)
|
||||
{
|
||||
register Uint32 *start32 = dest;
|
||||
while (height > 0) {
|
||||
memcpy(start32, src, width);
|
||||
src += Screen_WIDTH;
|
||||
start32 += pitch;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitNormal16(Uint32 *dest, Uint8 *src, int pitch, int width, int height, Uint16 *palette16)
|
||||
{
|
||||
register Uint32 quad;
|
||||
register Uint32 *start32 = dest;
|
||||
register Uint8 c;
|
||||
register int pos;
|
||||
int width_32;
|
||||
if (width & 0x01)
|
||||
width_32 = width + 1;
|
||||
else
|
||||
width_32 = width;
|
||||
while (height > 0) {
|
||||
pos = width_32;
|
||||
do {
|
||||
pos--;
|
||||
c = src[pos];
|
||||
quad = palette16[c] << 16;
|
||||
pos--;
|
||||
c = src[pos];
|
||||
quad += palette16[c];
|
||||
start32[pos >> 1] = quad;
|
||||
} while (pos > 0);
|
||||
src += Screen_WIDTH;
|
||||
start32 += pitch;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitNormal32(Uint32 *dest, Uint8 *src, int pitch, int width, int height, Uint32 *palette32)
|
||||
{
|
||||
register Uint32 quad;
|
||||
register Uint32 *start32 = dest;
|
||||
register Uint8 c;
|
||||
register int pos;
|
||||
while (height > 0) {
|
||||
pos = width;
|
||||
do {
|
||||
pos--;
|
||||
c = src[pos];
|
||||
quad = palette32[c];
|
||||
start32[pos] = quad;
|
||||
} while (pos > 0);
|
||||
src += Screen_WIDTH;
|
||||
start32 += pitch;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitXEP80_8(Uint32 *dest, Uint8 *src, int pitch, int width, int height)
|
||||
{
|
||||
register Uint32 *start32 = dest;
|
||||
while (height > 0) {
|
||||
memcpy(start32, src, width);
|
||||
start32 += pitch;
|
||||
src += XEP80_SCRN_WIDTH;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitXEP80_16(Uint32 *dest, Uint8 *src, int pitch, int width, int height, Uint16 *palette16)
|
||||
{
|
||||
register Uint32 quad;
|
||||
register Uint32 *start32 = dest;
|
||||
register Uint8 c;
|
||||
register int pos;
|
||||
int width_32;
|
||||
if (width & 0x01)
|
||||
width_32 = width + 1;
|
||||
else
|
||||
width_32 = width;
|
||||
while (height > 0) {
|
||||
pos = width_32;
|
||||
do {
|
||||
pos--;
|
||||
c = src[pos];
|
||||
quad = palette16[c] << 16;
|
||||
pos--;
|
||||
c = src[pos];
|
||||
quad += palette16[c];
|
||||
start32[pos >> 1] = quad;
|
||||
} while (pos > 0);
|
||||
src += XEP80_SCRN_WIDTH;
|
||||
start32 += pitch;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitXEP80_32(Uint32 *dest, Uint8 *src, int pitch, int width, int height, Uint32 *palette32)
|
||||
{
|
||||
register Uint32 quad;
|
||||
register Uint32 *start32 = dest;
|
||||
register Uint8 c;
|
||||
register int pos;
|
||||
while (height > 0) {
|
||||
pos = width;
|
||||
do {
|
||||
pos--;
|
||||
c = src[pos];
|
||||
quad = palette32[c];
|
||||
start32[pos] = quad;
|
||||
} while (pos > 0);
|
||||
src += XEP80_SCRN_WIDTH;
|
||||
start32 += pitch;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitProto80_8(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line)
|
||||
{
|
||||
int skip = pitch - (last_column - first_column)*2;
|
||||
register Uint32 *start32 = dest;
|
||||
unsigned int column;
|
||||
UBYTE pixels;
|
||||
register Uint32 quad;
|
||||
for (; first_line < last_line; first_line++) {
|
||||
for (column = first_column; column < last_column; column++) {
|
||||
int i;
|
||||
pixels = PBI_PROTO80_GetPixels(first_line, column);
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (pixels & 0x80)
|
||||
quad = 0x0000000f;
|
||||
else
|
||||
quad = 0x00000000;
|
||||
if (pixels & 0x40)
|
||||
quad |= 0x00000f00;
|
||||
if (pixels & 0x20)
|
||||
quad |= 0x000f0000;
|
||||
if (pixels & 0x10)
|
||||
quad |= 0x0f000000;
|
||||
*start32++ = quad;
|
||||
pixels <<= 4;
|
||||
}
|
||||
}
|
||||
start32 += skip;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitProto80_16(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, Uint16 *palette16)
|
||||
{
|
||||
Uint32 const black = (Uint32)palette16[0];
|
||||
Uint32 const white = (Uint32)palette16[15];
|
||||
Uint32 const black2 = black << 16;
|
||||
Uint32 const white2 = white << 16;
|
||||
int skip = pitch - (last_column - first_column)*4;
|
||||
register Uint32 *start32 = dest;
|
||||
unsigned int column;
|
||||
UBYTE pixels;
|
||||
register Uint32 quad;
|
||||
for (; first_line < last_line; first_line++) {
|
||||
for (column = first_column; column < last_column; column++) {
|
||||
int i;
|
||||
pixels = PBI_PROTO80_GetPixels(first_line, column);
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (pixels & 0x80)
|
||||
quad = white;
|
||||
else
|
||||
quad = black;
|
||||
if (pixels & 0x40)
|
||||
quad |= white2;
|
||||
else
|
||||
quad |= black2;
|
||||
*start32++ = quad;
|
||||
pixels <<= 2;
|
||||
}
|
||||
}
|
||||
start32 += skip;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitProto80_32(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, Uint32 *palette32)
|
||||
{
|
||||
Uint32 const black = palette32[0];
|
||||
Uint32 const white = palette32[15];
|
||||
int skip = pitch - (last_column - first_column)*8;
|
||||
register Uint32 *start32 = dest;
|
||||
unsigned int column;
|
||||
UBYTE pixels;
|
||||
for (; first_line < last_line; first_line++) {
|
||||
for (column = first_column; column < last_column; column++) {
|
||||
int i;
|
||||
pixels = PBI_PROTO80_GetPixels(first_line, column);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (pixels & 0x80)
|
||||
*start32++ = white;
|
||||
else
|
||||
*start32++ = black;
|
||||
pixels <<= 1;
|
||||
}
|
||||
}
|
||||
start32 += skip;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef AF80
|
||||
void SDL_VIDEO_BlitAF80_8(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink)
|
||||
{
|
||||
int skip = pitch - (last_column - first_column)*2;
|
||||
register Uint32 *start32 = dest;
|
||||
unsigned int column;
|
||||
UBYTE pixels;
|
||||
register Uint32 quad;
|
||||
for (; first_line < last_line; first_line++) {
|
||||
for (column = first_column; column < last_column; column++) {
|
||||
int i;
|
||||
int colour;
|
||||
pixels = AF80_GetPixels(first_line, column, &colour, blink);
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (pixels & 0x01)
|
||||
quad = colour;
|
||||
else
|
||||
quad = 0;
|
||||
if (pixels & 0x02)
|
||||
quad |= colour << 8;
|
||||
if (pixels & 0x04)
|
||||
quad |= colour << 16;
|
||||
if (pixels & 0x08)
|
||||
quad |= colour << 24;
|
||||
*start32++ = quad;
|
||||
pixels >>= 4;
|
||||
}
|
||||
}
|
||||
start32 += skip;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitAF80_16(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink, Uint16 *palette16)
|
||||
{
|
||||
Uint32 const black = (Uint32)palette16[0];
|
||||
Uint32 const black2 = black << 16;
|
||||
int skip = pitch - (last_column - first_column)*4;
|
||||
register Uint32 *start32 = dest;
|
||||
unsigned int column;
|
||||
UBYTE pixels;
|
||||
register Uint32 quad;
|
||||
for (; first_line < last_line; first_line++) {
|
||||
for (column = first_column; column < last_column; column++) {
|
||||
int i;
|
||||
int colour;
|
||||
pixels = AF80_GetPixels(first_line, column, &colour, blink);
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (pixels & 0x01)
|
||||
quad = palette16[colour];
|
||||
else
|
||||
quad = black;
|
||||
if (pixels & 0x02)
|
||||
quad |= palette16[colour] << 16;
|
||||
else
|
||||
quad |= black2;
|
||||
*start32++ = quad;
|
||||
pixels >>= 2;
|
||||
}
|
||||
}
|
||||
start32 += skip;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitAF80_32(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink, Uint32 *palette32)
|
||||
{
|
||||
Uint32 const black = palette32[0];
|
||||
int skip = pitch - (last_column - first_column)*8;
|
||||
register Uint32 *start32 = dest;
|
||||
unsigned int column;
|
||||
UBYTE pixels;
|
||||
for (; first_line < last_line; first_line++) {
|
||||
for (column = first_column; column < last_column; column++) {
|
||||
int i;
|
||||
int colour;
|
||||
pixels = AF80_GetPixels(first_line, column, &colour, blink);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (pixels & 0x01)
|
||||
*start32++ = palette32[colour];
|
||||
else
|
||||
*start32++ = black;
|
||||
pixels >>= 1;
|
||||
}
|
||||
}
|
||||
start32 += skip;
|
||||
}
|
||||
}
|
||||
#endif /* AF80 */
|
||||
|
||||
#ifdef BIT3
|
||||
void SDL_VIDEO_BlitBIT3_8(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink)
|
||||
{
|
||||
int skip = pitch - (last_column - first_column)*2;
|
||||
register Uint32 *start32 = dest;
|
||||
unsigned int column;
|
||||
UBYTE pixels;
|
||||
register Uint32 quad;
|
||||
for (; first_line < last_line; first_line++) {
|
||||
for (column = first_column; column < last_column; column++) {
|
||||
int i;
|
||||
int colour;
|
||||
pixels = BIT3_GetPixels(first_line, column, &colour, blink);
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (pixels & 0x01)
|
||||
quad = colour;
|
||||
else
|
||||
quad = 0;
|
||||
if (pixels & 0x02)
|
||||
quad |= colour << 8;
|
||||
if (pixels & 0x04)
|
||||
quad |= colour << 16;
|
||||
if (pixels & 0x08)
|
||||
quad |= colour << 24;
|
||||
*start32++ = quad;
|
||||
pixels >>= 4;
|
||||
}
|
||||
}
|
||||
start32 += skip;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitBIT3_16(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink, Uint16 *palette16)
|
||||
{
|
||||
Uint32 const black = (Uint32)palette16[0];
|
||||
Uint32 const black2 = black << 16;
|
||||
int skip = pitch - (last_column - first_column)*4;
|
||||
register Uint32 *start32 = dest;
|
||||
unsigned int column;
|
||||
UBYTE pixels;
|
||||
register Uint32 quad;
|
||||
for (; first_line < last_line; first_line++) {
|
||||
for (column = first_column; column < last_column; column++) {
|
||||
int i;
|
||||
int colour;
|
||||
pixels = BIT3_GetPixels(first_line, column, &colour, blink);
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (pixels & 0x01)
|
||||
quad = palette16[colour];
|
||||
else
|
||||
quad = black;
|
||||
if (pixels & 0x02)
|
||||
quad |= palette16[colour] << 16;
|
||||
else
|
||||
quad |= black2;
|
||||
*start32++ = quad;
|
||||
pixels >>= 2;
|
||||
}
|
||||
}
|
||||
start32 += skip;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_BlitBIT3_32(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink, Uint32 *palette32)
|
||||
{
|
||||
Uint32 const black = palette32[0];
|
||||
int skip = pitch - (last_column - first_column)*8;
|
||||
register Uint32 *start32 = dest;
|
||||
unsigned int column;
|
||||
UBYTE pixels;
|
||||
for (; first_line < last_line; first_line++) {
|
||||
for (column = first_column; column < last_column; column++) {
|
||||
int i;
|
||||
int colour;
|
||||
pixels = BIT3_GetPixels(first_line, column, &colour, blink);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (pixels & 0x01)
|
||||
*start32++ = palette32[colour];
|
||||
else
|
||||
*start32++ = black;
|
||||
pixels >>= 1;
|
||||
}
|
||||
}
|
||||
start32 += skip;
|
||||
}
|
||||
}
|
||||
#endif /* BIT3 */
|
||||
|
||||
void SDL_VIDEO_SetScanlinesPercentage(int value)
|
||||
{
|
||||
if (value < 0)
|
||||
value = 0;
|
||||
else if (value > 100)
|
||||
value = 100;
|
||||
SDL_VIDEO_scanlines_percentage = value;
|
||||
#if HAVE_OPENGL
|
||||
SDL_VIDEO_GL_ScanlinesPercentageChanged();
|
||||
#endif /* HAVE_OPENGL */
|
||||
}
|
||||
|
||||
void SDL_VIDEO_SetInterpolateScanlines(int value)
|
||||
{
|
||||
SDL_VIDEO_interpolate_scanlines = value;
|
||||
#if HAVE_OPENGL
|
||||
SDL_VIDEO_GL_InterpolateScanlinesChanged();
|
||||
#endif /* HAVE_OPENGL */
|
||||
}
|
||||
|
||||
void SDL_VIDEO_ToggleInterpolateScanlines(void)
|
||||
{
|
||||
SDL_VIDEO_SetInterpolateScanlines(!SDL_VIDEO_interpolate_scanlines);
|
||||
}
|
||||
|
||||
#if HAVE_OPENGL
|
||||
/* Sets an integer parameter and updates the video mode if needed. */
|
||||
static int SetIntAndUpdateVideo(int *ptr, int value)
|
||||
{
|
||||
int old_value = *ptr;
|
||||
if (old_value != value) {
|
||||
*ptr = value;
|
||||
if (!VIDEOMODE_Update()) {
|
||||
*ptr = old_value;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int SDL_VIDEO_SetOpengl(int value)
|
||||
{
|
||||
if (!SDL_VIDEO_opengl_available)
|
||||
return FALSE;
|
||||
return SetIntAndUpdateVideo(&SDL_VIDEO_opengl, value);
|
||||
}
|
||||
|
||||
int SDL_VIDEO_ToggleOpengl(void)
|
||||
{
|
||||
return SDL_VIDEO_SetOpengl(!SDL_VIDEO_opengl);
|
||||
}
|
||||
#endif /* HAVE_OPENGL */
|
||||
|
||||
int SDL_VIDEO_SetVsync(int value)
|
||||
{
|
||||
SDL_VIDEO_vsync = value;
|
||||
VIDEOMODE_Update();
|
||||
/* Return false if vsync is requested but not available. */
|
||||
return !SDL_VIDEO_vsync || SDL_VIDEO_vsync_available;
|
||||
}
|
||||
|
||||
int SDL_VIDEO_ToggleVsync(void)
|
||||
{
|
||||
return SDL_VIDEO_SetVsync(!SDL_VIDEO_vsync);
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
#ifndef SDL_VIDEO_H_
|
||||
#define SDL_VIDEO_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "videomode.h"
|
||||
|
||||
/* Native BPP of the desktop. OpenGL modes can be opened only
|
||||
in the native BPP. */
|
||||
extern int SDL_VIDEO_native_bpp;
|
||||
|
||||
/* Current width/height of the screen/window. */
|
||||
extern int SDL_VIDEO_width;
|
||||
extern int SDL_VIDEO_height;
|
||||
|
||||
/* Indicates current display mode */
|
||||
extern VIDEOMODE_MODE_t SDL_VIDEO_current_display_mode;
|
||||
|
||||
extern SDL_Surface *SDL_VIDEO_screen;
|
||||
|
||||
#if HAVE_OPENGL
|
||||
/* Indicates whenther OpenGL is available on the host machine. */
|
||||
extern int SDL_VIDEO_opengl_available;
|
||||
/* Get/set video hardware acceleration. */
|
||||
/* Call VIDEOMODE_Update() after changing this variable, or use SDL_VIDEO_SetOpengl() instead. */
|
||||
extern int SDL_VIDEO_opengl;
|
||||
int SDL_VIDEO_SetOpengl(int value);
|
||||
int SDL_VIDEO_ToggleOpengl(void);
|
||||
#endif /* HAVE_OPENGL */
|
||||
|
||||
/* Get/set the vertical synchronisation feature. */
|
||||
/* Call VIDEOMODE_Update() after changing this variable, or use SDL_VIDEO_SetVsync() instead. */
|
||||
extern int SDL_VIDEO_vsync;
|
||||
/* If Vsync is requested but not available in the current video mode, these
|
||||
functions return FALSE and set SDL_VIDEO_vsync_available to FALSE; else the returned and
|
||||
set values are TRUE. */
|
||||
int SDL_VIDEO_SetVsync(int value);
|
||||
int SDL_VIDEO_ToggleVsync(void);
|
||||
extern int SDL_VIDEO_vsync_available;
|
||||
|
||||
/* Get/set brightness of scanlines. (0=none, 100=completely black). */
|
||||
/* Use SDL_VIDEO_SetScanlinesPercentage() to set this value. */
|
||||
extern int SDL_VIDEO_scanlines_percentage;
|
||||
void SDL_VIDEO_SetScanlinesPercentage(int value);
|
||||
|
||||
/* Get/set scanlines interplation, both in sowtfare and in OpenGL mode. */
|
||||
/* Use SDL_VIDEO_SetInterpolateScanlines() to set this value. */
|
||||
extern int SDL_VIDEO_interpolate_scanlines;
|
||||
void SDL_VIDEO_SetInterpolateScanlines(int value);
|
||||
void SDL_VIDEO_ToggleInterpolateScanlines(void);
|
||||
|
||||
/* Initialise the SDL video subsystem. */
|
||||
void SDL_VIDEO_InitSDL(void);
|
||||
/* Close the SDL video subsystem. */
|
||||
void SDL_VIDEO_QuitSDL(void);
|
||||
/* Close and restart the SDL video subsystem. */
|
||||
void SDL_VIDEO_ReinitSDL(void);
|
||||
|
||||
int SDL_VIDEO_ReadConfig(char *option, char *parameters);
|
||||
void SDL_VIDEO_WriteConfig(FILE *fp);
|
||||
int SDL_VIDEO_Initialise(int *argc, char *argv[]);
|
||||
void SDL_VIDEO_Exit(void);
|
||||
|
||||
/* Write the screen data into DEST. */
|
||||
void SDL_VIDEO_BlitNormal8(Uint32 *dest, Uint8 *src, int pitch, int width, int height);
|
||||
void SDL_VIDEO_BlitNormal16(Uint32 *dest, Uint8 *src, int pitch, int width, int height, Uint16 *palette16);
|
||||
void SDL_VIDEO_BlitNormal32(Uint32 *dest, Uint8 *src, int pitch, int width, int height, Uint32 *palette32);
|
||||
void SDL_VIDEO_BlitXEP80_8(Uint32 *dest, Uint8 *src, int pitch, int width, int height);
|
||||
void SDL_VIDEO_BlitXEP80_16(Uint32 *dest, Uint8 *src, int pitch, int width, int height, Uint16 *palette16);
|
||||
void SDL_VIDEO_BlitXEP80_32(Uint32 *dest, Uint8 *src, int pitch, int width, int height, Uint32 *palette32);
|
||||
void SDL_VIDEO_BlitProto80_8(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line);
|
||||
void SDL_VIDEO_BlitProto80_16(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, Uint16 *palette16);
|
||||
void SDL_VIDEO_BlitProto80_32(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, Uint32 *palette32);
|
||||
#ifdef AF80
|
||||
void SDL_VIDEO_BlitAF80_8(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink);
|
||||
void SDL_VIDEO_BlitAF80_16(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink, Uint16 *palette16);
|
||||
void SDL_VIDEO_BlitAF80_32(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink, Uint32 *palette32);
|
||||
#endif
|
||||
#ifdef BIT3
|
||||
void SDL_VIDEO_BlitBIT3_8(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink);
|
||||
void SDL_VIDEO_BlitBIT3_16(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink, Uint16 *palette16);
|
||||
void SDL_VIDEO_BlitBIT3_32(Uint32 *dest, int first_column, int last_column, int pitch, int first_line, int last_line, int blink, Uint32 *palette32);
|
||||
#endif
|
||||
|
||||
/* Update lookup tables for the blit functions. */
|
||||
void SDL_VIDEO_UpdatePaletteLookup(VIDEOMODE_MODE_t mode, int bpp_32);
|
||||
|
||||
#endif /* SDL_VIDEO_H_ */
|
||||
@@ -0,0 +1,981 @@
|
||||
/*
|
||||
* sdl/video_gl.c - SDL library specific port code - OpenGL accelerated video display
|
||||
*
|
||||
* Copyright (c) 2010 Tomasz Krasuski
|
||||
* Copyright (C) 2010 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Atari800 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_opengl.h>
|
||||
|
||||
#include "af80.h"
|
||||
#include "bit3.h"
|
||||
#include "artifact.h"
|
||||
#include "atari.h"
|
||||
#include "cfg.h"
|
||||
#include "colours.h"
|
||||
#include "config.h"
|
||||
#include "filter_ntsc.h"
|
||||
#include "log.h"
|
||||
#include "pbi_proto80.h"
|
||||
#ifdef PAL_BLENDING
|
||||
#include "pal_blending.h"
|
||||
#endif /* PAL_BLENDING */
|
||||
#include "platform.h"
|
||||
#include "screen.h"
|
||||
#include "videomode.h"
|
||||
#include "xep80.h"
|
||||
#include "xep80_fonts.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "sdl/palette.h"
|
||||
#include "sdl/video.h"
|
||||
#include "sdl/video_gl.h"
|
||||
|
||||
static int currently_rotated = FALSE;
|
||||
/* If TRUE, then 32 bit, else 16 bit screen. */
|
||||
static int bpp_32 = FALSE;
|
||||
|
||||
int SDL_VIDEO_GL_filtering = 0;
|
||||
int SDL_VIDEO_GL_pixel_format = SDL_VIDEO_GL_PIXEL_FORMAT_BGR16;
|
||||
|
||||
/* Path to the OpenGL shared library. */
|
||||
static char const *library_path = NULL;
|
||||
|
||||
/* Pointers to OpenGL functions, loaded dynamically during initialisation. */
|
||||
static struct
|
||||
{
|
||||
void(APIENTRY*Viewport)(GLint,GLint,GLsizei,GLsizei);
|
||||
void(APIENTRY*ClearColor)(GLfloat, GLfloat, GLfloat, GLfloat);
|
||||
void(APIENTRY*Clear)(GLbitfield);
|
||||
void(APIENTRY*Enable)(GLenum);
|
||||
void(APIENTRY*Disable)(GLenum);
|
||||
void(APIENTRY*GenTextures)(GLsizei, GLuint*);
|
||||
void(APIENTRY*DeleteTextures)(GLsizei, const GLuint*);
|
||||
void(APIENTRY*BindTexture)(GLenum, GLuint);
|
||||
void(APIENTRY*TexParameteri)(GLenum, GLenum, GLint);
|
||||
void(APIENTRY*TexImage2D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*);
|
||||
void(APIENTRY*TexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*);
|
||||
void(APIENTRY*TexCoord2f)(GLfloat, GLfloat);
|
||||
void(APIENTRY*Vertex3f)(GLfloat, GLfloat, GLfloat);
|
||||
void(APIENTRY*Color4f)(GLfloat, GLfloat, GLfloat, GLfloat);
|
||||
void(APIENTRY*BlendFunc)(GLenum,GLenum);
|
||||
void(APIENTRY*MatrixMode)(GLenum);
|
||||
void(APIENTRY*Ortho)(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
|
||||
void(APIENTRY*LoadIdentity)(void);
|
||||
void(APIENTRY*Begin)(GLenum);
|
||||
void(APIENTRY*End)(void);
|
||||
void(APIENTRY*GetIntegerv)(GLenum, GLint*);
|
||||
const GLubyte*(APIENTRY*GetString)(GLenum);
|
||||
GLuint(APIENTRY*GenLists)(GLsizei);
|
||||
void(APIENTRY*DeleteLists)(GLuint, GLsizei);
|
||||
void(APIENTRY*NewList)(GLuint, GLenum);
|
||||
void(APIENTRY*EndList)(void);
|
||||
void(APIENTRY*CallList)(GLuint);
|
||||
void(APIENTRY*GenBuffers)(GLsizei, GLuint*);
|
||||
void(APIENTRY*DeleteBuffers)(GLsizei, const GLuint*);
|
||||
void(APIENTRY*BindBuffer)(GLenum, GLuint);
|
||||
void(APIENTRY*BufferData)(GLenum, GLsizeiptr, const GLvoid*, GLenum);
|
||||
void*(APIENTRY*MapBuffer)(GLenum, GLenum);
|
||||
GLboolean(APIENTRY*UnmapBuffer)(GLenum);
|
||||
} gl;
|
||||
|
||||
static void DisplayNormal(GLvoid *dest);
|
||||
#if NTSC_FILTER
|
||||
static void DisplayNTSCEmu(GLvoid *dest);
|
||||
#endif
|
||||
#ifdef XEP80_EMULATION
|
||||
static void DisplayXEP80(GLvoid *dest);
|
||||
#endif
|
||||
#ifdef PBI_PROTO80
|
||||
static void DisplayProto80(GLvoid *dest);
|
||||
#endif
|
||||
#ifdef AF80
|
||||
static void DisplayAF80(GLvoid *dest);
|
||||
#endif
|
||||
#ifdef BIT3
|
||||
static void DisplayBIT3(GLvoid *dest);
|
||||
#endif
|
||||
#ifdef PAL_BLENDING
|
||||
static void DisplayPalBlending(GLvoid *dest);
|
||||
#endif /* PAL_BLENDING */
|
||||
|
||||
static void (* blit_funcs[VIDEOMODE_MODE_SIZE])(GLvoid *) = {
|
||||
&DisplayNormal
|
||||
#if NTSC_FILTER
|
||||
,&DisplayNTSCEmu
|
||||
#endif
|
||||
#ifdef XEP80_EMULATION
|
||||
,&DisplayXEP80
|
||||
#endif
|
||||
#ifdef PBI_PROTO80
|
||||
,&DisplayProto80
|
||||
#endif
|
||||
#ifdef AF80
|
||||
,&DisplayAF80
|
||||
#endif
|
||||
#ifdef BIT3
|
||||
,&DisplayBIT3
|
||||
#endif
|
||||
};
|
||||
|
||||
/* GL textures - [0] is screen, [1] is scanlines. */
|
||||
static GLuint textures[2];
|
||||
|
||||
int SDL_VIDEO_GL_pbo = TRUE;
|
||||
|
||||
/* Indicates whether Pixel Buffer Objects GL extension is available.
|
||||
Available from OpenGL 2.1, it gives a significant boost in blit speed. */
|
||||
static int pbo_available;
|
||||
/* Name of the main screen Pixel Buffer Object. */
|
||||
static GLuint screen_pbo;
|
||||
|
||||
/* Data for the screen texture. not used when PBOs are used. */
|
||||
static GLvoid *screen_texture = NULL;
|
||||
|
||||
/* 16- and 32-bit ARGB textures, both of size 1x2, used for displaying scanlines.
|
||||
They contain a transparent black pixel above an opaque black pixel. */
|
||||
static Uint32 const scanline_tex32[2] = { 0x00000000, 0xff000000 }; /* BGRA 8-8-8-8-REV */
|
||||
/* The 16-bit one is padded to 32 bits, hence it contains 4 values, not 2. */
|
||||
static Uint16 const scanline_tex16[4] = { 0x0000, 0x0000, 0x8000, 0x0000 }; /* BGRA 5-5-5-1-REV */
|
||||
|
||||
/* Variables used with "subpixel shifting". Screen and scanline textures
|
||||
sometimes are intentionally shifted by a part of a pixel to look better/clearer. */
|
||||
static GLfloat screen_vshift;
|
||||
static GLfloat screen_hshift;
|
||||
static GLfloat scanline_vshift;
|
||||
static int paint_scanlines;
|
||||
|
||||
/* GL Display List for placing the screen and scanline textures on the screen. */
|
||||
static GLuint screen_dlist;
|
||||
|
||||
static char const * const pixel_format_cfg_strings[SDL_VIDEO_GL_PIXEL_FORMAT_SIZE] = {
|
||||
"BGR16",
|
||||
"RGB16",
|
||||
"BGRA32",
|
||||
"ARGB32"
|
||||
};
|
||||
|
||||
typedef struct pixel_format_t {
|
||||
GLint internal_format;
|
||||
GLenum format;
|
||||
GLenum type;
|
||||
Uint32 black_pixel;
|
||||
Uint32 rmask;
|
||||
Uint32 gmask;
|
||||
Uint32 bmask;
|
||||
void(*calc_pal_func)(void *dest, int const *palette, int size);
|
||||
void(*ntsc_blit_func)(atari_ntsc_t const*, ATARI_NTSC_IN_T const*, long, int, int, void*, long);
|
||||
} pixel_format_t;
|
||||
|
||||
pixel_format_t const pixel_formats[4] = {
|
||||
{ GL_RGB5, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, 0x0000,
|
||||
0x0000001f, 0x000007e0, 0x0000f800,
|
||||
&SDL_PALETTE_Calculate16_B5G6R5, &atari_ntsc_blit_bgr16 },
|
||||
{ GL_RGB5, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0x0000,
|
||||
0x0000f800, 0x000007e0, 0x0000001f,
|
||||
&SDL_PALETTE_Calculate16_R5G6B5, &atari_ntsc_blit_rgb16 }, /* NVIDIA 16-bit */
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, 0xff000000,
|
||||
0x0000ff00, 0x00ff0000, 0xff000000,
|
||||
&SDL_PALETTE_Calculate32_B8G8R8A8, &atari_ntsc_blit_bgra32 },
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0xff000000,
|
||||
0x00ff0000, 0x0000ff00, 0x000000ff,
|
||||
&SDL_PALETTE_Calculate32_A8R8G8B8, &atari_ntsc_blit_argb32 } /* NVIDIA 32-bit */
|
||||
};
|
||||
|
||||
/* Conversion between function pointers and 'void *' is forbidden in
|
||||
ISO C, but unfortunately unavoidable when using SDL_GL_GetProcAddress.
|
||||
So the code below is non-portable and gives a warning with gcc -ansi
|
||||
-Wall -pedantic, but is the only possible solution. */
|
||||
static void (*GetGlFunc(const char* s))(void)
|
||||
{
|
||||
/* suppress warning: ISO C forbids conversion of object pointer to function pointer type [-pedantic] */
|
||||
#ifdef __GNUC__
|
||||
__extension__
|
||||
#endif
|
||||
void(*f)(void) = (void(*)(void))SDL_GL_GetProcAddress(s);
|
||||
if (f == NULL)
|
||||
Log_print("Unable to get function pointer for %s\n",s);
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Alocates memory for the screen texture, if needed. */
|
||||
static void AllocTexture(void)
|
||||
{
|
||||
if (!SDL_VIDEO_GL_pbo && screen_texture == NULL)
|
||||
/* The largest width is in NTSC-filtered full overscan mode - 672 pixels.
|
||||
The largest height is in PAL XEP-80 mode - 300 pixels. Add 1 pixel at each side
|
||||
to nicely render screen borders. The texture is 1024x512, which is more than
|
||||
enough - although it's rounded to powers of 2 to be more compatible (earlier
|
||||
versions of OpenGL supported only textures with width/height of powers of 2). */
|
||||
screen_texture = Util_malloc(1024*512*(bpp_32 ? sizeof(Uint32) : sizeof(Uint16)));
|
||||
}
|
||||
|
||||
/* Frees memory for the screen texture, if needed. */
|
||||
static void FreeTexture(void)
|
||||
{
|
||||
if (screen_texture != NULL) {
|
||||
free(screen_texture);
|
||||
screen_texture = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets up the initial parameters of the OpenGL context. See also CleanGlContext. */
|
||||
static void InitGlContext(void)
|
||||
{
|
||||
GLint filtering = SDL_VIDEO_GL_filtering ? GL_LINEAR : GL_NEAREST;
|
||||
gl.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
gl.Clear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
gl.Enable(GL_TEXTURE_2D);
|
||||
gl.GenTextures(2, textures);
|
||||
|
||||
/* Screen texture. */
|
||||
gl.BindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
|
||||
/* Scanlines texture. */
|
||||
filtering = SDL_VIDEO_interpolate_scanlines ? GL_LINEAR : GL_NEAREST;
|
||||
gl.BindTexture(GL_TEXTURE_2D, textures[1]);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
gl.MatrixMode(GL_PROJECTION);
|
||||
gl.LoadIdentity();
|
||||
gl.Ortho(-1.0, 1.0, -1.0, 1.0, 0.0, 10.0);
|
||||
gl.MatrixMode(GL_MODELVIEW);
|
||||
gl.LoadIdentity();
|
||||
screen_dlist = gl.GenLists(1);
|
||||
if (SDL_VIDEO_GL_pbo)
|
||||
gl.GenBuffers(1, &screen_pbo);
|
||||
}
|
||||
|
||||
/* Cleans up the structures allocated in InitGlContext. */
|
||||
static void CleanGlContext(void)
|
||||
{
|
||||
if (SDL_VIDEO_GL_pbo)
|
||||
gl.DeleteBuffers(1, &screen_pbo);
|
||||
gl.DeleteLists(screen_dlist, 1);
|
||||
gl.DeleteTextures(2, textures);
|
||||
}
|
||||
|
||||
/* Sets up the initial parameters of all used textures and the PBO. */
|
||||
static void InitGlTextures(void)
|
||||
{
|
||||
/* Texture for the display surface. */
|
||||
gl.BindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
gl.TexImage2D(GL_TEXTURE_2D, 0, pixel_formats[SDL_VIDEO_GL_pixel_format].internal_format, 1024, 512, 0,
|
||||
pixel_formats[SDL_VIDEO_GL_pixel_format].format, pixel_formats[SDL_VIDEO_GL_pixel_format].type,
|
||||
NULL);
|
||||
/* Texture for scanlines. */
|
||||
gl.BindTexture(GL_TEXTURE_2D, textures[1]);
|
||||
if (bpp_32)
|
||||
gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
scanline_tex32);
|
||||
else
|
||||
gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0,
|
||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV,
|
||||
scanline_tex16);
|
||||
if (SDL_VIDEO_GL_pbo) {
|
||||
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, screen_pbo);
|
||||
gl.BufferData(GL_PIXEL_UNPACK_BUFFER_ARB, 1024*512*(bpp_32 ? sizeof(Uint32) : sizeof(Uint16)), NULL, GL_DYNAMIC_DRAW_ARB);
|
||||
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_Cleanup(void)
|
||||
{
|
||||
if (SDL_VIDEO_screen != NULL && (SDL_VIDEO_screen->flags & SDL_OPENGL) == SDL_OPENGL)
|
||||
CleanGlContext();
|
||||
FreeTexture();
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_GetPixelFormat(PLATFORM_pixel_format_t *format)
|
||||
{
|
||||
format->bpp = bpp_32 ? 32 : 16;
|
||||
format->rmask = pixel_formats[SDL_VIDEO_GL_pixel_format].rmask;
|
||||
format->gmask = pixel_formats[SDL_VIDEO_GL_pixel_format].gmask;
|
||||
format->bmask = pixel_formats[SDL_VIDEO_GL_pixel_format].bmask;
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_MapRGB(void *dest, int const *palette, int size)
|
||||
{
|
||||
(*pixel_formats[SDL_VIDEO_GL_pixel_format].calc_pal_func)(dest, palette, size);
|
||||
}
|
||||
|
||||
/* Calculate the palette in the 32-bit BGRA format, or 16-bit BGR 5-6-5 format. */
|
||||
static void UpdatePaletteLookup(VIDEOMODE_MODE_t mode)
|
||||
{
|
||||
SDL_VIDEO_UpdatePaletteLookup(mode, bpp_32);
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_PaletteUpdate(void)
|
||||
{
|
||||
UpdatePaletteLookup(SDL_VIDEO_current_display_mode);
|
||||
}
|
||||
|
||||
/* Set parameters that will shift the screen and scanline textures a bit,
|
||||
in order to look better/cleaner on screen. */
|
||||
static void SetSubpixelShifts(void)
|
||||
{
|
||||
int dest_width;
|
||||
int dest_height;
|
||||
int vmult, hmult;
|
||||
if (currently_rotated) {
|
||||
dest_width = VIDEOMODE_dest_height;
|
||||
dest_height = VIDEOMODE_dest_width;
|
||||
} else {
|
||||
dest_width = VIDEOMODE_dest_width;
|
||||
dest_height = VIDEOMODE_dest_height;
|
||||
}
|
||||
vmult = dest_height / VIDEOMODE_src_height;
|
||||
hmult = dest_width / VIDEOMODE_src_width;
|
||||
|
||||
paint_scanlines = vmult >= 2 && SDL_VIDEO_scanlines_percentage != 0;
|
||||
|
||||
if (dest_height % VIDEOMODE_src_height == 0 &&
|
||||
SDL_VIDEO_GL_filtering &&
|
||||
!(vmult & 1))
|
||||
screen_vshift = 0.5 / vmult;
|
||||
else
|
||||
screen_vshift = 0.0;
|
||||
|
||||
|
||||
if (dest_height % VIDEOMODE_src_height == 0 &&
|
||||
((SDL_VIDEO_interpolate_scanlines && !(vmult & 1)) ||
|
||||
(!SDL_VIDEO_interpolate_scanlines && (vmult & 3) == 3)
|
||||
)
|
||||
)
|
||||
scanline_vshift = -0.25 + 0.5 / vmult;
|
||||
else
|
||||
scanline_vshift = -0.25;
|
||||
|
||||
if (dest_width % VIDEOMODE_src_width == 0 &&
|
||||
SDL_VIDEO_GL_filtering &&
|
||||
!(hmult & 1))
|
||||
screen_hshift = 0.5 / hmult;
|
||||
else
|
||||
screen_hshift = 0.0;
|
||||
}
|
||||
|
||||
/* Sets up the GL Display List that creates a textured rectangle of the main
|
||||
screen and a second, translucent, rectangle with scanlines. */
|
||||
static void SetGlDisplayList(void)
|
||||
{
|
||||
gl.NewList(screen_dlist, GL_COMPILE);
|
||||
gl.Clear(GL_COLOR_BUFFER_BIT);
|
||||
gl.BindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
gl.Begin(GL_QUADS);
|
||||
if (currently_rotated) {
|
||||
gl.TexCoord2f(screen_hshift/1024.0f, ((GLfloat)VIDEOMODE_src_height + screen_vshift)/512.0f);
|
||||
gl.Vertex3f(1.0f, -1.0f, -2.0f);
|
||||
gl.TexCoord2f(((GLfloat)VIDEOMODE_actual_width + screen_hshift)/1024.0f, ((GLfloat)VIDEOMODE_src_height + screen_vshift)/512.0f);
|
||||
gl.Vertex3f(1.0f, 1.0f, -2.0f);
|
||||
gl.TexCoord2f(((GLfloat)VIDEOMODE_actual_width + screen_hshift)/1024.0f, screen_vshift/512.0f);
|
||||
gl.Vertex3f(-1.0f, 1.0f, -2.0f);
|
||||
gl.TexCoord2f(screen_hshift/1024.0f, screen_vshift/512.0f);
|
||||
gl.Vertex3f(-1.0f, -1.0f, -2.0f);
|
||||
} else {
|
||||
gl.TexCoord2f(screen_hshift/1024.0f, ((GLfloat)VIDEOMODE_src_height + screen_vshift)/512.0f);
|
||||
gl.Vertex3f(-1.0f, -1.0f, -2.0f);
|
||||
gl.TexCoord2f(((GLfloat)VIDEOMODE_actual_width + screen_hshift)/1024.0f, ((GLfloat)VIDEOMODE_src_height + screen_vshift)/512.0f);
|
||||
gl.Vertex3f(1.0f, -1.0f, -2.0f);
|
||||
gl.TexCoord2f(((GLfloat)VIDEOMODE_actual_width + screen_hshift)/1024.0f, screen_vshift/512.0f);
|
||||
gl.Vertex3f(1.0f, 1.0f, -2.0f);
|
||||
gl.TexCoord2f(screen_hshift/1024.0f, screen_vshift/512.0f);
|
||||
gl.Vertex3f(-1.0f, 1.0f, -2.0f);
|
||||
}
|
||||
gl.End();
|
||||
if (paint_scanlines) {
|
||||
gl.Enable(GL_BLEND);
|
||||
gl.Color4f(1.0f, 1.0f, 1.0f, ((GLfloat)SDL_VIDEO_scanlines_percentage / 100.0f));
|
||||
gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
gl.BindTexture(GL_TEXTURE_2D, textures[1]);
|
||||
gl.Begin(GL_QUADS);
|
||||
if (currently_rotated) {
|
||||
gl.TexCoord2f(0.0f, (GLfloat)VIDEOMODE_src_height + scanline_vshift);
|
||||
gl.Vertex3f(1.0f, -1.0f, -1.0f);
|
||||
gl.TexCoord2f(1.0f, (GLfloat)VIDEOMODE_src_height + scanline_vshift);
|
||||
gl.Vertex3f(1.0f, 1.0f, -1.0f);
|
||||
gl.TexCoord2f(1.0f, scanline_vshift);
|
||||
gl.Vertex3f(-1.0f, 1.0f, -1.0f);
|
||||
gl.TexCoord2f(0.0f, scanline_vshift);
|
||||
gl.Vertex3f(-1.0f, -1.0f, -1.0f);
|
||||
} else {
|
||||
gl.TexCoord2f(0.0f, (GLfloat)VIDEOMODE_src_height + scanline_vshift);
|
||||
gl.Vertex3f(-1.0f, -1.0f, -1.0f);
|
||||
gl.TexCoord2f(1.0f, (GLfloat)VIDEOMODE_src_height + scanline_vshift);
|
||||
gl.Vertex3f(1.0f, -1.0f, -1.0f);
|
||||
gl.TexCoord2f(1.0f, scanline_vshift);
|
||||
gl.Vertex3f(1.0f, 1.0f, -1.0f);
|
||||
gl.TexCoord2f(0.0f, scanline_vshift);
|
||||
gl.Vertex3f(-1.0f, 1.0f, -1.0f);
|
||||
}
|
||||
gl.End();
|
||||
gl.Disable(GL_BLEND);
|
||||
}
|
||||
gl.EndList();
|
||||
}
|
||||
|
||||
/* Resets the screen texture/PBO to all-black. */
|
||||
static void CleanDisplayTexture(void)
|
||||
{
|
||||
GLvoid *ptr;
|
||||
gl.BindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
if (SDL_VIDEO_GL_pbo) {
|
||||
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, screen_pbo);
|
||||
ptr = gl.MapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
}
|
||||
else
|
||||
ptr = screen_texture;
|
||||
if (bpp_32) {
|
||||
Uint32* tex = (Uint32 *)ptr;
|
||||
unsigned int i;
|
||||
for (i = 0; i < 1024*512; i ++)
|
||||
/* Set alpha channel to full opacity. */
|
||||
tex[i] = pixel_formats[SDL_VIDEO_GL_pixel_format].black_pixel;
|
||||
|
||||
} else
|
||||
memset(ptr, 0x00, 1024*512*sizeof(Uint16));
|
||||
if (SDL_VIDEO_GL_pbo) {
|
||||
gl.UnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
|
||||
ptr = NULL;
|
||||
}
|
||||
if (bpp_32)
|
||||
gl.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1024, 512,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
ptr);
|
||||
else
|
||||
gl.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1024, 512,
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||
ptr);
|
||||
if (SDL_VIDEO_GL_pbo)
|
||||
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
|
||||
}
|
||||
|
||||
/* Sets pointers to OpenGL functions. Returns TRUE on success, FALSE on failure. */
|
||||
static int InitGlFunctions(void)
|
||||
{
|
||||
if ((gl.Viewport = (void(APIENTRY*)(GLint,GLint,GLsizei,GLsizei))GetGlFunc("glViewport")) == NULL ||
|
||||
(gl.ClearColor = (void(APIENTRY*)(GLfloat, GLfloat, GLfloat, GLfloat))GetGlFunc("glClearColor")) == NULL ||
|
||||
(gl.Clear = (void(APIENTRY*)(GLbitfield))GetGlFunc("glClear")) == NULL ||
|
||||
(gl.Enable = (void(APIENTRY*)(GLenum))GetGlFunc("glEnable")) == NULL ||
|
||||
(gl.Disable = (void(APIENTRY*)(GLenum))GetGlFunc("glDisable")) == NULL ||
|
||||
(gl.GenTextures = (void(APIENTRY*)(GLsizei, GLuint*))GetGlFunc("glGenTextures")) == NULL ||
|
||||
(gl.DeleteTextures = (void(APIENTRY*)(GLsizei, const GLuint*))GetGlFunc("glDeleteTextures")) == NULL ||
|
||||
(gl.BindTexture = (void(APIENTRY*)(GLenum, GLuint))GetGlFunc("glBindTexture")) == NULL ||
|
||||
(gl.TexParameteri = (void(APIENTRY*)(GLenum, GLenum, GLint))GetGlFunc("glTexParameteri")) == NULL ||
|
||||
(gl.TexImage2D = (void(APIENTRY*)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*))GetGlFunc("glTexImage2D")) == NULL ||
|
||||
(gl.TexSubImage2D = (void(APIENTRY*)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*))GetGlFunc("glTexSubImage2D")) == NULL ||
|
||||
(gl.TexCoord2f = (void(APIENTRY*)(GLfloat, GLfloat))GetGlFunc("glTexCoord2f")) == NULL ||
|
||||
(gl.Vertex3f = (void(APIENTRY*)(GLfloat, GLfloat, GLfloat))GetGlFunc("glVertex3f")) == NULL ||
|
||||
(gl.Color4f = (void(APIENTRY*)(GLfloat, GLfloat, GLfloat, GLfloat))GetGlFunc("glColor4f")) == NULL ||
|
||||
(gl.BlendFunc = (void(APIENTRY*)(GLenum,GLenum))GetGlFunc("glBlendFunc")) == NULL ||
|
||||
(gl.MatrixMode = (void(APIENTRY*)(GLenum))GetGlFunc("glMatrixMode")) == NULL ||
|
||||
(gl.Ortho = (void(APIENTRY*)(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble))GetGlFunc("glOrtho")) == NULL ||
|
||||
(gl.LoadIdentity = (void(APIENTRY*)(void))GetGlFunc("glLoadIdentity")) == NULL ||
|
||||
(gl.Begin = (void(APIENTRY*)(GLenum))GetGlFunc("glBegin")) == NULL ||
|
||||
(gl.End = (void(APIENTRY*)(void))GetGlFunc("glEnd")) == NULL ||
|
||||
(gl.GetIntegerv = (void(APIENTRY*)(GLenum, GLint*))GetGlFunc("glGetIntegerv")) == NULL ||
|
||||
(gl.GetString = (const GLubyte*(APIENTRY*)(GLenum))GetGlFunc("glGetString")) == NULL ||
|
||||
(gl.GenLists = (GLuint(APIENTRY*)(GLsizei))GetGlFunc("glGenLists")) == NULL ||
|
||||
(gl.DeleteLists = (void(APIENTRY*)(GLuint, GLsizei))GetGlFunc("glDeleteLists")) == NULL ||
|
||||
(gl.NewList = (void(APIENTRY*)(GLuint, GLenum))GetGlFunc("glNewList")) == NULL ||
|
||||
(gl.EndList = (void(APIENTRY*)(void))GetGlFunc("glEndList")) == NULL ||
|
||||
(gl.CallList = (void(APIENTRY*)(GLuint))GetGlFunc("glCallList")) == NULL)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Checks availability of Pixel Buffer Objests extension and sets pointers of PBO-related OpenGL functions.
|
||||
Returns TRUE on success, FALSE on failure. */
|
||||
static int InitGlPbo(void)
|
||||
{
|
||||
const GLubyte *extensions = gl.GetString(GL_EXTENSIONS);
|
||||
if (!strstr((char *)extensions, "EXT_pixel_buffer_object")) {
|
||||
return FALSE;
|
||||
}
|
||||
if ((gl.GenBuffers = (void(APIENTRY*)(GLsizei, GLuint*))GetGlFunc("glGenBuffersARB")) == NULL ||
|
||||
(gl.DeleteBuffers = (void(APIENTRY*)(GLsizei, const GLuint*))GetGlFunc("glDeleteBuffersARB")) == NULL ||
|
||||
(gl.BindBuffer = (void(APIENTRY*)(GLenum, GLuint))GetGlFunc("glBindBufferARB")) == NULL ||
|
||||
(gl.BufferData = (void(APIENTRY*)(GLenum, GLsizeiptr, const GLvoid*, GLenum))GetGlFunc("glBufferDataARB")) == NULL ||
|
||||
(gl.MapBuffer = (void*(APIENTRY*)(GLenum, GLenum))GetGlFunc("glMapBufferARB")) == NULL ||
|
||||
(gl.UnmapBuffer = (GLboolean(APIENTRY*)(GLenum))GetGlFunc("glUnmapBufferARB")) == NULL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ModeInfo(void)
|
||||
{
|
||||
const char *fullstring = (SDL_VIDEO_screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ? "fullscreen" : "windowed";
|
||||
Log_print("Video Mode: %dx%dx%d %s, pixel format: %s", SDL_VIDEO_screen->w, SDL_VIDEO_screen->h,
|
||||
SDL_VIDEO_screen->format->BitsPerPixel, fullstring, pixel_format_cfg_strings[SDL_VIDEO_GL_pixel_format]);
|
||||
}
|
||||
|
||||
/* Return value of TRUE indicates that the video subsystem was reinitialised. */
|
||||
static int SetVideoMode(int w, int h, int windowed)
|
||||
{
|
||||
int reinit = FALSE;
|
||||
Uint32 flags = SDL_OPENGL | (windowed ? SDL_RESIZABLE : SDL_FULLSCREEN);
|
||||
/* In OpenGL mode, the SDL screen is always opened with the default
|
||||
desktop depth - it is the most compatible way. */
|
||||
SDL_VIDEO_screen = SDL_SetVideoMode(w, h, SDL_VIDEO_native_bpp, flags);
|
||||
if (SDL_VIDEO_screen == NULL) {
|
||||
/* Some SDL_SetVideoMode errors can be averted by reinitialising the SDL video subsystem. */
|
||||
Log_print("Setting video mode: %dx%dx%d failed: %s. Reinitialising video.", w, h, SDL_VIDEO_native_bpp, SDL_GetError());
|
||||
SDL_VIDEO_ReinitSDL();
|
||||
reinit = TRUE;
|
||||
SDL_VIDEO_screen = SDL_SetVideoMode(w, h, SDL_VIDEO_native_bpp, flags);
|
||||
if (SDL_VIDEO_screen == NULL) {
|
||||
Log_print("Setting Video Mode: %dx%dx%d failed: %s", w, h, SDL_VIDEO_native_bpp, SDL_GetError());
|
||||
Log_flushlog();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
SDL_VIDEO_width = SDL_VIDEO_screen->w;
|
||||
SDL_VIDEO_height = SDL_VIDEO_screen->h;
|
||||
SDL_VIDEO_vsync_available = FALSE;
|
||||
ModeInfo();
|
||||
return reinit;
|
||||
}
|
||||
|
||||
int SDL_VIDEO_GL_SetVideoMode(VIDEOMODE_resolution_t const *res, int windowed, VIDEOMODE_MODE_t mode, int rotate90)
|
||||
{
|
||||
int isnew = SDL_VIDEO_screen == NULL; /* TRUE means the SDL/GL screen was not yet initialised */
|
||||
int context_updated = FALSE; /* TRUE means the OpenGL context has been recreated */
|
||||
currently_rotated = rotate90;
|
||||
|
||||
/* Call SetVideoMode only when there was change in width, height, or windowed/fullscreen. */
|
||||
if (isnew || SDL_VIDEO_screen->w != res->width || SDL_VIDEO_screen->h != res->height ||
|
||||
((SDL_VIDEO_screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) == windowed) {
|
||||
if (!isnew) {
|
||||
CleanGlContext();
|
||||
}
|
||||
#if HAVE_WINDOWS_H
|
||||
if (isnew && !windowed) {
|
||||
/* Switching from fullscreen software mode directly to fullscreen OpenGL mode causes
|
||||
glitches on Windows (eg. when switched to windowed mode, the window would spontaneously
|
||||
go back to fullscreen each time it loses and regains focus). We avoid the issue by
|
||||
switching to a windowed non-OpenGL mode inbetween. */
|
||||
SDL_SetVideoMode(320, 200, SDL_VIDEO_native_bpp, SDL_RESIZABLE);
|
||||
}
|
||||
#endif /* HAVE_WINDOWS_H */
|
||||
if (SetVideoMode(res->width, res->height, windowed))
|
||||
/* Reinitialisation happened! Need to recreate GL context. */
|
||||
isnew = TRUE;
|
||||
if (!InitGlFunctions()) {
|
||||
Log_print("Cannot use OpenGL - some functions are not provided.");
|
||||
return FALSE;
|
||||
}
|
||||
if (isnew) {
|
||||
GLint tex_size;
|
||||
gl.GetIntegerv(GL_MAX_TEXTURE_SIZE, & tex_size);
|
||||
if (tex_size < 1024) {
|
||||
Log_print("Cannot use OpenGL - Supported texture size is too small (%d).", tex_size);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
pbo_available = InitGlPbo();
|
||||
if (!pbo_available)
|
||||
SDL_VIDEO_GL_pbo = FALSE;
|
||||
if (isnew) {
|
||||
Log_print("OpenGL initialized successfully. Version: %s", gl.GetString(GL_VERSION));
|
||||
if (pbo_available)
|
||||
Log_print("OpenGL Pixel Buffer Objects available.");
|
||||
else
|
||||
Log_print("OpenGL Pixel Buffer Objects not available.");
|
||||
}
|
||||
InitGlContext();
|
||||
context_updated = TRUE;
|
||||
}
|
||||
|
||||
if (isnew) {
|
||||
FreeTexture();
|
||||
AllocTexture();
|
||||
}
|
||||
|
||||
UpdatePaletteLookup(mode);
|
||||
|
||||
if (context_updated)
|
||||
InitGlTextures();
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE); /* hide mouse cursor */
|
||||
|
||||
if (mode == VIDEOMODE_MODE_NORMAL) {
|
||||
#ifdef PAL_BLENDING
|
||||
if (ARTIFACT_mode == ARTIFACT_PAL_BLEND)
|
||||
blit_funcs[0] = &DisplayPalBlending;
|
||||
else
|
||||
#endif /* PAL_BLENDING */
|
||||
blit_funcs[0] = &DisplayNormal;
|
||||
}
|
||||
|
||||
gl.Viewport(VIDEOMODE_dest_offset_left, VIDEOMODE_dest_offset_top, VIDEOMODE_dest_width, VIDEOMODE_dest_height);
|
||||
SetSubpixelShifts();
|
||||
SetGlDisplayList();
|
||||
CleanDisplayTexture();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int SDL_VIDEO_GL_SupportsVideomode(VIDEOMODE_MODE_t mode, int stretch, int rotate90)
|
||||
{
|
||||
/* OpenGL supports rotation and stretching in all display modes. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void DisplayNormal(GLvoid *dest)
|
||||
{
|
||||
Uint8 *screen = (Uint8 *)Screen_atari + Screen_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left;
|
||||
if (bpp_32)
|
||||
SDL_VIDEO_BlitNormal32((Uint32*)dest, screen, VIDEOMODE_actual_width, VIDEOMODE_src_width, VIDEOMODE_src_height, SDL_PALETTE_buffer.bpp32);
|
||||
else {
|
||||
int pitch;
|
||||
if (VIDEOMODE_actual_width & 0x01)
|
||||
pitch = VIDEOMODE_actual_width / 2 + 1;
|
||||
else
|
||||
pitch = VIDEOMODE_actual_width / 2;
|
||||
SDL_VIDEO_BlitNormal16((Uint32*)dest, screen, pitch, VIDEOMODE_src_width, VIDEOMODE_src_height, SDL_PALETTE_buffer.bpp16);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PAL_BLENDING
|
||||
static void DisplayPalBlending(GLvoid *dest)
|
||||
{
|
||||
Uint8 *screen = (Uint8 *)Screen_atari + Screen_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left;
|
||||
if (bpp_32)
|
||||
PAL_BLENDING_Blit32((ULONG*)dest, screen, VIDEOMODE_actual_width, VIDEOMODE_src_width, VIDEOMODE_src_height, VIDEOMODE_src_offset_top % 2);
|
||||
else {
|
||||
int pitch;
|
||||
if (VIDEOMODE_actual_width & 0x01)
|
||||
pitch = VIDEOMODE_actual_width / 2 + 1;
|
||||
else
|
||||
pitch = VIDEOMODE_actual_width / 2;
|
||||
PAL_BLENDING_Blit16((ULONG*)dest, screen, pitch, VIDEOMODE_src_width, VIDEOMODE_src_height, VIDEOMODE_src_offset_top % 2);
|
||||
}
|
||||
}
|
||||
#endif /* PAL_BLENDING */
|
||||
|
||||
#if NTSC_FILTER
|
||||
static void DisplayNTSCEmu(GLvoid *dest)
|
||||
{
|
||||
(*pixel_formats[SDL_VIDEO_GL_pixel_format].ntsc_blit_func)(
|
||||
FILTER_NTSC_emu,
|
||||
(ATARI_NTSC_IN_T *) ((UBYTE *)Screen_atari + Screen_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left),
|
||||
Screen_WIDTH,
|
||||
VIDEOMODE_src_width,
|
||||
VIDEOMODE_src_height,
|
||||
dest,
|
||||
VIDEOMODE_actual_width * (bpp_32 ? 4 : 2));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XEP80_EMULATION
|
||||
static void DisplayXEP80(GLvoid *dest)
|
||||
{
|
||||
static int xep80Frame = 0;
|
||||
Uint8 *screen;
|
||||
xep80Frame++;
|
||||
if (xep80Frame == 60) xep80Frame = 0;
|
||||
if (xep80Frame > 29)
|
||||
screen = XEP80_screen_1;
|
||||
else
|
||||
screen = XEP80_screen_2;
|
||||
|
||||
screen += XEP80_SCRN_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left;
|
||||
if (bpp_32)
|
||||
SDL_VIDEO_BlitXEP80_32((Uint32*)dest, screen, VIDEOMODE_actual_width, VIDEOMODE_src_width, VIDEOMODE_src_height, SDL_PALETTE_buffer.bpp32);
|
||||
else
|
||||
SDL_VIDEO_BlitXEP80_16((Uint32*)dest, screen, VIDEOMODE_actual_width / 2, VIDEOMODE_src_width, VIDEOMODE_src_height, SDL_PALETTE_buffer.bpp16);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PBI_PROTO80
|
||||
static void DisplayProto80(GLvoid *dest)
|
||||
{
|
||||
int first_column = (VIDEOMODE_src_offset_left+7) / 8;
|
||||
int last_column = (VIDEOMODE_src_offset_left + VIDEOMODE_src_width) / 8;
|
||||
int first_line = VIDEOMODE_src_offset_top;
|
||||
int last_line = first_line + VIDEOMODE_src_height;
|
||||
if (bpp_32)
|
||||
SDL_VIDEO_BlitProto80_32((Uint32*)dest, first_column, last_column, VIDEOMODE_actual_width, first_line, last_line, SDL_PALETTE_buffer.bpp32);
|
||||
else
|
||||
SDL_VIDEO_BlitProto80_16((Uint32*)dest, first_column, last_column, VIDEOMODE_actual_width/2, first_line, last_line, SDL_PALETTE_buffer.bpp16);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AF80
|
||||
static void DisplayAF80(GLvoid *dest)
|
||||
{
|
||||
int first_column = (VIDEOMODE_src_offset_left+7) / 8;
|
||||
int last_column = (VIDEOMODE_src_offset_left + VIDEOMODE_src_width) / 8;
|
||||
int first_line = VIDEOMODE_src_offset_top;
|
||||
int last_line = first_line + VIDEOMODE_src_height;
|
||||
static int AF80Frame = 0;
|
||||
int blink;
|
||||
AF80Frame++;
|
||||
if (AF80Frame == 60) AF80Frame = 0;
|
||||
blink = AF80Frame >= 30;
|
||||
if (bpp_32)
|
||||
SDL_VIDEO_BlitAF80_32((Uint32*)dest, first_column, last_column, VIDEOMODE_actual_width, first_line, last_line, blink, SDL_PALETTE_buffer.bpp32);
|
||||
else
|
||||
SDL_VIDEO_BlitAF80_16((Uint32*)dest, first_column, last_column, VIDEOMODE_actual_width/2, first_line, last_line, blink, SDL_PALETTE_buffer.bpp16);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BIT3
|
||||
static void DisplayBIT3(GLvoid *dest)
|
||||
{
|
||||
int first_column = (VIDEOMODE_src_offset_left+7) / 8;
|
||||
int last_column = (VIDEOMODE_src_offset_left + VIDEOMODE_src_width) / 8;
|
||||
int first_line = VIDEOMODE_src_offset_top;
|
||||
int last_line = first_line + VIDEOMODE_src_height;
|
||||
static int BIT3Frame = 0;
|
||||
int blink;
|
||||
BIT3Frame++;
|
||||
if (BIT3Frame == 60) BIT3Frame = 0;
|
||||
blink = BIT3Frame >= 30;
|
||||
if (bpp_32)
|
||||
SDL_VIDEO_BlitBIT3_32((Uint32*)dest, first_column, last_column, VIDEOMODE_actual_width, first_line, last_line, blink, SDL_PALETTE_buffer.bpp32);
|
||||
else
|
||||
SDL_VIDEO_BlitBIT3_16((Uint32*)dest, first_column, last_column, VIDEOMODE_actual_width/2, first_line, last_line, blink, SDL_PALETTE_buffer.bpp16);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SDL_VIDEO_GL_DisplayScreen(void)
|
||||
{
|
||||
gl.BindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
if (SDL_VIDEO_GL_pbo) {
|
||||
GLvoid *ptr;
|
||||
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, screen_pbo);
|
||||
ptr = gl.MapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
(*blit_funcs[SDL_VIDEO_current_display_mode])(ptr);
|
||||
gl.UnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
|
||||
gl.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEOMODE_actual_width, VIDEOMODE_src_height,
|
||||
pixel_formats[SDL_VIDEO_GL_pixel_format].format, pixel_formats[SDL_VIDEO_GL_pixel_format].type,
|
||||
NULL);
|
||||
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
|
||||
} else {
|
||||
(*blit_funcs[SDL_VIDEO_current_display_mode])(screen_texture);
|
||||
gl.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEOMODE_actual_width, VIDEOMODE_src_height,
|
||||
pixel_formats[SDL_VIDEO_GL_pixel_format].format, pixel_formats[SDL_VIDEO_GL_pixel_format].type,
|
||||
screen_texture);
|
||||
}
|
||||
gl.CallList(screen_dlist);
|
||||
SDL_GL_SwapBuffers();
|
||||
}
|
||||
|
||||
int SDL_VIDEO_GL_ReadConfig(char *option, char *parameters)
|
||||
{
|
||||
if (strcmp(option, "PIXEL_FORMAT") == 0) {
|
||||
int i = CFG_MatchTextParameter(parameters, pixel_format_cfg_strings, SDL_VIDEO_GL_PIXEL_FORMAT_SIZE);
|
||||
if (i < 0)
|
||||
return FALSE;
|
||||
SDL_VIDEO_GL_pixel_format = i;
|
||||
}
|
||||
else if (strcmp(option, "BILINEAR_FILTERING") == 0)
|
||||
return (SDL_VIDEO_GL_filtering = Util_sscanbool(parameters)) != -1;
|
||||
else if (strcmp(option, "OPENGL_PBO") == 0)
|
||||
return (SDL_VIDEO_GL_pbo = Util_sscanbool(parameters)) != -1;
|
||||
else
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_WriteConfig(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "PIXEL_FORMAT=%s\n", pixel_format_cfg_strings[SDL_VIDEO_GL_pixel_format]);
|
||||
fprintf(fp, "BILINEAR_FILTERING=%d\n", SDL_VIDEO_GL_filtering);
|
||||
fprintf(fp, "OPENGL_PBO=%d\n", SDL_VIDEO_GL_pbo);
|
||||
}
|
||||
|
||||
/* Loads the OpenGL library. Return TRUE on success, FALSE on failure. */
|
||||
static int InitGlLibrary(void)
|
||||
{
|
||||
if (SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) != 0) {
|
||||
Log_print("Cannot use OpenGL - unable to set GL attribute: %s\n",SDL_GetError());
|
||||
return FALSE;
|
||||
}
|
||||
if (SDL_GL_LoadLibrary(library_path) < 0) {
|
||||
Log_print("Cannot use OpenGL - unable to dynamically open OpenGL library: %s\n",SDL_GetError());
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_InitSDL(void)
|
||||
{
|
||||
SDL_VIDEO_opengl_available = InitGlLibrary();
|
||||
}
|
||||
|
||||
int SDL_VIDEO_GL_Initialise(int *argc, char *argv[])
|
||||
{
|
||||
int i, j;
|
||||
int help_only = FALSE;
|
||||
|
||||
for (i = j = 1; i < *argc; i++) {
|
||||
int i_a = (i + 1 < *argc); /* is argument available? */
|
||||
int a_m = FALSE; /* error, argument missing! */
|
||||
int a_i = FALSE; /* error, argument invalid! */
|
||||
|
||||
if (strcmp(argv[i], "-pixel-format") == 0) {
|
||||
if (i_a) {
|
||||
if ((SDL_VIDEO_GL_pixel_format = CFG_MatchTextParameter(argv[++i], pixel_format_cfg_strings, SDL_VIDEO_GL_PIXEL_FORMAT_SIZE)) < 0)
|
||||
a_i = TRUE;
|
||||
}
|
||||
else a_m = TRUE;
|
||||
}
|
||||
else if (strcmp(argv[i], "-bilinear-filter") == 0)
|
||||
SDL_VIDEO_GL_filtering = TRUE;
|
||||
else if (strcmp(argv[i], "-no-bilinear-filter") == 0)
|
||||
SDL_VIDEO_GL_filtering = FALSE;
|
||||
else if (strcmp(argv[i], "-pbo") == 0)
|
||||
SDL_VIDEO_GL_pbo = TRUE;
|
||||
else if (strcmp(argv[i], "-no-pbo") == 0)
|
||||
SDL_VIDEO_GL_pbo = FALSE;
|
||||
else if (strcmp(argv[i], "-opengl-lib") == 0) {
|
||||
if (i_a)
|
||||
library_path = argv[++i];
|
||||
else a_m = TRUE;
|
||||
}
|
||||
else {
|
||||
if (strcmp(argv[i], "-help") == 0) {
|
||||
help_only = TRUE;
|
||||
Log_print("\t-pixel-format bgr16|rgb16|bgra32|argb32");
|
||||
Log_print("\t Set internal pixel format (affects performance)");
|
||||
Log_print("\t-bilinear-filter Enable OpenGL bilinear filtering");
|
||||
Log_print("\t-no-bilinear-filter Disable OpenGL bilinear filtering");
|
||||
Log_print("\t-pbo Use OpenGL Pixel Buffer Objects if available");
|
||||
Log_print("\t-no-pbo Don't use OpenGL Pixel Buffer Objects");
|
||||
Log_print("\t-opengl-lib <path> Use a custom OpenGL shared library");
|
||||
}
|
||||
argv[j++] = argv[i];
|
||||
}
|
||||
if (a_m) {
|
||||
Log_print("Missing argument for '%s'", argv[i]);
|
||||
return FALSE;
|
||||
} else if (a_i) {
|
||||
Log_print("Invalid argument for '%s'", argv[--i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
*argc = j;
|
||||
|
||||
if (help_only)
|
||||
return TRUE;
|
||||
|
||||
bpp_32 = SDL_VIDEO_GL_pixel_format >= SDL_VIDEO_GL_PIXEL_FORMAT_BGRA32;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_SetPixelFormat(int value)
|
||||
{
|
||||
SDL_VIDEO_GL_pixel_format = value;
|
||||
if (SDL_VIDEO_screen != NULL && (SDL_VIDEO_screen->flags & SDL_OPENGL) == SDL_OPENGL) {
|
||||
int new_bpp_32 = value >= SDL_VIDEO_GL_PIXEL_FORMAT_BGRA32;
|
||||
if (new_bpp_32 != bpp_32)
|
||||
{
|
||||
FreeTexture();
|
||||
bpp_32 = new_bpp_32;
|
||||
AllocTexture();
|
||||
}
|
||||
UpdatePaletteLookup(SDL_VIDEO_current_display_mode);
|
||||
InitGlTextures();
|
||||
CleanDisplayTexture();
|
||||
}
|
||||
else
|
||||
bpp_32 = value;
|
||||
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_TogglePixelFormat(void)
|
||||
{
|
||||
SDL_VIDEO_GL_SetPixelFormat((SDL_VIDEO_GL_pixel_format + 1) % SDL_VIDEO_GL_PIXEL_FORMAT_SIZE);
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_SetFiltering(int value)
|
||||
{
|
||||
SDL_VIDEO_GL_filtering = value;
|
||||
if (SDL_VIDEO_screen != NULL && (SDL_VIDEO_screen->flags & SDL_OPENGL) == SDL_OPENGL) {
|
||||
GLint filtering = value ? GL_LINEAR : GL_NEAREST;
|
||||
gl.BindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
||||
SetSubpixelShifts();
|
||||
SetGlDisplayList();
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_ToggleFiltering(void)
|
||||
{
|
||||
SDL_VIDEO_GL_SetFiltering(!SDL_VIDEO_GL_filtering);
|
||||
}
|
||||
|
||||
int SDL_VIDEO_GL_SetPbo(int value)
|
||||
{
|
||||
if (SDL_VIDEO_screen != NULL && (SDL_VIDEO_screen->flags & SDL_OPENGL) == SDL_OPENGL) {
|
||||
/* Return false if PBOs are requested but not available. */
|
||||
if (value && !pbo_available)
|
||||
return FALSE;
|
||||
CleanGlContext();
|
||||
FreeTexture();
|
||||
SDL_VIDEO_GL_pbo = value;
|
||||
InitGlContext();
|
||||
AllocTexture();
|
||||
InitGlTextures();
|
||||
SetGlDisplayList();
|
||||
CleanDisplayTexture();
|
||||
}
|
||||
else
|
||||
SDL_VIDEO_GL_pbo = value;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int SDL_VIDEO_GL_TogglePbo(void)
|
||||
{
|
||||
return SDL_VIDEO_GL_SetPbo(!SDL_VIDEO_GL_pbo);
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_ScanlinesPercentageChanged(void)
|
||||
{
|
||||
if (SDL_VIDEO_screen != NULL && (SDL_VIDEO_screen->flags & SDL_OPENGL) == SDL_OPENGL) {
|
||||
SetSubpixelShifts();
|
||||
SetGlDisplayList();
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_VIDEO_GL_InterpolateScanlinesChanged(void)
|
||||
{
|
||||
if (SDL_VIDEO_screen != NULL && (SDL_VIDEO_screen->flags & SDL_OPENGL) == SDL_OPENGL) {
|
||||
GLint filtering = SDL_VIDEO_interpolate_scanlines ? GL_LINEAR : GL_NEAREST;
|
||||
gl.BindTexture(GL_TEXTURE_2D, textures[1]);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
||||
SetSubpixelShifts();
|
||||
SetGlDisplayList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#ifndef SDL_VIDEO_GL_H_
|
||||
#define SDL_VIDEO_GL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include "videomode.h"
|
||||
|
||||
/* Get/set texture pixel format. On some video cards, either of these is faster. */
|
||||
enum {
|
||||
SDL_VIDEO_GL_PIXEL_FORMAT_BGR16,
|
||||
SDL_VIDEO_GL_PIXEL_FORMAT_RGB16,
|
||||
SDL_VIDEO_GL_PIXEL_FORMAT_BGRA32,
|
||||
SDL_VIDEO_GL_PIXEL_FORMAT_ARGB32,
|
||||
/* Number of values in enumerator */
|
||||
SDL_VIDEO_GL_PIXEL_FORMAT_SIZE
|
||||
};
|
||||
/* Call SDL_VIDEO_GL_SetPixelFormat() after changing this variable. */
|
||||
extern int SDL_VIDEO_GL_pixel_format;
|
||||
void SDL_VIDEO_GL_SetPixelFormat(int value);
|
||||
void SDL_VIDEO_GL_TogglePixelFormat(void);
|
||||
|
||||
/* Returns parameters of the current display pixel format. Used when computing
|
||||
lookup tables used for blitting the Atari screen to display surface. */
|
||||
void SDL_VIDEO_GL_GetPixelFormat(PLATFORM_pixel_format_t *format);
|
||||
/* Convert a table of RGB values, PALETTE, of size SIZE, to a display's native
|
||||
format and store it in the lookup table DEST. */
|
||||
void SDL_VIDEO_GL_MapRGB(void *dest, int const *palette, int size);
|
||||
|
||||
/* Get/set bilinear filtering. */
|
||||
/* Call VIDEOMODE_Update() after changing this variable, or use SDL_VIDEO_GL_SetFiltering() instead. */
|
||||
extern int SDL_VIDEO_GL_filtering;
|
||||
void SDL_VIDEO_GL_SetFiltering(int value);
|
||||
void SDL_VIDEO_GL_ToggleFiltering(void);
|
||||
|
||||
/* Get/set usage of Pixel Buffer Objects if available. */
|
||||
/* Call VIDEOMODE_Update() after changing this variable, or use SDL_VIDEO_GL_SetPbo() instead. */
|
||||
extern int SDL_VIDEO_GL_pbo;
|
||||
/* If PBOs are requested but not available, these functions return FALSE. Note: Testing for
|
||||
availibility of PBOs is only possible when OpenGL is active. If the host doesn't support PBOs
|
||||
but OpenGL mode is not active, the functions will return TRUE. */
|
||||
int SDL_VIDEO_GL_SetPbo(int value);
|
||||
int SDL_VIDEO_GL_TogglePbo(void);
|
||||
|
||||
void SDL_VIDEO_GL_ScanlinesPercentageChanged(void);
|
||||
void SDL_VIDEO_GL_InterpolateScanlinesChanged(void);
|
||||
|
||||
/* Called when switching back to software mode. Cleans the OpenGL context and frees structures. */
|
||||
void SDL_VIDEO_GL_Cleanup(void);
|
||||
|
||||
void SDL_VIDEO_GL_DisplayScreen(void);
|
||||
void SDL_VIDEO_GL_PaletteUpdate(void);
|
||||
int SDL_VIDEO_GL_SetVideoMode(VIDEOMODE_resolution_t const *res, int windowed, VIDEOMODE_MODE_t mode, int rotate90);
|
||||
int SDL_VIDEO_GL_SupportsVideomode(VIDEOMODE_MODE_t mode, int stretch, int rotate90);
|
||||
|
||||
int SDL_VIDEO_GL_ReadConfig(char *option, char *parameters);
|
||||
void SDL_VIDEO_GL_WriteConfig(FILE *fp);
|
||||
int SDL_VIDEO_GL_Initialise(int *argc, char *argv[]);
|
||||
|
||||
/* Initialise SDL GL subsystem. Must be called after SDL video initialisation
|
||||
(SDL_VIDEO_InitSDL()). */
|
||||
void SDL_VIDEO_GL_InitSDL(void);
|
||||
|
||||
#endif /* SDL_VIDEO_GL_H_ */
|
||||
@@ -0,0 +1,881 @@
|
||||
/*
|
||||
* sdl/video_sw.c - SDL library specific port code - software-based video display
|
||||
*
|
||||
* Copyright (c) 2001-2002 Jacek Poplawski
|
||||
* Copyright (C) 2001-2010 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Atari800 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#include "af80.h"
|
||||
#include "bit3.h"
|
||||
#include "artifact.h"
|
||||
#include "atari.h"
|
||||
#include "colours.h"
|
||||
#include "config.h"
|
||||
#include "filter_ntsc.h"
|
||||
#include "log.h"
|
||||
#include "pbi_proto80.h"
|
||||
#ifdef PAL_BLENDING
|
||||
#include "pal_blending.h"
|
||||
#endif /* PAL_BLENDING */
|
||||
#include "platform.h"
|
||||
#include "screen.h"
|
||||
#include "videomode.h"
|
||||
#include "xep80.h"
|
||||
#include "xep80_fonts.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "sdl/palette.h"
|
||||
#include "sdl/video.h"
|
||||
#include "sdl/video_sw.h"
|
||||
|
||||
static int fullscreen = 1;
|
||||
|
||||
int SDL_VIDEO_SW_bpp = 0;
|
||||
|
||||
static void DisplayWithoutScaling(void);
|
||||
static void DisplayWithScaling(void);
|
||||
static void DisplayRotated(void);
|
||||
#ifdef NTSC_FILTER
|
||||
static void DisplayNTSCEmu(void);
|
||||
#endif
|
||||
#ifdef XEP80_EMULATION
|
||||
static void DisplayXEP80(void);
|
||||
#endif
|
||||
#ifdef PBI_PROTO80
|
||||
static void DisplayProto80(void);
|
||||
#endif
|
||||
#ifdef AF80
|
||||
static void DisplayAF80(void);
|
||||
#endif
|
||||
#ifdef BIT3
|
||||
static void DisplayBIT3(void);
|
||||
#endif
|
||||
#ifdef PAL_BLENDING
|
||||
static void DisplayPalBlending(void);
|
||||
static void DisplayPalBlendingScaled(void);
|
||||
#endif /* PAL_BLENDING */
|
||||
|
||||
static void (*blit_funcs[VIDEOMODE_MODE_SIZE])(void) = {
|
||||
&DisplayWithoutScaling
|
||||
#ifdef NTSC_FILTER
|
||||
,&DisplayNTSCEmu
|
||||
#endif
|
||||
#ifdef XEP80_EMULATION
|
||||
,&DisplayXEP80
|
||||
#endif
|
||||
#ifdef PBI_PROTO80
|
||||
,&DisplayProto80
|
||||
#endif
|
||||
#ifdef AF80
|
||||
,&DisplayAF80
|
||||
#endif
|
||||
#ifdef BIT3
|
||||
,&DisplayBIT3
|
||||
#endif
|
||||
};
|
||||
|
||||
static void Set8BitPalette(VIDEOMODE_MODE_t mode)
|
||||
{
|
||||
int *pal = SDL_PALETTE_tab[mode].palette;
|
||||
int size = SDL_PALETTE_tab[mode].size;
|
||||
SDL_Color colors[256];
|
||||
int i, rgb;
|
||||
for (i = 0; i < size; i++) {
|
||||
rgb = pal[i];
|
||||
colors[i].r = (rgb & 0x00ff0000) >> 16;
|
||||
colors[i].g = (rgb & 0x0000ff00) >> 8;
|
||||
colors[i].b = (rgb & 0x000000ff) >> 0;
|
||||
}
|
||||
|
||||
/* As the data that will be written to SDL_VIDEO_screen is already palettised,
|
||||
SDL_SetPalette shouldn't modify the surface's logical palette (so no
|
||||
SDL_LOGPAL here). Adding SDL_LOGPAL would break the palette when running
|
||||
with DirectX video driver in 8bpp fullscreen videomode on Intel GMA 3100. */
|
||||
SDL_SetPalette(SDL_VIDEO_screen, SDL_PHYSPAL, colors, 0, 256);
|
||||
}
|
||||
|
||||
void SDL_VIDEO_SW_GetPixelFormat(PLATFORM_pixel_format_t *format)
|
||||
{
|
||||
format->bpp = SDL_VIDEO_SW_bpp;
|
||||
format->rmask = SDL_VIDEO_screen->format->Rmask;
|
||||
format->gmask = SDL_VIDEO_screen->format->Gmask;
|
||||
format->bmask = SDL_VIDEO_screen->format->Bmask;
|
||||
}
|
||||
|
||||
void SDL_VIDEO_SW_MapRGB(void *dest, int const *palette, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
Uint32 c = SDL_MapRGB(SDL_VIDEO_screen->format,
|
||||
(palette[i] & 0x00ff0000) >> 16,
|
||||
(palette[i] & 0x0000ff00) >> 8,
|
||||
(palette[i] & 0x000000ff));
|
||||
switch (SDL_VIDEO_screen->format->BitsPerPixel) {
|
||||
case 16:
|
||||
((UWORD *)dest)[i] = (UWORD) c;
|
||||
break;
|
||||
case 32:
|
||||
((ULONG *)dest)[i] = (ULONG) c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdatePaletteLookup(VIDEOMODE_MODE_t mode)
|
||||
{
|
||||
if (SDL_VIDEO_screen->format->BitsPerPixel == 8)
|
||||
Set8BitPalette(mode);
|
||||
else
|
||||
SDL_VIDEO_UpdatePaletteLookup(mode, SDL_VIDEO_screen->format->BitsPerPixel == 32);
|
||||
}
|
||||
|
||||
void SDL_VIDEO_SW_PaletteUpdate(void)
|
||||
{
|
||||
UpdatePaletteLookup(SDL_VIDEO_current_display_mode);
|
||||
}
|
||||
|
||||
static void ModeInfo(void)
|
||||
{
|
||||
const char *fullstring = fullscreen ? "fullscreen" : "windowed";
|
||||
const char *vsyncstring = (SDL_VIDEO_screen->flags & SDL_DOUBLEBUF) ? "with vsync" : "without vsync";
|
||||
Log_print("Video Mode: %dx%dx%d %s %s", SDL_VIDEO_screen->w, SDL_VIDEO_screen->h,
|
||||
SDL_VIDEO_screen->format->BitsPerPixel, fullstring, vsyncstring);
|
||||
}
|
||||
|
||||
static void SetVideoMode(int w, int h, int bpp)
|
||||
{
|
||||
Uint32 flags = (fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE)
|
||||
| SDL_HWPALETTE;
|
||||
if (SDL_VIDEO_vsync)
|
||||
flags |= SDL_HWSURFACE | SDL_DOUBLEBUF;
|
||||
|
||||
SDL_VIDEO_screen = SDL_SetVideoMode(w, h, bpp, flags);
|
||||
if (SDL_VIDEO_screen == NULL) {
|
||||
/* Some SDL_SetVideoMode errors can be averted by reinitialising the SDL video subsystem. */
|
||||
Log_print("Setting video mode: %dx%dx%d failed: %s. Reinitialising video.", w, h, bpp, SDL_GetError());
|
||||
SDL_VIDEO_ReinitSDL();
|
||||
SDL_VIDEO_screen = SDL_SetVideoMode(w, h, bpp, flags);
|
||||
if (SDL_VIDEO_screen == NULL) {
|
||||
Log_print("Setting Video Mode: %dx%dx%d failed: %s", w, h, bpp, SDL_GetError());
|
||||
Log_flushlog();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
SDL_VIDEO_width = SDL_VIDEO_screen->w;
|
||||
SDL_VIDEO_height = SDL_VIDEO_screen->h;
|
||||
/* When vsync is off, set its availability to TRUE. Otherwise check if
|
||||
SDL_DOUBLEBUF is supported by the screen. */
|
||||
SDL_VIDEO_vsync_available = !SDL_VIDEO_vsync || (SDL_VIDEO_screen->flags & SDL_DOUBLEBUF);
|
||||
ModeInfo();
|
||||
}
|
||||
|
||||
void SDL_VIDEO_SW_SetVideoMode(VIDEOMODE_resolution_t const *res, int windowed, VIDEOMODE_MODE_t mode, int rotate90)
|
||||
{
|
||||
int old_bpp = SDL_VIDEO_screen == NULL ? 0 : SDL_VIDEO_screen->format->BitsPerPixel;
|
||||
|
||||
if (SDL_VIDEO_SW_bpp == 0) {
|
||||
/* Autodetect bpp */
|
||||
if ((SDL_VIDEO_native_bpp != 8) && (SDL_VIDEO_native_bpp != 16) && (SDL_VIDEO_native_bpp != 32)) {
|
||||
Log_print("Native BPP of %i not supported, setting 8bit mode (slow conversion)", SDL_VIDEO_native_bpp);
|
||||
SDL_VIDEO_SW_bpp = 8;
|
||||
} else
|
||||
SDL_VIDEO_SW_bpp = SDL_VIDEO_native_bpp;
|
||||
}
|
||||
|
||||
if ((rotate90 && SDL_VIDEO_SW_bpp != 16) ||
|
||||
((0
|
||||
#ifdef NTSC_FILTER
|
||||
|| mode == VIDEOMODE_MODE_NTSC_FILTER
|
||||
#endif
|
||||
#ifdef PAL_BLENDING
|
||||
|| (mode == VIDEOMODE_MODE_NORMAL && ARTIFACT_mode == ARTIFACT_PAL_BLEND)
|
||||
#endif /* PAL_BLENDING */
|
||||
) && SDL_VIDEO_SW_bpp != 16 && SDL_VIDEO_SW_bpp != 32)) {
|
||||
/* Rotate90 supports only 16bpp; NTSC filter and PAL blending don't support 8bpp. */
|
||||
SDL_VIDEO_SW_bpp = 16;
|
||||
}
|
||||
|
||||
/* Call SetVideoMode only when there was change in width, height, bpp, windowed/fullscreen, or vsync. */
|
||||
if (SDL_VIDEO_screen == NULL || SDL_VIDEO_screen->w != res->width || SDL_VIDEO_screen->h != res->height || old_bpp != SDL_VIDEO_SW_bpp ||
|
||||
fullscreen == windowed || (SDL_VIDEO_vsync && SDL_VIDEO_vsync_available) != ((SDL_VIDEO_screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)) {
|
||||
fullscreen = !windowed;
|
||||
SetVideoMode(res->width, res->height, SDL_VIDEO_SW_bpp);
|
||||
}
|
||||
|
||||
UpdatePaletteLookup(mode);
|
||||
|
||||
/* Clear the screen. */
|
||||
SDL_FillRect(SDL_VIDEO_screen, NULL, 0);
|
||||
SDL_Flip(SDL_VIDEO_screen);
|
||||
if (SDL_VIDEO_vsync_available)
|
||||
/* Also clear the backbuffer. */
|
||||
SDL_FillRect(SDL_VIDEO_screen, NULL, 0);
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE); /* hide mouse cursor */
|
||||
|
||||
if (mode == VIDEOMODE_MODE_NORMAL) {
|
||||
if (rotate90)
|
||||
blit_funcs[0] = &DisplayRotated;
|
||||
#ifdef PAL_BLENDING
|
||||
else if (ARTIFACT_mode == ARTIFACT_PAL_BLEND) {
|
||||
if (VIDEOMODE_src_width == VIDEOMODE_dest_width && VIDEOMODE_src_height == VIDEOMODE_dest_height)
|
||||
blit_funcs[0] = &DisplayPalBlending;
|
||||
else
|
||||
blit_funcs[0] = &DisplayPalBlendingScaled;
|
||||
}
|
||||
#endif /* PAL_BLENDING */
|
||||
else if (VIDEOMODE_src_width == VIDEOMODE_dest_width && VIDEOMODE_src_height == VIDEOMODE_dest_height)
|
||||
blit_funcs[0] = &DisplayWithoutScaling;
|
||||
else
|
||||
blit_funcs[0] = &DisplayWithScaling;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_VIDEO_SW_SupportsVideomode(VIDEOMODE_MODE_t mode, int stretch, int rotate90)
|
||||
{
|
||||
if (mode == VIDEOMODE_MODE_NORMAL) {
|
||||
/* Normal mode doesn't support stretching together with rotation. */
|
||||
return !(stretch && rotate90);
|
||||
} else
|
||||
/* Other modes don't support stretching or rotation at all. */
|
||||
return !stretch && !rotate90;
|
||||
}
|
||||
|
||||
int SDL_VIDEO_SW_SetBpp(int value)
|
||||
{
|
||||
int old_value = SDL_VIDEO_SW_bpp;
|
||||
if (old_value != value) {
|
||||
SDL_VIDEO_SW_bpp = value;
|
||||
if (!VIDEOMODE_Update()) {
|
||||
SDL_VIDEO_SW_bpp = old_value;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int SDL_VIDEO_SW_ToggleBpp(void)
|
||||
{
|
||||
int new_bpp;
|
||||
switch (SDL_VIDEO_SW_bpp) {
|
||||
case 16:
|
||||
new_bpp = 32;
|
||||
break;
|
||||
case 32:
|
||||
new_bpp = 8;
|
||||
break;
|
||||
default: /* 0 or 8 */
|
||||
new_bpp = 16;
|
||||
}
|
||||
return SDL_VIDEO_SW_SetBpp(new_bpp);
|
||||
}
|
||||
|
||||
/* License of scanLines_16():*/
|
||||
/* This function has been altered from its original version */
|
||||
/* This license is a verbatim copy of the license of ZLib
|
||||
* http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses
|
||||
* This is a free software license, and compatible with the GPL. */
|
||||
/*****************************************************************************
|
||||
** Original Source: /cvsroot/bluemsx/blueMSX/Src/VideoRender/VideoRender.c,v
|
||||
**
|
||||
** Original Revision: 1.25
|
||||
**
|
||||
** Original Date: 2006/01/17 08:49:34
|
||||
**
|
||||
** More info: http://www.bluemsx.com
|
||||
**
|
||||
** Copyright (C) 2003-2004 Daniel Vik
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Modified version, which optionally uses interpolation (slower but better).
|
||||
Caution! This function assumes that the 16-bit screen format is 565
|
||||
(rrrrrggg gggbbbbb). */
|
||||
static void scanLines_16(void* pBuffer, int width, int height, int pitch, int scanLinesPct)
|
||||
{
|
||||
Uint32* pBuf = (Uint32*)(pBuffer)+pitch/sizeof(Uint32);
|
||||
Uint32* sBuf = (Uint32*)(pBuffer);
|
||||
Uint32* tBuf = (Uint32*)(pBuffer)+pitch*2/sizeof(Uint32);
|
||||
int w, h;
|
||||
static int prev_scanLinesPct;
|
||||
|
||||
pitch = pitch * 2 / (int)sizeof(Uint32);
|
||||
height /= 2;
|
||||
width /= 2;
|
||||
|
||||
if (scanLinesPct < 0) scanLinesPct = 0;
|
||||
if (scanLinesPct > 100) scanLinesPct = 100;
|
||||
|
||||
if (scanLinesPct == 100) {
|
||||
if (prev_scanLinesPct != 100) {
|
||||
/*clean dirty blank scanlines*/
|
||||
prev_scanLinesPct = 100;
|
||||
for (h = 0; h < height; h++) {
|
||||
memset(pBuf, 0, width * sizeof(Uint32));
|
||||
pBuf += pitch;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
prev_scanLinesPct = scanLinesPct;
|
||||
|
||||
|
||||
if (scanLinesPct == 0) {
|
||||
/* fill in blank scanlines */
|
||||
for (h = 0; h < height; h++) {
|
||||
memcpy(pBuf, sBuf, width * sizeof(Uint32));
|
||||
sBuf += pitch;
|
||||
pBuf += pitch;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDL_VIDEO_interpolate_scanlines) {
|
||||
scanLinesPct = (100-scanLinesPct) * 32 / 200;
|
||||
for (h = 0; h < height-1; h++) {
|
||||
for (w = 0; w < width; w++) {
|
||||
Uint32 pixel = sBuf[w];
|
||||
Uint32 pixel2 = tBuf[w];
|
||||
Uint32 a = ((((pixel & 0x07e0f81f)+(pixel2 & 0x07e0f81f)) * scanLinesPct) & 0xfc1f03e0) >> 5;
|
||||
Uint32 b = ((((pixel >> 5) & 0x07c0f83f)+((pixel2 >> 5) & 0x07c0f83f)) * scanLinesPct) & 0xf81f07e0;
|
||||
pBuf[w] = a | b;
|
||||
}
|
||||
sBuf += pitch;
|
||||
tBuf += pitch;
|
||||
pBuf += pitch;
|
||||
}
|
||||
} else {
|
||||
scanLinesPct = (100-scanLinesPct) * 32 / 100;
|
||||
for (h = 0; h < height; h++) {
|
||||
for (w = 0; w < width; w++) {
|
||||
Uint32 pixel = sBuf[w];
|
||||
Uint32 a = (((pixel & 0x07e0f81f) * scanLinesPct) & 0xfc1f03e0) >> 5;
|
||||
Uint32 b = (((pixel >> 5) & 0x07c0f83f) * scanLinesPct) & 0xf81f07e0;
|
||||
pBuf[w] = a | b;
|
||||
}
|
||||
sBuf += pitch;
|
||||
pBuf += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Modified version of scanLines_16, for 32-bit screen.
|
||||
Caution! This function assumes that the 32-bit screen format is ARGB
|
||||
(aaaaaaaa rrrrrrrr gggggggg bbbbbbbb). */
|
||||
static void scanLines_32(void* pBuffer, int width, int height, int pitch, int scanLinesPct)
|
||||
{
|
||||
Uint32* pBuf = (Uint32*)(pBuffer)+pitch/sizeof(Uint32);
|
||||
Uint32* sBuf = (Uint32*)(pBuffer);
|
||||
Uint32* tBuf = (Uint32*)(pBuffer)+pitch*2/sizeof(Uint32);
|
||||
int w, h;
|
||||
static int prev_scanLinesPct;
|
||||
|
||||
pitch = pitch * 2 / (int)sizeof(Uint32);
|
||||
height /= 2;
|
||||
|
||||
if (scanLinesPct < 0) scanLinesPct = 0;
|
||||
if (scanLinesPct > 100) scanLinesPct = 100;
|
||||
|
||||
if (scanLinesPct == 100) {
|
||||
if (prev_scanLinesPct != 100) {
|
||||
/*clean dirty blank scanlines*/
|
||||
prev_scanLinesPct = 100;
|
||||
for (h = 0; h < height; h++) {
|
||||
memset(pBuf, 0, width * sizeof(Uint32));
|
||||
pBuf += pitch;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
prev_scanLinesPct = scanLinesPct;
|
||||
|
||||
|
||||
if (scanLinesPct == 0) {
|
||||
/* fill in blank scanlines */
|
||||
for (h = 0; h < height; h++) {
|
||||
memcpy(pBuf, sBuf, width * sizeof(Uint32));
|
||||
sBuf += pitch;
|
||||
pBuf += pitch;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDL_VIDEO_interpolate_scanlines) {
|
||||
scanLinesPct = (100-scanLinesPct) * 256 / 200;
|
||||
for (h = 0; h < height-1; h++) {
|
||||
for (w = 0; w < width; w++) {
|
||||
Uint32 pixel = sBuf[w];
|
||||
Uint32 pixel2 = tBuf[w];
|
||||
Uint32 a = ((((pixel & 0x00ff00ff)+(pixel2 & 0x00ff00ff)) * scanLinesPct) & 0xff00ff00) >> 8;
|
||||
Uint32 b = ((((pixel & 0x0000ff00)+(pixel2 & 0x0000ff00)) >> 8) * scanLinesPct) & 0x0000ff00;
|
||||
pBuf[w] = a | b;
|
||||
}
|
||||
sBuf += pitch;
|
||||
tBuf += pitch;
|
||||
pBuf += pitch;
|
||||
}
|
||||
} else {
|
||||
scanLinesPct = (100-scanLinesPct) * 256 / 100;
|
||||
for (h = 0; h < height; h++) {
|
||||
for (w = 0; w < width; w++) {
|
||||
Uint32 pixel = sBuf[w];
|
||||
Uint32 a = (((pixel & 0x00ff00ff) * scanLinesPct) & 0xff00ff00) >> 8;
|
||||
Uint32 b = (((pixel & 0x0000ff00) >> 8) * scanLinesPct) & 0x0000ff00;
|
||||
pBuf[w] = a | b;
|
||||
}
|
||||
sBuf += pitch;
|
||||
pBuf += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef XEP80_EMULATION
|
||||
static void DisplayXEP80(void)
|
||||
{
|
||||
static int xep80Frame = 0;
|
||||
int pitch4 = SDL_VIDEO_screen->pitch / 2;
|
||||
UBYTE *screen;
|
||||
Uint8 *pixels = (Uint8 *) SDL_VIDEO_screen->pixels + SDL_VIDEO_screen->pitch * VIDEOMODE_dest_offset_top;
|
||||
xep80Frame++;
|
||||
if (xep80Frame == 60) xep80Frame = 0;
|
||||
if (xep80Frame > 29) {
|
||||
screen = XEP80_screen_1;
|
||||
}
|
||||
else {
|
||||
screen = XEP80_screen_2;
|
||||
}
|
||||
|
||||
screen += XEP80_SCRN_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left;
|
||||
switch (SDL_VIDEO_screen->format->BitsPerPixel) {
|
||||
case 8:
|
||||
pixels += VIDEOMODE_dest_offset_left;
|
||||
SDL_VIDEO_BlitXEP80_8((Uint32 *)pixels, screen, pitch4, VIDEOMODE_src_width, VIDEOMODE_src_height);
|
||||
break;
|
||||
case 16:
|
||||
pixels += VIDEOMODE_dest_offset_left * 2;
|
||||
SDL_VIDEO_BlitXEP80_16((Uint32 *)pixels, screen, pitch4, VIDEOMODE_src_width, VIDEOMODE_src_height, SDL_PALETTE_buffer.bpp16);
|
||||
scanLines_16((void *)pixels, VIDEOMODE_dest_width, VIDEOMODE_dest_height, SDL_VIDEO_screen->pitch, SDL_VIDEO_scanlines_percentage);
|
||||
break;
|
||||
default:
|
||||
pixels += VIDEOMODE_dest_offset_left * 4;
|
||||
SDL_VIDEO_BlitXEP80_32((Uint32 *)pixels, screen, pitch4, VIDEOMODE_src_width, VIDEOMODE_src_height, SDL_PALETTE_buffer.bpp32);
|
||||
scanLines_32((void *)pixels, VIDEOMODE_dest_width, VIDEOMODE_dest_height, SDL_VIDEO_screen->pitch, SDL_VIDEO_scanlines_percentage);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NTSC_FILTER
|
||||
static void DisplayNTSCEmu(void)
|
||||
{
|
||||
Uint8 *pixels = (Uint8*)SDL_VIDEO_screen->pixels + SDL_VIDEO_screen->pitch * VIDEOMODE_dest_offset_top;
|
||||
switch (SDL_VIDEO_screen->format->BitsPerPixel) {
|
||||
case 16:
|
||||
pixels += VIDEOMODE_dest_offset_left * 2;
|
||||
/* blit atari image, doubled vertically */
|
||||
atari_ntsc_blit_rgb16(FILTER_NTSC_emu,
|
||||
(ATARI_NTSC_IN_T *) ((UBYTE *)Screen_atari + Screen_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left),
|
||||
Screen_WIDTH,
|
||||
VIDEOMODE_src_width,
|
||||
VIDEOMODE_src_height,
|
||||
pixels,
|
||||
SDL_VIDEO_screen->pitch * 2);
|
||||
scanLines_16((void *)pixels, VIDEOMODE_dest_width, VIDEOMODE_dest_height, SDL_VIDEO_screen->pitch, SDL_VIDEO_scanlines_percentage);
|
||||
break;
|
||||
case 32:
|
||||
pixels += VIDEOMODE_dest_offset_left * 4;
|
||||
atari_ntsc_blit_argb32(FILTER_NTSC_emu,
|
||||
(ATARI_NTSC_IN_T *) ((UBYTE *)Screen_atari + Screen_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left),
|
||||
Screen_WIDTH,
|
||||
VIDEOMODE_src_width,
|
||||
VIDEOMODE_src_height,
|
||||
pixels,
|
||||
SDL_VIDEO_screen->pitch * 2);
|
||||
scanLines_32((void *)pixels, VIDEOMODE_dest_width, VIDEOMODE_dest_height, SDL_VIDEO_screen->pitch, SDL_VIDEO_scanlines_percentage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PBI_PROTO80
|
||||
static void DisplayProto80(void)
|
||||
{
|
||||
int first_column = (VIDEOMODE_src_offset_left+7) / 8;
|
||||
int last_column = (VIDEOMODE_src_offset_left + VIDEOMODE_src_width) / 8;
|
||||
int first_line = VIDEOMODE_src_offset_top;
|
||||
int last_line = first_line + VIDEOMODE_src_height;
|
||||
int pitch4 = SDL_VIDEO_screen->pitch / 2;
|
||||
Uint8 *pixels = (Uint8*)SDL_VIDEO_screen->pixels + SDL_VIDEO_screen->pitch * VIDEOMODE_dest_offset_top;
|
||||
|
||||
|
||||
switch (SDL_VIDEO_screen->format->BitsPerPixel) {
|
||||
case 8:
|
||||
pixels += VIDEOMODE_dest_offset_left;
|
||||
SDL_VIDEO_BlitProto80_8((Uint32 *)pixels, first_column, last_column, pitch4, first_line, last_line);
|
||||
break;
|
||||
case 16:
|
||||
pixels += VIDEOMODE_dest_offset_left * 2;
|
||||
SDL_VIDEO_BlitProto80_16((Uint32 *)pixels, first_column, last_column, pitch4, first_line, last_line, SDL_PALETTE_buffer.bpp16);
|
||||
scanLines_16((void *)pixels, VIDEOMODE_dest_width, VIDEOMODE_dest_height, SDL_VIDEO_screen->pitch, SDL_VIDEO_scanlines_percentage);
|
||||
break;
|
||||
default:
|
||||
pixels += VIDEOMODE_dest_offset_left * 4;
|
||||
SDL_VIDEO_BlitProto80_32((Uint32 *)pixels, first_column, last_column, pitch4, first_line, last_line, SDL_PALETTE_buffer.bpp32);
|
||||
scanLines_32((void *)pixels, VIDEOMODE_dest_width, VIDEOMODE_dest_height, SDL_VIDEO_screen->pitch, SDL_VIDEO_scanlines_percentage);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AF80
|
||||
static void DisplayAF80(void)
|
||||
{
|
||||
int first_column = (VIDEOMODE_src_offset_left+7) / 8;
|
||||
int last_column = (VIDEOMODE_src_offset_left + VIDEOMODE_src_width) / 8;
|
||||
int first_line = VIDEOMODE_src_offset_top;
|
||||
int last_line = first_line + VIDEOMODE_src_height;
|
||||
int pitch4 = SDL_VIDEO_screen->pitch / 2;
|
||||
Uint8 *pixels = (Uint8*)SDL_VIDEO_screen->pixels + SDL_VIDEO_screen->pitch * VIDEOMODE_dest_offset_top;
|
||||
|
||||
static int AF80Frame = 0;
|
||||
int blink;
|
||||
AF80Frame++;
|
||||
if (AF80Frame == 60) AF80Frame = 0;
|
||||
blink = AF80Frame >= 30;
|
||||
|
||||
switch (SDL_VIDEO_screen->format->BitsPerPixel) {
|
||||
case 8:
|
||||
pixels += VIDEOMODE_dest_offset_left;
|
||||
SDL_VIDEO_BlitAF80_8((Uint32 *)pixels, first_column, last_column, pitch4, first_line, last_line, blink);
|
||||
break;
|
||||
case 16:
|
||||
pixels += VIDEOMODE_dest_offset_left * 2;
|
||||
SDL_VIDEO_BlitAF80_16((Uint32 *)pixels, first_column, last_column, pitch4, first_line, last_line, blink, SDL_PALETTE_buffer.bpp16);
|
||||
scanLines_16((void *)pixels, VIDEOMODE_dest_width, VIDEOMODE_dest_height, SDL_VIDEO_screen->pitch, SDL_VIDEO_scanlines_percentage);
|
||||
break;
|
||||
default:
|
||||
pixels += VIDEOMODE_dest_offset_left * 4;
|
||||
SDL_VIDEO_BlitAF80_32((Uint32 *)pixels, first_column, last_column, pitch4, first_line, last_line, blink, SDL_PALETTE_buffer.bpp32);
|
||||
scanLines_32((void *)pixels, VIDEOMODE_dest_width, VIDEOMODE_dest_height, SDL_VIDEO_screen->pitch, SDL_VIDEO_scanlines_percentage);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BIT3
|
||||
static void DisplayBIT3(void)
|
||||
{
|
||||
int first_column = (VIDEOMODE_src_offset_left+7) / 8;
|
||||
int last_column = (VIDEOMODE_src_offset_left + VIDEOMODE_src_width) / 8;
|
||||
int first_line = VIDEOMODE_src_offset_top;
|
||||
int last_line = first_line + VIDEOMODE_src_height;
|
||||
int pitch4 = SDL_VIDEO_screen->pitch / 2;
|
||||
Uint8 *pixels = (Uint8*)SDL_VIDEO_screen->pixels + SDL_VIDEO_screen->pitch * VIDEOMODE_dest_offset_top;
|
||||
|
||||
static int BIT3Frame = 0;
|
||||
int blink;
|
||||
BIT3Frame++;
|
||||
if (BIT3Frame == 60) BIT3Frame = 0;
|
||||
blink = BIT3Frame >= 30;
|
||||
|
||||
switch (SDL_VIDEO_screen->format->BitsPerPixel) {
|
||||
case 8:
|
||||
pixels += VIDEOMODE_dest_offset_left;
|
||||
SDL_VIDEO_BlitBIT3_8((Uint32 *)pixels, first_column, last_column, pitch4, first_line, last_line, blink);
|
||||
break;
|
||||
case 16:
|
||||
pixels += VIDEOMODE_dest_offset_left * 2;
|
||||
SDL_VIDEO_BlitBIT3_16((Uint32 *)pixels, first_column, last_column, pitch4, first_line, last_line, blink, SDL_PALETTE_buffer.bpp16);
|
||||
scanLines_16((void *)pixels, VIDEOMODE_dest_width, VIDEOMODE_dest_height, SDL_VIDEO_screen->pitch, SDL_VIDEO_scanlines_percentage);
|
||||
break;
|
||||
default:
|
||||
pixels += VIDEOMODE_dest_offset_left * 4;
|
||||
SDL_VIDEO_BlitBIT3_32((Uint32 *)pixels, first_column, last_column, pitch4, first_line, last_line, blink, SDL_PALETTE_buffer.bpp32);
|
||||
scanLines_32((void *)pixels, VIDEOMODE_dest_width, VIDEOMODE_dest_height, SDL_VIDEO_screen->pitch, SDL_VIDEO_scanlines_percentage);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void DisplayRotated(void)
|
||||
{
|
||||
unsigned int x, y;
|
||||
register Uint32 *start32 = (Uint32 *) SDL_VIDEO_screen->pixels + SDL_VIDEO_screen->pitch / 4 * VIDEOMODE_dest_offset_top + VIDEOMODE_dest_offset_left / 2;
|
||||
int pitch4 = SDL_VIDEO_screen->pitch / 4 - VIDEOMODE_dest_width / 2;
|
||||
UBYTE *screen = (UBYTE *)Screen_atari + Screen_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left;
|
||||
for (y = 0; y < VIDEOMODE_dest_height; y++) {
|
||||
for (x = 0; x < VIDEOMODE_dest_width / 2; x++) {
|
||||
Uint8 left = screen[Screen_WIDTH * (x * 2) + VIDEOMODE_src_width - y];
|
||||
Uint8 right = screen[Screen_WIDTH * (x * 2 + 1) + VIDEOMODE_src_width - y];
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
*start32++ = (SDL_PALETTE_buffer.bpp16[left] << 16) + SDL_PALETTE_buffer.bpp16[right];
|
||||
#else
|
||||
*start32++ = (SDL_PALETTE_buffer.bpp16[right] << 16) + SDL_PALETTE_buffer.bpp16[left];
|
||||
#endif
|
||||
}
|
||||
start32 += pitch4;
|
||||
}
|
||||
}
|
||||
|
||||
static void DisplayWithoutScaling(void)
|
||||
{
|
||||
int pitch4 = SDL_VIDEO_screen->pitch / 4;
|
||||
UBYTE *screen = (UBYTE *)Screen_atari + Screen_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left;
|
||||
Uint8 *pixels = (Uint8 *) SDL_VIDEO_screen->pixels + SDL_VIDEO_screen->pitch * VIDEOMODE_dest_offset_top;
|
||||
switch (SDL_VIDEO_screen->format->BitsPerPixel) {
|
||||
/* Possible values are 8, 16 and 32, as checked earlier in the
|
||||
* PLATFORM_SetVideoMode() function. */
|
||||
case 8:
|
||||
pixels += VIDEOMODE_dest_offset_left;
|
||||
SDL_VIDEO_BlitNormal8((Uint32 *)pixels, screen, pitch4, VIDEOMODE_src_width, VIDEOMODE_src_height);
|
||||
break;
|
||||
case 16:
|
||||
pixels += VIDEOMODE_dest_offset_left * 2;
|
||||
SDL_VIDEO_BlitNormal16((Uint32*)pixels, screen, pitch4, VIDEOMODE_src_width, VIDEOMODE_src_height, SDL_PALETTE_buffer.bpp16);
|
||||
break;
|
||||
default: /* SDL_VIDEO_screen->format->BitsPerPixel == 32 */
|
||||
pixels += VIDEOMODE_dest_offset_left * 4;
|
||||
SDL_VIDEO_BlitNormal32((Uint32 *)pixels, screen, pitch4, VIDEOMODE_src_width, VIDEOMODE_src_height, SDL_PALETTE_buffer.bpp32);
|
||||
}
|
||||
}
|
||||
|
||||
static void DisplayWithScaling(void)
|
||||
{
|
||||
register Uint32 quad;
|
||||
register int x;
|
||||
register Uint8 *screen = (UBYTE *)Screen_atari + Screen_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left;
|
||||
register Uint32 *pixels = (Uint32 *) SDL_VIDEO_screen->pixels;
|
||||
int i;
|
||||
int y = 0;
|
||||
int w1;
|
||||
int w = (VIDEOMODE_src_width) << 16;
|
||||
int h = (VIDEOMODE_src_height) << 16;
|
||||
register int dx = w / VIDEOMODE_dest_width;
|
||||
register int yy;
|
||||
int pos;
|
||||
int pitch4 = SDL_VIDEO_screen->pitch / 4;
|
||||
int dy = h / VIDEOMODE_dest_height;
|
||||
int init_x = (VIDEOMODE_src_width << 16) - 0x4000;
|
||||
|
||||
Uint8 c;
|
||||
|
||||
i = VIDEOMODE_dest_height;
|
||||
|
||||
switch (SDL_VIDEO_screen->format->BitsPerPixel) {
|
||||
/* Possible values are 8, 16 and 32, as checked earlier in the
|
||||
* PLATFORM_SetVideoMode() function. */
|
||||
case 8:
|
||||
pixels += pitch4 * VIDEOMODE_dest_offset_top + VIDEOMODE_dest_offset_left / 4;
|
||||
w1 = VIDEOMODE_dest_width / 4 - 1;
|
||||
while (i > 0) {
|
||||
x = init_x;
|
||||
pos = w1;
|
||||
yy = Screen_WIDTH * (y >> 16);
|
||||
while (pos >= 0) {
|
||||
quad = (screen[yy + (x >> 16)] << 24);
|
||||
x -= dx;
|
||||
quad += (screen[yy + (x >> 16)] << 16);
|
||||
x -= dx;
|
||||
quad += (screen[yy + (x >> 16)] << 8);
|
||||
x -= dx;
|
||||
quad += (screen[yy + (x >> 16)] << 0);
|
||||
x -= dx;
|
||||
|
||||
pixels[pos] = quad;
|
||||
pos--;
|
||||
|
||||
}
|
||||
pixels += pitch4;
|
||||
y += dy;
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
pixels += pitch4 * VIDEOMODE_dest_offset_top + VIDEOMODE_dest_offset_left / 2;
|
||||
w1 = VIDEOMODE_dest_width / 2 - 1;
|
||||
while (i > 0) {
|
||||
x = init_x;
|
||||
pos = w1;
|
||||
yy = Screen_WIDTH * (y >> 16);
|
||||
while (pos >= 0) {
|
||||
c = screen[yy + (x >> 16)];
|
||||
quad = SDL_PALETTE_buffer.bpp16[c] << 16;
|
||||
x -= dx;
|
||||
c = screen[yy + (x >> 16)];
|
||||
quad += SDL_PALETTE_buffer.bpp16[c];
|
||||
x -= dx;
|
||||
pixels[pos] = quad;
|
||||
pos--;
|
||||
}
|
||||
pixels += pitch4;
|
||||
y += dy;
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pixels += pitch4 * VIDEOMODE_dest_offset_top + VIDEOMODE_dest_offset_left;
|
||||
w1 = VIDEOMODE_dest_width - 1;
|
||||
/* SDL_VIDEO_screen->format->BitsPerPixel = 32 */
|
||||
while (i > 0) {
|
||||
x = init_x;
|
||||
pos = w1;
|
||||
yy = Screen_WIDTH * (y >> 16);
|
||||
while (pos >= 0) {
|
||||
c = screen[yy + (x >> 16)];
|
||||
quad = SDL_PALETTE_buffer.bpp32[c];
|
||||
x -= dx;
|
||||
pixels[pos] = quad;
|
||||
pos--;
|
||||
}
|
||||
pixels += pitch4;
|
||||
y += dy;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PAL_BLENDING
|
||||
static void DisplayPalBlending(void)
|
||||
{
|
||||
int pitch4 = SDL_VIDEO_screen->pitch / 4;
|
||||
UBYTE *screen = (UBYTE *)Screen_atari + Screen_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left;
|
||||
Uint8 *pixels = (Uint8 *) SDL_VIDEO_screen->pixels + SDL_VIDEO_screen->pitch * VIDEOMODE_dest_offset_top;
|
||||
switch (SDL_VIDEO_screen->format->BitsPerPixel) {
|
||||
/* Possible values are 8, 16 and 32, as checked earlier in the
|
||||
* PLATFORM_SetVideoMode() function. */
|
||||
case 16:
|
||||
pixels += VIDEOMODE_dest_offset_left * 2;
|
||||
PAL_BLENDING_Blit16((ULONG*)pixels, screen, pitch4, VIDEOMODE_src_width, VIDEOMODE_src_height, VIDEOMODE_src_offset_top % 2);
|
||||
break;
|
||||
default: /* SDL_VIDEO_screen->format->BitsPerPixel == 32 */
|
||||
pixels += VIDEOMODE_dest_offset_left * 4;
|
||||
PAL_BLENDING_Blit32((ULONG *)pixels, screen, pitch4, VIDEOMODE_src_width, VIDEOMODE_src_height, VIDEOMODE_src_offset_top % 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void DisplayPalBlendingScaled(void)
|
||||
{
|
||||
int pitch4 = SDL_VIDEO_screen->pitch / 4;
|
||||
Uint8 *screen = (UBYTE *)Screen_atari + Screen_WIDTH * VIDEOMODE_src_offset_top + VIDEOMODE_src_offset_left;
|
||||
Uint32 *pixels = (Uint32 *) SDL_VIDEO_screen->pixels;
|
||||
switch (SDL_VIDEO_screen->format->BitsPerPixel) {
|
||||
/* Possible values are 8, 16 and 32, as checked earlier in the
|
||||
* PLATFORM_SetVideoMode() function. */
|
||||
case 16:
|
||||
pixels += pitch4 * VIDEOMODE_dest_offset_top + VIDEOMODE_dest_offset_left / 2;
|
||||
PAL_BLENDING_BlitScaled16((ULONG*)pixels, screen, pitch4, VIDEOMODE_src_width, VIDEOMODE_src_height, VIDEOMODE_dest_width, VIDEOMODE_dest_height, VIDEOMODE_src_offset_top % 2);
|
||||
break;
|
||||
case 32:
|
||||
pixels += pitch4 * VIDEOMODE_dest_offset_top + VIDEOMODE_dest_offset_left;
|
||||
PAL_BLENDING_BlitScaled32((ULONG*)pixels, screen, pitch4, VIDEOMODE_src_width, VIDEOMODE_src_height, VIDEOMODE_dest_width, VIDEOMODE_dest_height, VIDEOMODE_src_offset_top % 2);
|
||||
}
|
||||
}
|
||||
#endif /* PAL_BLENDING */
|
||||
|
||||
void SDL_VIDEO_SW_DisplayScreen(void)
|
||||
{
|
||||
if (SDL_LockSurface(SDL_VIDEO_screen) != 0)
|
||||
/* When the window manager decides to switch the SDL display from
|
||||
fullscreen to windowed mode (eg. by minimising the window after the
|
||||
user pressed Alt+Tab in Windows), hardware surface gets disabled
|
||||
immediately. In such case surface locking will fail. When it happens,
|
||||
don't blit to screen as it would cause a segfault. When fullscreen
|
||||
mode gets re-enabled, surface locking will work again and screen
|
||||
displaying will be restored */
|
||||
return;
|
||||
/* Use function corresponding to the current_display_mode. */
|
||||
(*blit_funcs[SDL_VIDEO_current_display_mode])();
|
||||
SDL_UnlockSurface(SDL_VIDEO_screen);
|
||||
/* SDL_UpdateRect is faster than SDL_Flip for a software surface, because
|
||||
it copies only the used part of the screen. */
|
||||
if (SDL_VIDEO_screen->flags & SDL_DOUBLEBUF)
|
||||
SDL_Flip(SDL_VIDEO_screen);
|
||||
else
|
||||
SDL_UpdateRect(SDL_VIDEO_screen, VIDEOMODE_dest_offset_left, VIDEOMODE_dest_offset_top, VIDEOMODE_dest_width, VIDEOMODE_dest_height);
|
||||
}
|
||||
|
||||
int SDL_VIDEO_SW_ReadConfig(char *option, char *parameters)
|
||||
{
|
||||
if (strcmp(option, "VIDEO_BPP") == 0) {
|
||||
int value = Util_sscandec(parameters);
|
||||
if (value != 0 && value != 8 && value != 16 && value != 32)
|
||||
return FALSE;
|
||||
else
|
||||
SDL_VIDEO_SW_bpp = value;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SDL_VIDEO_SW_WriteConfig(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "VIDEO_BPP=%d\n", SDL_VIDEO_SW_bpp);
|
||||
}
|
||||
|
||||
int SDL_VIDEO_SW_Initialise(int *argc, char *argv[])
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = j = 1; i < *argc; i++) {
|
||||
int i_a = (i + 1 < *argc); /* is argument available? */
|
||||
int a_m = FALSE; /* error, argument missing! */
|
||||
if (strcmp(argv[i], "-bpp") == 0) {
|
||||
if (i_a) {
|
||||
SDL_VIDEO_SW_bpp = Util_sscandec(argv[++i]);
|
||||
if (SDL_VIDEO_SW_bpp != 0 && SDL_VIDEO_SW_bpp != 8 && SDL_VIDEO_SW_bpp != 16 && SDL_VIDEO_SW_bpp != 32) {
|
||||
Log_print("Invalid BPP value %s", argv[i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else a_m = TRUE;
|
||||
}
|
||||
else {
|
||||
if (strcmp(argv[i], "-help") == 0)
|
||||
Log_print("\t-bpp <num> Host color depth (0 = autodetect)");
|
||||
argv[j++] = argv[i];
|
||||
}
|
||||
|
||||
if (a_m) {
|
||||
Log_print("Missing argument for '%s'", argv[i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
*argc = j;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef SDL_VIDEO_SW_H_
|
||||
#define SDL_VIDEO_SW_H_
|
||||
|
||||
#include "platform.h"
|
||||
#include "videomode.h"
|
||||
|
||||
void SDL_VIDEO_SW_DisplayScreen(void);
|
||||
void SDL_VIDEO_SW_PaletteUpdate(void);
|
||||
void SDL_VIDEO_SW_SetVideoMode(VIDEOMODE_resolution_t const *res, int windowed, VIDEOMODE_MODE_t mode, int rotate90);
|
||||
int SDL_VIDEO_SW_SupportsVideomode(VIDEOMODE_MODE_t mode, int stretch, int rotate90);
|
||||
|
||||
/* Get/set videomode bits per pixel. */
|
||||
/* Call VIDEOMODE_Update() after changing this variable, or use SDL_VIDEO_SW_SetBpp() instead. */
|
||||
extern int SDL_VIDEO_SW_bpp;
|
||||
int SDL_VIDEO_SW_SetBpp(int value);
|
||||
int SDL_VIDEO_SW_ToggleBpp(void);
|
||||
|
||||
/* Returns parameters of the current display pixel format. Used when computing
|
||||
lookup tables used for blitting the Atari screen to display surface. */
|
||||
void SDL_VIDEO_SW_GetPixelFormat(PLATFORM_pixel_format_t *format);
|
||||
/* Convert a table of RGB values, PALETTE, of size SIZE, to a display's native
|
||||
format and store it in the lookup table DEST. */
|
||||
void SDL_VIDEO_SW_MapRGB(void *dest, int const *palette, int size);
|
||||
|
||||
/* Read/write to configuration file. */
|
||||
int SDL_VIDEO_SW_ReadConfig(char *option, char *parameters);
|
||||
void SDL_VIDEO_SW_WriteConfig(FILE *fp);
|
||||
|
||||
/* Initialisation and processing of command-line arguments. */
|
||||
int SDL_VIDEO_SW_Initialise(int *argc, char *argv[]);
|
||||
|
||||
#endif /* SDL_VIDEO_SW_H_ */
|
||||
Reference in New Issue
Block a user