Files
CnC_Remastered_Collection/code/redalert/winstub.cpp
T
2020-06-25 13:10:31 -07:00

1305 lines
41 KiB
C++

//
// Copyright 2020 Electronic Arts Inc.
//
// TiberianDawn.DLL and RedAlert.dll and corresponding source code 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 3 of the License, or (at your option) any later version.
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
// in the hope that it will be useful, but with permitted additional restrictions
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
// distributed with this program. You should have received a copy of the
// GNU General Public License along with permitted additional restrictions
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
/* $Header: /CounterStrike/WINSTUB.CPP 3 3/13/97 2:06p Steve_tall $ */
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* File Name : WINSTUB.CPP *
* *
* Programmer : Steve Tall *
* *
* Start Date : 10/04/95 *
* *
* Last Update : October 4th 1995 [ST] *
* *
*---------------------------------------------------------------------------------------------*
* Overview: *
* This file contains stubs for undefined externals when linked under Watcom for Win 95 *
* *
*---------------------------------------------------------------------------------------------*
* *
* Functions: *
* Assert_Failure -- display the line and source file where a failed assert occurred *
* Check_For_Focus_Loss -- check for the end of the focus loss *
* Create_Main_Window -- opens the MainWindow for C&C *
* Focus_Loss -- this function is called when a library function detects focus loss *
* Memory_Error_Handler -- Handle a possibly fatal failure to allocate memory *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "imgui.h"
#include "examples/imgui_impl_sdl.h"
#include "function.h"
#include "il/il.h"
#include "il/ilu.h"
#include "image.h"
#include "texcache.h"
#ifdef WINSOCK_IPX
#include "WSProto.h"
#else //WINSOCK_IPX
#include "tcpip.h"
#include "ipx95.h"
#endif //WINSOCK_IPX
#include <SDL.h>
#include <SDL_syswm.h>
#include <gl/glew.h>
#include <imgui.h>
#include <examples/imgui_impl_opengl3.h>
#include <string>
#include <algorithm>
#include <vector>
#include "HOUSECOLOR.H"
#include "IMGUTIL.H"
GLuint backbuffer_texture = -1;
//byte* backbuffer_data;
unsigned char* backbuffer_data_raw;
byte backbuffer_palette[768];
HWND MainWindow;
SurfaceMonitorClass AllSurfaces;
SDL_Window* game_window;
SDL_GLContext game_context;
int OverlappedVideoBlits = 0;
float animFrameNum = 0;
extern std::vector<const ObjectClass*> renderedFrameObjects;
bool renderConsole = false;
void (*Misc_Focus_Loss_Function)(void) = nullptr;
void (*Misc_Focus_Restore_Function)(void) = nullptr;
void (*Imgui_Dialog_Function)(void) = nullptr;
bool show_oldframebuffer = true;
void Show_OldFrameBuffer(bool show) {
show_oldframebuffer = show;
memset(backbuffer_data_raw, 0, ScreenWidth * ScreenHeight * 4);
}
Image_t* overlay_image = NULL;
void Sys_SetOverlayImage(Image_t* image) {
overlay_image = image;
}
std::vector<Image_t *> loaded_images;
unsigned char* Draw_Dropsample(const unsigned char* in, int inwidth, int inheight, int outwidth, int outheight);
static char* Image_GetGeneratedName(Image_t* image, const char* name, int houseid, int animid, int frameId, int64_t hash) {
static char generatedFileName[1024];
sprintf(generatedFileName, "%s.%d.%d.%d.%d.tga", name, frameId, houseid, animid, hash);
return &generatedFileName[0];
}
static bool Image_LoadFromCache(Image_t* image, const char* name, int houseid, int animid, int frameId, int64_t hash) {
static byte* Data = NULL;
if (Data == NULL) {
Data = new byte[8192 * 8192 * 4];
}
int Width, Height, Bpp;
if (!texCache.FindCachedImage(hash, Width, Height, Bpp, Data)) {
return false;
}
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
if (Bpp == 4) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, Data);
}
else if (Bpp == 3) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
}
else if (Bpp == 1) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_R, GL_UNSIGNED_BYTE, Data);
}
else {
assert(!"Unknown BPP in image!");
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
strcpy(image->name, name);
if (houseid == -1)
image->HouseImages[0].image[animid][frameId] = texture;
else
image->HouseImages[houseid].image[animid][frameId] = texture;
//image->namehash = hash;
image->renderwidth[animid] = image->width = Width;
image->renderheight[animid] = image->height = Height;
//image->buffer[houseid][animid] = new unsigned char[Width * Height * Bpp];
//memcpy(image->buffer[houseid][animid], Data, Width * Height * Bpp);
return true;
}
static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int animid, int frameId, int64_t hash) {
// Don't load the image if its already loaded.
if (houseid == -1) {
if (image->HouseImages[0].image[animid][frameId] != 0) {
return true;
}
}
else {
if (image->HouseImages[houseid].image[animid][frameId] != 0) {
return true;
}
}
const char* generatedName = Image_GetGeneratedName(image, name, houseid, animid, frameId, hash);
hash = generateHashValue(generatedName, strlen(generatedName));
// Check to see if we can load a generated image first.
// We only generate images that need a houseid
{
if (Image_LoadFromCache(image, generatedName, houseid, animid, frameId, hash)) {
return true;
}
}
ILuint ImageName;
ilGenImages(1, &ImageName);
ilBindImage(ImageName);
if (!ilLoadImage(name)) {
ilDeleteImages(1, &ImageName);
return false;
}
if (strstr(name, ".TGA") || strstr(name, ".tga")) {
iluFlipImage();
}
ILuint Width, Height, Bpp;
Width = ilGetInteger(IL_IMAGE_WIDTH);
Height = ilGetInteger(IL_IMAGE_HEIGHT);
Bpp = ilGetInteger(IL_IMAGE_BPP);
ILubyte* Data = ilGetData();
if (Bpp == 4 && houseid != -1) {
//Buffer_Enable_HD_Texture(true);
//Data = Draw_Dropsample(Data, Width, Height, Width / 2, Height / 2);
//Buffer_Enable_HD_Texture(false);
//Width = Width / 2;
//Height = Height / 2;
for (int i = 0; i < Width * Height; i++) {
RenderTeamPalette(&Data[i * 4], *houseColors[houseid]);
}
}
else if (Bpp == 4) {
for (int i = 0; i < Width * Height; i++) {
byte b = Data[(i * 4) + 2];
Data[(i * 4) + 2] = Data[(i * 4) + 0];
Data[(i * 4) + 0] = b;
}
}
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
if (Bpp == 4) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, Data);
}
else if (Bpp == 3) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
}
else if (Bpp == 1) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_R, GL_UNSIGNED_BYTE, Data);
}
else {
assert(!"Unknown BPP in image!");
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
strcpy(image->name, name);
if(houseid == -1)
image->HouseImages[0].image[animid][frameId] = texture;
else
image->HouseImages[houseid].image[animid][frameId] = texture;
//image->namehash = hash;
image->renderwidth[animid] = image->width = Width;
image->renderheight[animid] = image->height = Height;
//image->buffer[houseid][animid] = new unsigned char[Width * Height * Bpp];
//memcpy(image->buffer[houseid][animid], Data, Width * Height * Bpp);
if (Bpp == 4) {
texCache.AddImage(generatedName, Width, Height, Bpp, Data);
Console_Printf("Writing %s to cache %s\n", image->name, name);
Sleep(0);
}
ilDeleteImages(1, &ImageName);
return true;
}
Image_t* Image_CreateBlankImage(const char* name, int width, int height) {
int64_t hash = generateHashValue(name, strlen(name));
int image_table_size = loaded_images.size();
if (image_table_size > 0)
{
Image_t** image_table = &loaded_images[0];
// Check to see if the image is already loaded.
for (int i = 0; i < image_table_size; i++) {
if (image_table[i]->namehash == hash) {
return image_table[i];
}
}
}
Image_t* image = new Image_t();
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
strcpy(image->name, name);
image->HouseImages[0].image[0][0] = texture;
image->namehash = hash;
image->renderwidth[0] = image->width = width;
image->renderheight[0] = image->height = height;
loaded_images.push_back(image);
return image;
}
void Image_UploadRaw(Image_t* image, uint8_t* data, bool paletteRebuild, uint8_t* palette) {
if (image->ScratchBuffer == NULL && paletteRebuild) {
image->ScratchBuffer = new uint8_t[image->width * image->height * 4];
}
if (paletteRebuild) {
for (int i = 0; i < image->width * image->height; i++) {
unsigned char c = data[i];
unsigned char r = palette[(c * 3) + 0] << 2;
unsigned char g = palette[(c * 3) + 1] << 2;
unsigned char b = palette[(c * 3) + 2] << 2;
image->ScratchBuffer[(i * 4) + 0] = r;
image->ScratchBuffer[(i * 4) + 1] = g;
image->ScratchBuffer[(i * 4) + 2] = b;
image->ScratchBuffer[(i * 4) + 3] = 255;
}
}
glBindTexture(GL_TEXTURE_2D, image->HouseImages[0].image[0][0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image->width, image->height, GL_RGBA, GL_UNSIGNED_BYTE, image->ScratchBuffer);
}
Image_t* Image_LoadImage(const char* name, bool loadAnims, bool loadHouseColor) {
int64_t hash = generateHashValue(name, strlen(name));
int image_table_size = loaded_images.size();
if (image_table_size > 0)
{
Image_t** image_table = &loaded_images[0];
// Check to see if the image is already loaded.
for (int i = 0; i < image_table_size; i++) {
if (image_table[i]->namehash == hash) {
return image_table[i];
}
}
}
Image_t* image = new Image_t();
if (!loadAnims) {
unsigned char remap[3] = { 0, 0, 0 };
if (!Image_loadHDImage(image, name, -1, 0, 0, hash)) {
delete image;
return NULL;
}
}
else {
byte* palette = (byte *)CCPalette.Get_Data();
for (int i = 0; i < MAX_MPLAYER_COLORS; i++) {
if (!Image_loadHDImage(image, name, i, 0, 0, hash)) {
delete image;
return NULL;
}
}
}
image->namehash = hash;
loaded_images.push_back(image);
return image;
}
Image_t *Find_Image(const char* name) {
int64_t hash = generateHashValue(name, strlen(name));
int image_table_size = loaded_images.size();
if (image_table_size > 0)
{
Image_t** image_table = &loaded_images[0];
// Check to see if the image is already loaded.
for (int i = 0; i < image_table_size; i++) {
if (image_table[i]->namehash == hash) {
return image_table[i];
}
}
}
return NULL;
}
Image_t* Image_CreateImageFrom8Bit(const char* name, int Width, int Height, unsigned char *data, unsigned char* remap) {
int64_t hash = generateHashValue(name, strlen(name));
int image_table_size = loaded_images.size();
if (image_table_size > 0)
{
Image_t** image_table = &loaded_images[0];
// Check to see if the image is already loaded.
for (int i = 0; i < image_table_size; i++) {
if (image_table[i]->namehash == hash) {
return image_table[i];
}
}
}
unsigned char* ccpalete = (unsigned char*)CCPalette.Get_Data();
Image_t* image = new Image_t();
unsigned char *buffer = new unsigned char[Width * Height * 4];
for (int i = 0; i < Width * Height; i++) {
unsigned char c = data[i];
if (remap) {
c = remap[c];
}
unsigned char r = ccpalete[(c * 3) + 0] << 2;
unsigned char g = ccpalete[(c * 3) + 1] << 2;
unsigned char b = ccpalete[(c * 3) + 2] << 2;
unsigned char a = 0;
if ((r == 84 && g == 252 && b == 84) || (r == 0 && g == 168 && b == 0)) {
r = 0;
g = 0;
b = 0;
a = 128;
}
else if (c != 0) {
a = 255;
}
buffer[(i * 4) + 0] = r;
buffer[(i * 4) + 1] = g;
buffer[(i * 4) + 2] = b;
buffer[(i * 4) + 3] = a;
}
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
strcpy(image->name, name);
image->HouseImages[0].image[0][0] = texture;
image->numAnimFrames = -1;
image->namehash = hash;
image->renderwidth[0] = image->width = Width;
image->renderheight[0] = image->height = Height;
loaded_images.push_back(image);
delete buffer;
return image;
}
void Image_Add8BitImage(Image_t *image, int HouseId, int ShapeID, int Width, int Height, unsigned char* data, unsigned char* remap) {
unsigned char* buffer = new unsigned char[Width * Height * 4];
unsigned char* ccpalete = (unsigned char*)CCPalette.Get_Data();
if (image->width != Width || image->height != Height) {
assert(!"Image_Add8BitImage: Invalid new dimensions!");
}
for (int i = 0; i < Width * Height; i++) {
unsigned char c = data[i];
if (remap) {
c = remap[c];
}
unsigned char r = ccpalete[(c * 3) + 0] << 2;
unsigned char g = ccpalete[(c * 3) + 1] << 2;
unsigned char b = ccpalete[(c * 3) + 2] << 2;
unsigned char a = 0;
if ((r == 84 && g == 252 && b == 84) || (r == 0 && g == 168 && b == 0)) {
r = 0;
g = 0;
b = 0;
a = 128;
}
else if (c != 0) {
a = 255;
}
buffer[(i * 4) + 0] = r;
buffer[(i * 4) + 1] = g;
buffer[(i * 4) + 2] = b;
buffer[(i * 4) + 3] = a;
}
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
image->HouseImages[HouseId].image[ShapeID][0] = texture;
image->numAnimFrames = -1;
image->renderwidth[ShapeID] = image->width = Width;
image->renderheight[ShapeID] = image->height = Height;
delete buffer;
}
bool Image_Add32BitImage(const char *name, Image_t* image, int HouseId, int ShapeID, int frameId) {
return Image_loadHDImage(image, name, HouseId, ShapeID, frameId, image->namehash);
}
BOOL Set_Video_Mode(HWND hwnd, int w, int h, int bits_per_pixel) {
// Todo implement resoluton scaling.
return true; // Always return true;
}
unsigned int Get_Free_Video_Memory(void) {
return 64 * 1024 * 1024;
}
unsigned int Get_Video_Hardware_Capabilities() {
return 0;
}
void Reset_Video_Mode(void) {
}
void Set_DD_Palette(void* palette, bool raShift)
{
char* palette_get = (char*)palette; //CCPalette.Get_Data();
for (int j = 0; j < 768; j++) {
if (raShift) {
backbuffer_palette[j] = palette_get[j] << 2;
}
else {
backbuffer_palette[j] = palette_get[j];
}
}
}
void ImGui_NewFrame(void) {
ImGuiIO& io = ImGui::GetIO();
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
io.DisplaySize = ImVec2(ScreenWidth, ScreenHeight);
ImGui_ImplOpenGL3_NewFrame();
ImGui::NewFrame(show_oldframebuffer);
ImGui_ImplSDL2_NewFrame(game_window);
renderedFrameObjects.clear();
}
void Device_Present(void) {
if (overlay_image) {
GL_RenderImage(overlay_image, 0, 0, ScreenWidth, ScreenHeight);
}
// Rasterize the palette.
//for (int i = 0; i < ScreenWidth * ScreenHeight; i++) {
// backbuffer_data[(i * 4) + 0] = backbuffer_palette[(backbuffer_data_raw[i] * 3) + 0];
// backbuffer_data[(i * 4) + 1] = backbuffer_palette[(backbuffer_data_raw[i] * 3) + 1];
// backbuffer_data[(i * 4) + 2] = backbuffer_palette[(backbuffer_data_raw[i] * 3) + 2];
// backbuffer_data[(i * 4) + 3] = 255;
//}
//glBindTexture(GL_TEXTURE_2D, backbuffer_texture);
//glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ScreenWidth, ScreenHeight, GL_RGBA, GL_UNSIGNED_BYTE, backbuffer_data_raw);
bool ScreenActive;
ImGuiStyle& style = ImGui::GetStyle();
style.FramePadding = ImVec2(0, 0);
ImGui::SetNextWindowSize(ImVec2(ScreenWidth, ScreenHeight));
ImGui::SetNextWindowPos(ImVec2(0, 0));
// jmarshall - I'm removing this because we don't render the legacy buffer anymore.
//ImGui::Begin("RenderWindow", &ScreenActive, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMouseInputs);
// if (show_oldframebuffer)
// {
// ImVec2 desktopSize(ScreenWidth, ScreenHeight);
// ImGui::Image((ImTextureID)backbuffer_texture, desktopSize);
// }
//
//ImGui::End();
// jmarshall end
if (Imgui_Dialog_Function) {
Map.Render();
Imgui_Dialog_Function();
}
if (renderConsole) {
Console_Render();
}
WWMouse->RenderMouse();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(game_window);
// Last thing we do is execute any console commands
Console_Tick();
ImGui_NewFrame();
}
void output(short,short)
{}
unsigned long CCFocusMessage = WM_USER+50; //Private message for receiving application focus
extern void VQA_PauseAudio(void);
extern void VQA_ResumeAudio(void);
//#include "WolDebug.h"
/***********************************************************************************************
* Focus_Loss -- this function is called when a library function detects focus loss *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 2/1/96 2:10PM ST : Created *
*=============================================================================================*/
void Focus_Loss(void)
{
Theme.Suspend();
Stop_Primary_Sound_Buffer();
if (WWMouse) WWMouse->Clear_Cursor_Clip();
}
void Focus_Restore(void)
{
Restore_Cached_Icons();
Map.Flag_To_Redraw(true);
Start_Primary_Sound_Buffer(TRUE);
if (WWMouse) WWMouse->Set_Cursor_Clip();
VisiblePage.Clear();
HiddenPage.Clear();
}
/***********************************************************************************************
* Check_For_Focus_Loss -- check for the end of the focus loss *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 2/2/96 10:49AM ST : Created *
*=============================================================================================*/
void Check_For_Focus_Loss(void)
{
#if (0)//PG
static BOOL focus_last_time = 1;
MSG msg;
if ( !GameInFocus ) {
Focus_Loss();
while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE | PM_NOYIELD ) ) {
if (!GetMessage( &msg, NULL, 0, 0 ) ) {
return;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if (!focus_last_time && GameInFocus) {
VQA_PauseAudio();
CountDownTimerClass cd;
cd.Set(60*1);
do {
while (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {
if (!GetMessage( &msg, NULL, 0, 0 ) ) {
return;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} while (cd.Time());
VQA_ResumeAudio();
PostMessage (MainWindow, CCFocusMessage, 0, 0);
// AllSurfaces.Restore_Surfaces();
// VisiblePage.Clear();
// HiddenPage.Clear();
// Map.Flag_To_Redraw(true);
}
focus_last_time = GameInFocus;
#endif
}
extern bool InMovie;
HANDLE DebugFile = INVALID_HANDLE_VALUE;
/***********************************************************************************************
* WWDebugString -- sends a string to the debugger and echos it to disk *
* *
* *
* *
* INPUT: string *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/28/96 12:48PM ST : Created *
*=============================================================================================*/
void WWDebugString (char *string)
{
Console_Printf(string);
}
/***********************************************************************************************
* Create_Main_Window -- opens the MainWindow for C&C *
* *
* *
* *
* INPUT: instance -- handle to program instance *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/10/95 4:08PM ST : Created *
*=============================================================================================*/
#define CC_ICON 1
#define WINDOW_NAME "Red Alert"
void Create_Main_Window ( HANDLE instance , int command_show , int width , int height )
{
HWND hwnd ;
ilInit();
texCache.Init();
SDL_Init(SDL_INIT_VIDEO);
game_window = SDL_CreateWindow(WINDOW_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
game_context = SDL_GL_CreateContext(game_window);
SDL_GL_SetSwapInterval(0);
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(game_window, &wmInfo);
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
hwnd = wmInfo.info.win.window;
GameInFocus = TRUE;
ShowWindow(hwnd, command_show );
ShowCommand = command_show;
UpdateWindow(hwnd);
SetFocus(hwnd);
MainWindow = hwnd;
hInstance = instance;
CCFocusMessage = RegisterWindowMessage("CC_GOT_FOCUS");
//Audio_Focus_Loss_Function = &Focus_Loss;
Misc_Focus_Loss_Function = &Focus_Loss;
Misc_Focus_Restore_Function = &Focus_Restore;
Gbuffer_Focus_Loss_Function = &Focus_Loss;
glGenTextures(1, &backbuffer_texture);
glBindTexture(GL_TEXTURE_2D, backbuffer_texture);
// Give the image to OpenGL
backbuffer_data_raw = new byte[width * height * 4];
memset(backbuffer_data_raw, 0, width * height * 4);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, backbuffer_data_raw);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glewInit();
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer bindings
ImGui_ImplSDL2_InitForD3D(game_window);
ImGui_ImplOpenGL3_Init();
io.Fonts->AddFontFromFileTTF("fonts/Arial.ttf", 16.0f);
ImGui_NewFrame();
}
void Window_Dialog_Box(HANDLE hinst, LPCTSTR lpszTemplate, HWND hwndOwner, DLGPROC dlgprc)
{
#if (0)//PG
MSG msg;
/*
** Get rid of the Westwood mouse cursor because we are showing a
** dialog box and we want to have the right windows cursor showing
** for it.
*/
Hide_Mouse();
ShowCursor(TRUE);
/*
** Pop up the dialog box and then run a standard message handler
** until the dialog box is closed.
*/
DialogBox(hinst, lpszTemplate, hwndOwner, dlgprc);
while (GetMessage(&msg, NULL, 0, 0) && !AllDone) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/*
** Restore the westwood mouse cursor and get rid of the windows one
** because it is now time to restore back to the westwood way of
** doing things.
*/
ShowCursor(FALSE);
Show_Mouse();
#endif
}
typedef struct tColourList {
char Red;
char Green;
char Blue;
} ColourList;
ColourList ColourLookup[9]={
0,0,0,
63,0,0,
0,63,0,
0,0,63,
63,0,63,
63,63,0,
0,63,63,
32,32,32,
63,63,63
};
int DebugColour=1;
extern "C" void Set_Palette_Register(int number, int red, int green, int blue);
//#pragma off (unreferenced)
void Colour_Debug (int call_number)
{
#if (0)//PG
//#if 0
//if (DebugColour==call_number || !call_number) {
//if (call_number) {
// Wait_Vert_Blank();
//}
Set_Palette_Register (0,ColourLookup[call_number].Red ,
ColourLookup[call_number].Green,
ColourLookup[call_number].Blue);
//}
//#endif
#endif
}
//#pragma on (unreferenced)
BOOL Any_Locked (void)
{
if (SeenBuff.Get_LockCount() ||
HidPage.Get_LockCount()) {
return (TRUE);
} else {
return(FALSE);
}
}
//
// Miscellaneous stubs. Mainly for multi player stuff
//
//
//
//IPXAddressClass::IPXAddressClass(void) {
// int i;
// i++;
//}
//int IPXManagerClass::Num_Connections(void) { return (0); }
//int IPXManagerClass::Connection_ID( int ) { return (0); }
//IPXAddressClass * IPXManagerClass::Connection_Address( int ) { return ((IPXAddressClass*)0); }
//char * IPXManagerClass::Connection_Name( int ) { return ((char*)0); }
//int IPXAddressClass::Is_Broadcast() { return (0); }
//int IPXManagerClass::Send_Global_Message( void *, int, int, IPXAddressClass * ) { return (0); }
//int IPXManagerClass::Service() { return (0); }
//int IPXManagerClass::Get_Global_Message( void *, int *, IPXAddressClass *, short unsigned * ) { return (0); }
//int IPXAddressClass::operator ==( IPXAddressClass & ) { return (0); }
//IPXManagerClass::IPXManagerClass( int, int, int, int, short unsigned, short unsigned ) {}
//IPXManagerClass::~IPXManagerClass() {
// int i;
// i++;
// }
//int IPXManagerClass::Delete_Connection( int ) { return (0); }
//IPXAddressClass::IPXAddressClass( char unsigned *, char unsigned * ) {}
//void IPXManagerClass::Set_Socket( short unsigned ) {}
//int IPXManagerClass::Is_IPX() { return (0); }
//int IPXManagerClass::Init() { return (0); }
//void IPXAddressClass::Get_Address( char unsigned *, char unsigned * ) {}
//void IPXManagerClass::Set_Bridge( char unsigned * ) {}
//int IPXManagerClass::Global_Num_Send() { return (0); }
//void IPXManagerClass::Set_Timing( long unsigned, long unsigned, long unsigned ) {}
//unsigned long IPXManagerClass::Global_Response_Time() { return (0); }
//int IPXManagerClass::Create_Connection( int, char *, IPXAddressClass * ) { return (0); }
//int IPXAddressClass::operator !=( IPXAddressClass & ) { return (0); }
//int IPXManagerClass::Send_Private_Message( void *, int, int, int ) { return (0); }
//int IPXManagerClass::Get_Private_Message( void *, int *, int * ) { return (0); }
//int IPXManagerClass::Connection_Index( int ) { return (0); }
//void IPXManagerClass::Reset_Response_Time() {}
//long unsigned IPXManagerClass::Response_Time() { return (0); }
//int IPXManagerClass::Private_Num_Send( int ) { return (0); }
//void VQA_Init(VQAHandle *, long(*)(VQAHandle *vqa, long action, void *buffer, long nbytes)) {}
//long VQA_Open(VQAHandle *, char const *, VQAConfig *)
//{
// return (0);
//}
//void VQA_Close(VQAHandle *) {}
//long VQA_Play(VQAHandle *, long)
//{
// return (0);
//}
unsigned char *VQPalette;
long VQNumBytes;
unsigned long VQSlowpal;
bool VQPaletteChange = false;
extern "C"{
void __cdecl SetPalette(unsigned char *palette, long numbytes, unsigned long slowpal);
}
void Flag_To_Set_Palette(unsigned char *palette, long numbytes, unsigned long slowpal)
{
VQPalette = palette;
VQNumBytes = numbytes;
VQSlowpal = slowpal;
VQPaletteChange = true;
}
void Check_VQ_Palette_Set(void)
{
if (VQPaletteChange) {
SetPalette(VQPalette, VQNumBytes, VQSlowpal);
VQPaletteChange = false;
}
}
void __cdecl SetPalette(unsigned char *palette, long, unsigned long)
{
for (int i=0 ; i<256*3 ; i++) {
*(palette+i)&=63;
}
Increase_Palette_Luminance(palette , 15 , 15 , 15 ,63);
if (PalettesRead) {
memcpy (&PaletteInterpolationTable[0][0] , InterpolatedPalettes[PaletteCounter++] , 65536);
}
Set_Palette(palette);
}
void WWSDL_ProcessEvents(KeyNumType& key, int& flags, bool presentBuffer) {
//UserInput.Process_Input(key, flags);
}
#ifndef NDEBUG
/***********************************************************************************************
* Assert_Failure -- display the line and source file where a failed assert occurred *
* *
* *
* INPUT: line number in source file *
* name of source file *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 4/17/96 9:58AM ST : Created *
*=============================================================================================*/
void Assert_Failure (char *expression, int line, char *file)
{
char assertbuf[256];
char timebuff[512];
SYSTEMTIME time;
sprintf (assertbuf, "assert '%s' failed at line %d in module %s.\n", expression, line, file);
if (!MonoClass::Is_Enabled()) MonoClass::Enable();
Mono_Clear_Screen();
Mono_Printf("%s", assertbuf);
WWDebugString(assertbuf);
GetLocalTime(&time);
sprintf (timebuff, "%02d/%02d/%04d %02d:%02d:%02d - %s", time.wMonth, time.wDay, time.wYear,
time.wHour, time.wMinute, time.wSecond,
assertbuf);
HMMIO handle = mmioOpen("ASSERT.TXT", NULL, MMIO_WRITE);
if (!handle) {
handle = mmioOpen("ASSERT.TXT", NULL, MMIO_CREATE | MMIO_WRITE);
//mmioClose(handle, 0);
//handle = mmioOpen("ASSERT.TXT", NULL, MMIO_WRITE);
}
if (handle) {
mmioWrite(handle, timebuff, strlen(timebuff));
mmioClose(handle, 0);
}
WWMessageBox().Process(assertbuf);
Prog_End(assertbuf, false);
Invalidate_Cached_Icons();
}
#endif
/***********************************************************************************************
* Memory_Error_Handler -- Handle a possibly fatal failure to allocate memory *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 5/22/96 3:57PM ST : Created *
*=============================================================================================*/
void Memory_Error_Handler(void)
{
VisiblePage.Clear();
CCPalette.Set();
while (Get_Mouse_State()) {Show_Mouse();};
WWMessageBox().Process(TEXT_MEMORY_ERROR, TEXT_ABORT, false);
ReadyToQuit = 1;
PostMessage(MainWindow, WM_DESTROY, 0, 0);
do
{
Keyboard->Check();
}while (ReadyToQuit == 1);
ExitProcess(0);
}
GraphicBufferClass* Read_PCX_File(char* name, char* Palette, void *Buff, long Size);
void Load_Title_Screen(char *name, GraphicViewPortClass *video_page, unsigned char *palette) {
char filename[512];
sprintf(filename, "ui/%s", name);
COM_SetExtension(filename, sizeof(filename), ".png");
Image_t* image = Image_LoadImage(filename);
GL_RenderImage(image, 0, 0, ScreenWidth, ScreenHeight);
// We still have to do this for palette reasons.
{
GraphicBufferClass* load_buffer;
load_buffer = Read_PCX_File(name, (char*)palette, NULL, 0);
delete load_buffer;
//if (load_buffer) {
// load_buffer->Scale(*video_page, 0, 0, 0, 0, load_buffer->Get_Width(), load_buffer->Get_Height(), ScreenWidth, ScreenHeight, NULL);
// delete load_buffer;
//}
}
}
#include "filepcx.h"
/***************************************************************************
* READ_PCX_FILE -- read a pcx file into a Graphic Buffer *
* *
* GraphicBufferClass* Read_PCX_File (char* name, char* palette ,void *Buff, long size ); *
* *
* *
* INPUT: name is a NULL terminated string of the format [xxxx.pcx] *
* palette is optional, if palette != NULL the the color palette of *
* the pcx file will be place in the memory block pointed *
* by palette. *
* Buff is optional, if Buff == NULL a new memory Buffer *
* will be allocated, otherwise the file will be placed *
* at location pointed by Buffer; *
* Size is the size in bytes of the memory block pointed by Buff *
* is also optional; * *
* OUTPUT: on success a pointer to a GraphicBufferClass containing the *
* pcx file, NULL otherwise. *
* *
* WARNINGS: *
* Appears to be a comment-free zone *
* *
* HISTORY: *
* 05/03/1995 JRJ : Created. *
* 04/30/1996 ST : Tidied up and modified to use CCFileClass *
*=========================================================================*/
#define POOL_SIZE 2048
#define READ_CHAR() *file_ptr++ ; \
if ( file_ptr >= & pool [ POOL_SIZE ] ) { \
file_handle.Read (pool , POOL_SIZE ); \
file_ptr = pool ; \
}
GraphicBufferClass* Read_PCX_File(char* name, char* palette, void *Buff, long Size)
{
unsigned i, j;
unsigned rle;
unsigned color;
unsigned scan_pos;
char *file_ptr;
int width;
int height;
char *buffer;
PCX_HEADER header;
RGB *pal;
char pool [POOL_SIZE];
GraphicBufferClass *pic;
CCFileClass file_handle(name);
if (!file_handle.Is_Available()) return (NULL);
file_handle.Open(READ);
file_handle.Read (&header, sizeof (PCX_HEADER));
if (header.id != 10 && header.version != 5 && header.pixelsize != 8 ) return NULL ;
width = header.width - header.x + 1;
height = header.height - header.y + 1;
if (Buff) {
buffer = (char *)Buff;
i = Size / width;
height = MIN ((int)i - 1, height);
pic = new GraphicBufferClass(width, height, buffer, Size);
if ( !(pic && pic->Get_Buffer()) ) return NULL ;
} else {
pic = new GraphicBufferClass(width, height, NULL, width*(height+4));
if ( !(pic && pic->Get_Buffer()) ) return NULL ;
}
buffer = (char *) pic->Get_Buffer();
file_ptr = pool ;
file_handle.Read (pool , POOL_SIZE);
if ( header.byte_per_line != width ) {
for ( scan_pos = j = 0 ; j < (unsigned) height ; j ++, scan_pos += width ) {
for ( i = 0 ; i < (unsigned)width ; ) {
rle = READ_CHAR ();
if ( rle > 192 ) {
rle -= 192 ;
color = READ_CHAR (); ;
memset ( buffer + scan_pos + i , color , rle );
i += rle;
} else {
*(buffer+scan_pos + i++ ) = (char)rle;
}
}
}
if ( i == width ) rle = READ_CHAR ();
if ( rle > 192 ) rle = READ_CHAR ();
} else {
for ( i = 0 ; i < (unsigned)width * height ; ) {
rle = READ_CHAR ();
rle &= 0xff;
if ( rle > 192 ) {
rle -= 192 ;
color = READ_CHAR ();
memset ( buffer + i , color , rle );
i += rle ;
} else {
*(buffer + i++) = (char)rle;
}
}
}
if ( palette ) {
file_handle.Seek (- (256 * (int)sizeof ( RGB )) , SEEK_END );
file_handle.Read (palette , 256L * sizeof ( RGB ));
pal = ( RGB * ) palette;
for (i = 0 ; i < 256 ; i ++) {
pal ->red >>= 2;
pal ->green >>= 2;
pal ->blue >>= 2;
pal ++ ;
}
}
file_handle.Close();
return pic;
}