2022-10-05 00:35:05 -07:00
|
|
|
#include "svga.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-09-15 02:38:23 -07:00
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <SDL.h>
|
|
|
|
|
2022-07-12 02:09:53 -07:00
|
|
|
#include "audio_engine.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "color.h"
|
2022-07-29 06:04:05 -07:00
|
|
|
#include "config.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "dinput.h"
|
|
|
|
#include "draw.h"
|
2022-05-21 11:30:25 -07:00
|
|
|
#include "interface.h"
|
2022-10-03 06:42:34 -07:00
|
|
|
#include "kb.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "memory.h"
|
|
|
|
#include "mmx.h"
|
2022-10-03 02:41:33 -07:00
|
|
|
#include "mouse.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "text_font.h"
|
2022-10-02 23:37:05 -07:00
|
|
|
#include "vcr.h"
|
2022-05-28 11:46:58 -07:00
|
|
|
#include "win32.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "window_manager.h"
|
|
|
|
#include "window_manager_private.h"
|
|
|
|
|
2022-09-23 05:43:44 -07:00
|
|
|
namespace fallout {
|
|
|
|
|
2022-10-04 03:15:54 -07:00
|
|
|
static bool createRenderer(int width, int height);
|
|
|
|
static void destroyRenderer();
|
2022-08-16 04:24:57 -07:00
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
// NOTE: This value is never set, so it's impossible to understand it's
|
|
|
|
// meaning.
|
|
|
|
//
|
|
|
|
// 0x51E2C4
|
|
|
|
void (*_update_palette_func)() = NULL;
|
|
|
|
|
|
|
|
// 0x51E2C8
|
|
|
|
bool gMmxEnabled = true;
|
|
|
|
|
|
|
|
// 0x51E2CC
|
|
|
|
bool gMmxProbed = false;
|
|
|
|
|
|
|
|
// 0x6AC7F0
|
|
|
|
unsigned short gSixteenBppPalette[256];
|
|
|
|
|
|
|
|
// screen rect
|
|
|
|
Rect _scr_size;
|
|
|
|
|
|
|
|
// 0x6ACA00
|
|
|
|
int gGreenMask;
|
|
|
|
|
|
|
|
// 0x6ACA04
|
|
|
|
int gRedMask;
|
|
|
|
|
|
|
|
// 0x6ACA08
|
|
|
|
int gBlueMask;
|
|
|
|
|
|
|
|
// 0x6ACA0C
|
|
|
|
int gBlueShift;
|
|
|
|
|
|
|
|
// 0x6ACA10
|
|
|
|
int gRedShift;
|
|
|
|
|
|
|
|
// 0x6ACA14
|
|
|
|
int gGreenShift;
|
|
|
|
|
|
|
|
// 0x6ACA18
|
|
|
|
void (*_scr_blit)(unsigned char* src, int src_pitch, int a3, int src_x, int src_y, int src_width, int src_height, int dest_x, int dest_y) = _GNW95_ShowRect;
|
|
|
|
|
|
|
|
// 0x6ACA1C
|
|
|
|
void (*_zero_mem)() = NULL;
|
|
|
|
|
|
|
|
// 0x6ACA20
|
|
|
|
bool gMmxSupported;
|
|
|
|
|
|
|
|
// FIXME: This buffer was supposed to be used as temporary place to store
|
|
|
|
// current palette while switching video modes (changing resolution). However
|
|
|
|
// the original game does not have UI to change video mode. Even if it did this
|
|
|
|
// buffer it too small to hold the entire palette, which require 256 * 3 bytes.
|
|
|
|
//
|
|
|
|
// 0x6ACA24
|
|
|
|
unsigned char gLastVideoModePalette[268];
|
|
|
|
|
2022-05-19 04:01:17 -07:00
|
|
|
SDL_Window* gSdlWindow = NULL;
|
|
|
|
SDL_Surface* gSdlSurface = NULL;
|
2022-07-12 00:10:23 -07:00
|
|
|
SDL_Renderer* gSdlRenderer = NULL;
|
|
|
|
SDL_Texture* gSdlTexture = NULL;
|
|
|
|
SDL_Surface* gSdlTextureSurface = NULL;
|
2022-05-19 04:01:17 -07:00
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
// 0x4CACD0
|
|
|
|
void mmxSetEnabled(bool a1)
|
|
|
|
{
|
|
|
|
if (!gMmxProbed) {
|
|
|
|
gMmxSupported = mmxIsSupported();
|
|
|
|
gMmxProbed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gMmxSupported) {
|
|
|
|
gMmxEnabled = a1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAD08
|
|
|
|
int _init_mode_320_200()
|
|
|
|
{
|
|
|
|
return _GNW95_init_mode_ex(320, 200, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAD40
|
|
|
|
int _init_mode_320_400()
|
|
|
|
{
|
|
|
|
return _GNW95_init_mode_ex(320, 400, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAD5C
|
|
|
|
int _init_mode_640_480_16()
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAD64
|
|
|
|
int _init_mode_640_480()
|
|
|
|
{
|
|
|
|
return _init_vesa_mode(640, 480);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAD94
|
|
|
|
int _init_mode_640_400()
|
|
|
|
{
|
|
|
|
return _init_vesa_mode(640, 400);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CADA8
|
|
|
|
int _init_mode_800_600()
|
|
|
|
{
|
|
|
|
return _init_vesa_mode(800, 600);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CADBC
|
|
|
|
int _init_mode_1024_768()
|
|
|
|
{
|
|
|
|
return _init_vesa_mode(1024, 768);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CADD0
|
|
|
|
int _init_mode_1280_1024()
|
|
|
|
{
|
|
|
|
return _init_vesa_mode(1280, 1024);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CADF8
|
|
|
|
void _get_start_mode_()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CADFC
|
|
|
|
void _zero_vid_mem()
|
|
|
|
{
|
|
|
|
if (_zero_mem) {
|
|
|
|
_zero_mem();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAE1C
|
|
|
|
int _GNW95_init_mode_ex(int width, int height, int bpp)
|
|
|
|
{
|
2022-05-19 04:01:17 -07:00
|
|
|
bool fullscreen = true;
|
|
|
|
|
|
|
|
Config resolutionConfig;
|
|
|
|
if (configInit(&resolutionConfig)) {
|
|
|
|
if (configRead(&resolutionConfig, "f2_res.ini", false)) {
|
|
|
|
int screenWidth;
|
|
|
|
if (configGetInt(&resolutionConfig, "MAIN", "SCR_WIDTH", &screenWidth)) {
|
|
|
|
width = screenWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
int screenHeight;
|
|
|
|
if (configGetInt(&resolutionConfig, "MAIN", "SCR_HEIGHT", &screenHeight)) {
|
|
|
|
height = screenHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool windowed;
|
|
|
|
if (configGetBool(&resolutionConfig, "MAIN", "WINDOWED", &windowed)) {
|
|
|
|
fullscreen = !windowed;
|
|
|
|
}
|
2022-05-21 11:30:25 -07:00
|
|
|
|
|
|
|
configGetBool(&resolutionConfig, "IFACE", "IFACE_BAR_MODE", &gInterfaceBarMode);
|
2022-05-19 04:01:17 -07:00
|
|
|
}
|
|
|
|
configFree(&resolutionConfig);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_GNW95_init_window(width, height, fullscreen) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (directDrawInit(width, height, bpp) == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_scr_size.left = 0;
|
|
|
|
_scr_size.top = 0;
|
|
|
|
_scr_size.right = width - 1;
|
|
|
|
_scr_size.bottom = height - 1;
|
|
|
|
|
|
|
|
mmxSetEnabled(true);
|
|
|
|
|
|
|
|
if (bpp == 8) {
|
|
|
|
_mouse_blit_trans = NULL;
|
|
|
|
_scr_blit = _GNW95_ShowRect;
|
|
|
|
_zero_mem = _GNW95_zero_vid_mem;
|
|
|
|
_mouse_blit = _GNW95_ShowRect;
|
|
|
|
} else {
|
2022-07-29 06:04:05 -07:00
|
|
|
_zero_mem = NULL;
|
|
|
|
_mouse_blit = _GNW95_MouseShowRect16;
|
|
|
|
_mouse_blit_trans = _GNW95_MouseShowTransRect16;
|
|
|
|
_scr_blit = _GNW95_ShowRect16;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAECC
|
|
|
|
int _init_vesa_mode(int width, int height)
|
|
|
|
{
|
|
|
|
return _GNW95_init_mode_ex(width, height, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAEDC
|
2022-05-19 04:01:17 -07:00
|
|
|
int _GNW95_init_window(int width, int height, bool fullscreen)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
2022-05-23 01:44:49 -07:00
|
|
|
if (gSdlWindow == NULL) {
|
2022-07-12 00:10:23 -07:00
|
|
|
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
|
|
|
|
|
2022-05-19 04:01:17 -07:00
|
|
|
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-07-12 00:10:23 -07:00
|
|
|
Uint32 windowFlags = SDL_WINDOW_OPENGL;
|
|
|
|
|
|
|
|
if (fullscreen) {
|
|
|
|
windowFlags |= SDL_WINDOW_FULLSCREEN;
|
|
|
|
}
|
|
|
|
|
|
|
|
gSdlWindow = SDL_CreateWindow(gProgramWindowTitle, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, windowFlags);
|
2022-05-19 04:01:17 -07:00
|
|
|
if (gSdlWindow == NULL) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-10-04 03:15:54 -07:00
|
|
|
if (!createRenderer(width, height)) {
|
|
|
|
destroyRenderer();
|
2022-07-12 00:10:23 -07:00
|
|
|
|
2022-10-04 03:15:54 -07:00
|
|
|
SDL_DestroyWindow(gSdlWindow);
|
|
|
|
gSdlWindow = NULL;
|
2022-07-12 00:10:23 -07:00
|
|
|
|
2022-10-04 03:15:54 -07:00
|
|
|
return -1;
|
2022-05-19 04:01:17 -07:00
|
|
|
}
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// calculate shift for mask
|
|
|
|
// 0x4CAF50
|
|
|
|
int getShiftForBitMask(int mask)
|
|
|
|
{
|
|
|
|
int shift = 0;
|
|
|
|
|
|
|
|
if ((mask & 0xFFFF0000) != 0) {
|
|
|
|
shift |= 16;
|
|
|
|
mask &= 0xFFFF0000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mask & 0xFF00FF00) != 0) {
|
|
|
|
shift |= 8;
|
|
|
|
mask &= 0xFF00FF00;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mask & 0xF0F0F0F0) != 0) {
|
|
|
|
shift |= 4;
|
|
|
|
mask &= 0xF0F0F0F0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mask & 0xCCCCCCCC) != 0) {
|
|
|
|
shift |= 2;
|
|
|
|
mask &= 0xCCCCCCCC;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mask & 0xAAAAAAAA) != 0) {
|
|
|
|
shift |= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return shift;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAF9C
|
|
|
|
int directDrawInit(int width, int height, int bpp)
|
|
|
|
{
|
2022-05-19 04:01:17 -07:00
|
|
|
if (gSdlSurface != NULL) {
|
2022-05-19 01:51:26 -07:00
|
|
|
unsigned char* palette = directDrawGetPalette();
|
|
|
|
directDrawFree();
|
|
|
|
|
|
|
|
if (directDrawInit(width, height, bpp) == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
directDrawSetPalette(palette);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-05-19 04:01:17 -07:00
|
|
|
gSdlSurface = SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (bpp == 8) {
|
2022-05-19 04:01:17 -07:00
|
|
|
SDL_Color colors[256];
|
2022-05-19 01:51:26 -07:00
|
|
|
for (int index = 0; index < 256; index++) {
|
2022-05-19 04:01:17 -07:00
|
|
|
colors[index].r = index;
|
|
|
|
colors[index].g = index;
|
|
|
|
colors[index].b = index;
|
|
|
|
colors[index].a = 255;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-05-19 04:01:17 -07:00
|
|
|
SDL_SetPaletteColors(gSdlSurface->format->palette, colors, 0, 256);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2022-05-24 13:19:36 -07:00
|
|
|
gRedMask = gSdlSurface->format->Rmask;
|
|
|
|
gGreenMask = gSdlSurface->format->Gmask;
|
|
|
|
gBlueMask = gSdlSurface->format->Bmask;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-05-24 13:19:36 -07:00
|
|
|
gRedShift = gSdlSurface->format->Rshift;
|
|
|
|
gGreenShift = gSdlSurface->format->Gshift;
|
|
|
|
gBlueShift = gSdlSurface->format->Bshift;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
2022-05-24 13:19:36 -07:00
|
|
|
|
|
|
|
return 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CB1B0
|
|
|
|
void directDrawFree()
|
|
|
|
{
|
2022-05-19 04:01:17 -07:00
|
|
|
if (gSdlSurface != NULL) {
|
|
|
|
SDL_FreeSurface(gSdlSurface);
|
|
|
|
gSdlSurface = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CB310
|
|
|
|
void directDrawSetPaletteInRange(unsigned char* palette, int start, int count)
|
|
|
|
{
|
2022-05-19 04:01:17 -07:00
|
|
|
if (gSdlSurface != NULL && gSdlSurface->format->palette != NULL) {
|
|
|
|
SDL_Color colors[256];
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (count != 0) {
|
|
|
|
for (int index = 0; index < count; index++) {
|
2022-05-19 04:01:17 -07:00
|
|
|
colors[index].r = palette[index * 3] << 2;
|
|
|
|
colors[index].g = palette[index * 3 + 1] << 2;
|
|
|
|
colors[index].b = palette[index * 3 + 2] << 2;
|
|
|
|
colors[index].a = 255;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-19 04:01:17 -07:00
|
|
|
SDL_SetPaletteColors(gSdlSurface->format->palette, colors, start, count);
|
2022-07-12 00:10:23 -07:00
|
|
|
SDL_BlitSurface(gSdlSurface, NULL, gSdlTextureSurface, NULL);
|
|
|
|
SDL_UpdateTexture(gSdlTexture, NULL, gSdlTextureSurface->pixels, gSdlTextureSurface->pitch);
|
|
|
|
SDL_RenderClear(gSdlRenderer);
|
|
|
|
SDL_RenderCopy(gSdlRenderer, gSdlTexture, NULL, NULL);
|
|
|
|
SDL_RenderPresent(gSdlRenderer);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
|
|
|
for (int index = start; index < start + count; index++) {
|
|
|
|
unsigned short r = palette[0] << 2;
|
|
|
|
unsigned short g = palette[1] << 2;
|
|
|
|
unsigned short b = palette[2] << 2;
|
|
|
|
palette += 3;
|
|
|
|
|
|
|
|
r = gRedShift > 0 ? (r << gRedShift) : (r >> -gRedShift);
|
|
|
|
r &= gRedMask;
|
|
|
|
|
|
|
|
g = gGreenShift > 0 ? (g << gGreenShift) : (g >> -gGreenShift);
|
|
|
|
g &= gGreenMask;
|
|
|
|
|
|
|
|
b = gBlueShift > 0 ? (b << gBlueShift) : (b >> -gBlueShift);
|
|
|
|
b &= gBlueMask;
|
|
|
|
|
|
|
|
unsigned short rgb = r | g | b;
|
|
|
|
gSixteenBppPalette[index] = rgb;
|
|
|
|
}
|
|
|
|
|
|
|
|
windowRefreshAll(&_scr_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_update_palette_func != NULL) {
|
|
|
|
_update_palette_func();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CB568
|
|
|
|
void directDrawSetPalette(unsigned char* palette)
|
|
|
|
{
|
2022-05-19 04:01:17 -07:00
|
|
|
if (gSdlSurface != NULL && gSdlSurface->format->palette != NULL) {
|
2022-07-29 06:04:05 -07:00
|
|
|
SDL_Color colors[256];
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
for (int index = 0; index < 256; index++) {
|
2022-05-19 04:01:17 -07:00
|
|
|
colors[index].r = palette[index * 3] << 2;
|
|
|
|
colors[index].g = palette[index * 3 + 1] << 2;
|
|
|
|
colors[index].b = palette[index * 3 + 2] << 2;
|
|
|
|
colors[index].a = 255;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-05-19 04:01:17 -07:00
|
|
|
SDL_SetPaletteColors(gSdlSurface->format->palette, colors, 0, 256);
|
2022-07-12 00:10:23 -07:00
|
|
|
SDL_BlitSurface(gSdlSurface, NULL, gSdlTextureSurface, NULL);
|
|
|
|
SDL_UpdateTexture(gSdlTexture, NULL, gSdlTextureSurface->pixels, gSdlTextureSurface->pitch);
|
|
|
|
SDL_RenderClear(gSdlRenderer);
|
|
|
|
SDL_RenderCopy(gSdlRenderer, gSdlTexture, NULL, NULL);
|
|
|
|
SDL_RenderPresent(gSdlRenderer);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
|
|
|
for (int index = 0; index < 256; index++) {
|
|
|
|
unsigned short r = palette[index * 3] << 2;
|
|
|
|
unsigned short g = palette[index * 3 + 1] << 2;
|
|
|
|
unsigned short b = palette[index * 3 + 2] << 2;
|
|
|
|
|
|
|
|
r = gRedShift > 0 ? (r << gRedShift) : (r >> -gRedShift);
|
|
|
|
r &= gRedMask;
|
|
|
|
|
|
|
|
g = gGreenShift > 0 ? (g << gGreenShift) : (g >> -gGreenShift);
|
|
|
|
g &= gGreenMask;
|
|
|
|
|
|
|
|
b = gBlueShift > 0 ? (b << gBlueShift) : (b >> -gBlueShift);
|
|
|
|
b &= gBlueMask;
|
|
|
|
|
|
|
|
unsigned short rgb = r | g | b;
|
|
|
|
gSixteenBppPalette[index] = rgb;
|
|
|
|
}
|
|
|
|
|
|
|
|
windowRefreshAll(&_scr_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_update_palette_func != NULL) {
|
|
|
|
_update_palette_func();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CB68C
|
|
|
|
unsigned char* directDrawGetPalette()
|
|
|
|
{
|
2022-05-19 04:01:17 -07:00
|
|
|
if (gSdlSurface != NULL && gSdlSurface->format->palette != NULL) {
|
|
|
|
SDL_Color* colors = gSdlSurface->format->palette->colors;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
for (int index = 0; index < 256; index++) {
|
2022-05-19 04:01:17 -07:00
|
|
|
SDL_Color* color = &(colors[index]);
|
|
|
|
gLastVideoModePalette[index * 3] = color->r >> 2;
|
|
|
|
gLastVideoModePalette[index * 3 + 1] = color->g >> 2;
|
|
|
|
gLastVideoModePalette[index * 3 + 2] = color->b >> 2;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return gLastVideoModePalette;
|
|
|
|
}
|
|
|
|
|
|
|
|
int redShift = gRedShift + 2;
|
|
|
|
int greenShift = gGreenShift + 2;
|
|
|
|
int blueShift = gBlueShift + 2;
|
|
|
|
|
|
|
|
for (int index = 0; index < 256; index++) {
|
|
|
|
unsigned short rgb = gSixteenBppPalette[index];
|
|
|
|
|
|
|
|
unsigned short r = redShift > 0 ? ((rgb & gRedMask) >> redShift) : ((rgb & gRedMask) << -redShift);
|
|
|
|
unsigned short g = greenShift > 0 ? ((rgb & gGreenMask) >> greenShift) : ((rgb & gGreenMask) << -greenShift);
|
|
|
|
unsigned short b = blueShift > 0 ? ((rgb & gBlueMask) >> blueShift) : ((rgb & gBlueMask) << -blueShift);
|
|
|
|
|
|
|
|
gLastVideoModePalette[index * 3] = (r >> 2) & 0xFF;
|
|
|
|
gLastVideoModePalette[index * 3 + 1] = (g >> 2) & 0xFF;
|
|
|
|
gLastVideoModePalette[index * 3 + 2] = (b >> 2) & 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
return gLastVideoModePalette;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CB850
|
|
|
|
void _GNW95_ShowRect(unsigned char* src, int srcPitch, int a3, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY)
|
|
|
|
{
|
2022-05-19 04:01:17 -07:00
|
|
|
SDL_LockSurface(gSdlSurface);
|
|
|
|
blitBufferToBuffer(src + srcPitch * srcY + srcX, srcWidth, srcHeight, srcPitch, (unsigned char*)gSdlSurface->pixels + gSdlSurface->pitch * destY + destX, gSdlSurface->pitch);
|
|
|
|
SDL_UnlockSurface(gSdlSurface);
|
|
|
|
|
|
|
|
SDL_Rect srcRect;
|
|
|
|
srcRect.x = destX;
|
|
|
|
srcRect.y = destY;
|
|
|
|
srcRect.w = srcWidth;
|
|
|
|
srcRect.h = srcHeight;
|
|
|
|
|
|
|
|
SDL_Rect destRect;
|
|
|
|
destRect.x = destX;
|
|
|
|
destRect.y = destY;
|
2022-07-12 00:10:23 -07:00
|
|
|
SDL_BlitSurface(gSdlSurface, &srcRect, gSdlTextureSurface, &destRect);
|
|
|
|
SDL_UpdateTexture(gSdlTexture, NULL, gSdlTextureSurface->pixels, gSdlTextureSurface->pitch);
|
|
|
|
SDL_RenderClear(gSdlRenderer);
|
|
|
|
SDL_RenderCopy(gSdlRenderer, gSdlTexture, NULL, NULL);
|
|
|
|
SDL_RenderPresent(gSdlRenderer);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CB93C
|
|
|
|
void _GNW95_MouseShowRect16(unsigned char* src, int srcPitch, int a3, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY)
|
|
|
|
{
|
|
|
|
if (!gProgramIsActive) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-24 13:19:36 -07:00
|
|
|
SDL_LockSurface(gSdlSurface);
|
|
|
|
unsigned char* dest = (unsigned char*)gSdlSurface->pixels + gSdlSurface->pitch * destY + 2 * destX;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
src += srcPitch * srcY + srcX;
|
|
|
|
|
|
|
|
for (int y = 0; y < srcHeight; y++) {
|
|
|
|
unsigned short* destPtr = (unsigned short*)dest;
|
|
|
|
unsigned char* srcPtr = src;
|
|
|
|
for (int x = 0; x < srcWidth; x++) {
|
|
|
|
*destPtr = gSixteenBppPalette[*srcPtr];
|
|
|
|
destPtr++;
|
|
|
|
srcPtr++;
|
|
|
|
}
|
|
|
|
|
2022-05-24 13:19:36 -07:00
|
|
|
dest += gSdlSurface->pitch;
|
2022-05-19 01:51:26 -07:00
|
|
|
src += srcPitch;
|
|
|
|
}
|
|
|
|
|
2022-05-24 13:19:36 -07:00
|
|
|
SDL_UnlockSurface(gSdlSurface);
|
|
|
|
|
|
|
|
SDL_Rect srcRect;
|
|
|
|
srcRect.x = destX;
|
|
|
|
srcRect.y = destY;
|
|
|
|
srcRect.w = srcWidth;
|
|
|
|
srcRect.h = srcHeight;
|
|
|
|
|
|
|
|
SDL_Rect destRect;
|
|
|
|
destRect.x = destX;
|
|
|
|
destRect.y = destY;
|
2022-07-12 00:10:23 -07:00
|
|
|
SDL_BlitSurface(gSdlSurface, &srcRect, gSdlTextureSurface, &destRect);
|
|
|
|
SDL_UpdateTexture(gSdlTexture, NULL, gSdlTextureSurface->pixels, gSdlTextureSurface->pitch);
|
|
|
|
SDL_RenderClear(gSdlRenderer);
|
|
|
|
SDL_RenderCopy(gSdlRenderer, gSdlTexture, NULL, NULL);
|
|
|
|
SDL_RenderPresent(gSdlRenderer);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CBA44
|
|
|
|
void _GNW95_ShowRect16(unsigned char* src, int srcPitch, int a3, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY)
|
|
|
|
{
|
|
|
|
_GNW95_MouseShowRect16(src, srcPitch, a3, srcX, srcY, srcWidth, srcHeight, destX, destY);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CBAB0
|
|
|
|
void _GNW95_MouseShowTransRect16(unsigned char* src, int srcPitch, int a3, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, unsigned char keyColor)
|
|
|
|
{
|
|
|
|
if (!gProgramIsActive) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-24 13:19:36 -07:00
|
|
|
SDL_LockSurface(gSdlSurface);
|
|
|
|
unsigned char* dest = (unsigned char*)gSdlSurface->pixels + gSdlSurface->pitch * destY + 2 * destX;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
src += srcPitch * srcY + srcX;
|
|
|
|
|
|
|
|
for (int y = 0; y < srcHeight; y++) {
|
|
|
|
unsigned short* destPtr = (unsigned short*)dest;
|
|
|
|
unsigned char* srcPtr = src;
|
|
|
|
for (int x = 0; x < srcWidth; x++) {
|
|
|
|
if (*srcPtr != keyColor) {
|
|
|
|
*destPtr = gSixteenBppPalette[*srcPtr];
|
|
|
|
}
|
|
|
|
destPtr++;
|
|
|
|
srcPtr++;
|
|
|
|
}
|
|
|
|
|
2022-05-24 13:19:36 -07:00
|
|
|
dest += gSdlSurface->pitch;
|
2022-05-19 01:51:26 -07:00
|
|
|
src += srcPitch;
|
|
|
|
}
|
|
|
|
|
2022-05-24 13:19:36 -07:00
|
|
|
SDL_UnlockSurface(gSdlSurface);
|
|
|
|
|
|
|
|
SDL_Rect srcRect;
|
|
|
|
srcRect.x = destX;
|
|
|
|
srcRect.y = destY;
|
|
|
|
srcRect.w = srcWidth;
|
|
|
|
srcRect.h = srcHeight;
|
|
|
|
|
|
|
|
SDL_Rect destRect;
|
|
|
|
destRect.x = destX;
|
|
|
|
destRect.y = destY;
|
2022-07-12 00:10:23 -07:00
|
|
|
SDL_BlitSurface(gSdlSurface, &srcRect, gSdlTextureSurface, &destRect);
|
|
|
|
SDL_UpdateTexture(gSdlTexture, NULL, gSdlTextureSurface->pixels, gSdlTextureSurface->pitch);
|
|
|
|
SDL_RenderClear(gSdlRenderer);
|
|
|
|
SDL_RenderCopy(gSdlRenderer, gSdlTexture, NULL, NULL);
|
|
|
|
SDL_RenderPresent(gSdlRenderer);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Clears drawing surface.
|
|
|
|
//
|
|
|
|
// 0x4CBBC8
|
|
|
|
void _GNW95_zero_vid_mem()
|
|
|
|
{
|
|
|
|
if (!gProgramIsActive) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-24 13:19:36 -07:00
|
|
|
SDL_LockSurface(gSdlSurface);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-05-24 13:19:36 -07:00
|
|
|
unsigned char* surface = (unsigned char*)gSdlSurface->pixels;
|
2022-07-07 00:52:54 -07:00
|
|
|
for (int y = 0; y < gSdlSurface->h; y++) {
|
2022-05-24 13:19:36 -07:00
|
|
|
memset(surface, 0, gSdlSurface->w);
|
|
|
|
surface += gSdlSurface->pitch;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-05-24 13:19:36 -07:00
|
|
|
SDL_UnlockSurface(gSdlSurface);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-07-12 00:10:23 -07:00
|
|
|
SDL_BlitSurface(gSdlSurface, NULL, gSdlTextureSurface, NULL);
|
|
|
|
SDL_UpdateTexture(gSdlTexture, NULL, gSdlTextureSurface->pixels, gSdlTextureSurface->pitch);
|
|
|
|
SDL_RenderClear(gSdlRenderer);
|
|
|
|
SDL_RenderCopy(gSdlRenderer, gSdlTexture, NULL, NULL);
|
|
|
|
SDL_RenderPresent(gSdlRenderer);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-05-20 15:50:14 -07:00
|
|
|
int screenGetWidth()
|
|
|
|
{
|
|
|
|
// TODO: Make it on par with _xres;
|
2022-05-20 15:56:07 -07:00
|
|
|
return rectGetWidth(&_scr_size);
|
2022-05-20 15:50:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int screenGetHeight()
|
|
|
|
{
|
|
|
|
// TODO: Make it on par with _yres.
|
2022-05-20 15:56:07 -07:00
|
|
|
return rectGetHeight(&_scr_size);
|
2022-05-20 15:50:14 -07:00
|
|
|
}
|
2022-05-20 16:29:59 -07:00
|
|
|
|
2022-05-21 11:30:25 -07:00
|
|
|
int screenGetVisibleHeight()
|
|
|
|
{
|
|
|
|
int windowBottomMargin = 0;
|
|
|
|
|
|
|
|
if (!gInterfaceBarMode) {
|
|
|
|
windowBottomMargin = INTERFACE_BAR_HEIGHT;
|
|
|
|
}
|
|
|
|
return screenGetHeight() - windowBottomMargin;
|
|
|
|
}
|
|
|
|
|
2022-10-04 03:15:54 -07:00
|
|
|
static bool createRenderer(int width, int height)
|
|
|
|
{
|
|
|
|
gSdlRenderer = SDL_CreateRenderer(gSdlWindow, -1, 0);
|
|
|
|
if (gSdlRenderer == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SDL_RenderSetLogicalSize(gSdlRenderer, width, height) != 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
gSdlTexture = SDL_CreateTexture(gSdlRenderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
|
|
|
if (gSdlTexture == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint32 format;
|
|
|
|
if (SDL_QueryTexture(gSdlTexture, &format, NULL, NULL, NULL) != 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
gSdlTextureSurface = SDL_CreateRGBSurfaceWithFormat(0, width, height, SDL_BITSPERPIXEL(format), format);
|
|
|
|
if (gSdlTextureSurface == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void destroyRenderer()
|
|
|
|
{
|
|
|
|
if (gSdlTextureSurface != NULL) {
|
|
|
|
SDL_FreeSurface(gSdlTextureSurface);
|
|
|
|
gSdlTextureSurface = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gSdlTexture != NULL) {
|
|
|
|
SDL_DestroyTexture(gSdlTexture);
|
|
|
|
gSdlTexture = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gSdlRenderer != NULL) {
|
|
|
|
SDL_DestroyRenderer(gSdlRenderer);
|
|
|
|
gSdlRenderer = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-04 23:23:27 -07:00
|
|
|
void handleWindowSizeChanged()
|
|
|
|
{
|
|
|
|
destroyRenderer();
|
|
|
|
createRenderer(screenGetWidth(), screenGetHeight());
|
|
|
|
}
|
|
|
|
|
2022-09-23 05:43:44 -07:00
|
|
|
} // namespace fallout
|