hostile-takeover/game/sdl/display.cpp
2016-08-31 23:55:30 -04:00

349 lines
7.6 KiB
C++

#include "../ht.h"
#include "game/sdl/sdlspritemgr.h"
#include "game/sdl/hosthelpers.h"
#include "game/sdl/sdlspritemgr.h"
namespace wi {
static SdlSpriteManager *s_psprm;
static Size s_siz;
Display *HostCreateDisplay() {
// Create a display
Display *pdisp = new Display();
if (pdisp == NULL)
return NULL;
if (!pdisp->Init()) {
delete pdisp;
return NULL;
}
return pdisp;
}
Display::Display()
{
m_cx = 0;
m_cy = 0;
memset(m_amodeInfo, 0, sizeof(m_amodeInfo));
m_imode = -1;
m_cmodes = 0;
m_pbmBack = NULL;
m_pbmFront = NULL;
m_pbmClip = NULL;
m_window = NULL;
m_renderer = NULL;
m_texture = NULL;
m_gamePixels = NULL;
m_gamePixels32 = NULL;
memset(m_palette, 0, sizeof(m_palette));
m_pitch32 = 0;
m_pixelCount = 0;
m_density = 0;
m_fShouldRender = false;
}
Display::~Display()
{
delete m_pbmBack;
m_pbmBack = NULL;
delete m_pbmFront;
m_pbmFront = NULL;
delete m_pbmClip;
m_pbmClip = NULL;
SDL_DestroyWindow(m_window);
m_window = NULL;
SDL_DestroyRenderer(m_renderer);
m_renderer = NULL;
SDL_DestroyTexture(m_texture);
m_texture = NULL;
free(m_gamePixels);
m_gamePixels = NULL;
free(m_gamePixels32);
m_gamePixels32 = NULL;
}
bool Display::Init()
{
dword videoflags;
/* Initialize SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
LOG() << "Couldn't initialize SDL: " << SDL_GetError();
return false;
}
// Absolutely do not mess with SDL_FULLSCREEN if there is any chance the app
// will crash or stop at a breakpoint. If it does you will be lost in full
// screen mode! (ssh from another machine and kill the Xcode process)
videoflags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_SHOWN;
#if defined(__IPHONEOS__) || defined(__ANDROID__)
videoflags = videoflags | SDL_WINDOW_BORDERLESS;
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeRight LandscapeLeft");
#endif
// Android wants to process mouse and touch events separately
#if defined(__ANDROID__)
SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1");
#endif
// Get surface properties
SurfaceProperties props;
HostHelpers::GetSurfaceProperties(&props);
m_cx = props.cxWidth;
m_cy = props.cyHeight;
m_density = props.density;
// Create window
if ((m_window = SDL_CreateWindow("Hostile Takeover", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_cx, m_cy, videoflags)) == NULL) {
LOG() << "Couldn't create window: " << m_cx << "x" << m_cy << " \nError: " << SDL_GetError();
return false;
}
// Create renderer
m_renderer = SDL_CreateRenderer(m_window, 0, SDL_RENDERER_TARGETTEXTURE);
this->SetShouldRender(true);
// Keep the screen size around
s_siz.cx = m_cx;
s_siz.cy = m_cy;
// Create texture
m_texture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, m_cx, m_cy);
// Set pixel info
m_pixelCount = m_cx * m_cy;
m_gamePixels = (byte *)malloc(m_pixelCount);
m_gamePixels32 = (dword *)malloc(m_pixelCount * 4);
m_pitch32 = m_cx * sizeof(dword);
// Keep the screen size around
s_siz.cx = m_cx;
s_siz.cy = m_cy;
ModeInfo *pmode = m_amodeInfo;
#if 1
pmode->nDepth = 8;
pmode->cx = props.cxWidth;
pmode->cy = props.cyHeight;
pmode->cyGraffiti = 0;
pmode->fNative = true;
pmode->nDegreeOrientation = 0;
pmode++;
#endif
#if 0
pmode->nDepth = 8;
pmode->cx = props.cyHeight;
pmode->cy = props.cxWidth;
pmode->cyGraffiti = 0;
pmode->fNative = true;
pmode->nDegreeOrientation = 90; // leftie controls
pmode++;
#endif
#if 0
pmode->nDepth = 8;
pmode->cx = props.cxWidth;
pmode->cy = props.cyHeight;
pmode->cyGraffiti = 0;
pmode->fNative = true;
pmode->nDegreeOrientation = 180; // bizzaro controls
pmode++;
#endif
#if 0
pmode->nDepth = 8;
pmode->cx = props.cyHeight;
pmode->cy = props.cxWidth;
pmode->cyGraffiti = 0;
pmode->fNative = true;
pmode->nDegreeOrientation = 270; // rightie controls
pmode++;
#endif
m_cmodes = pmode - m_amodeInfo;
HostOutputDebugString("Display::Init %d", pmode - m_amodeInfo);
HostOutputDebugString("Display::Init %d modes", m_cmodes);
#if defined(__IPHONEOS__)
HostHelpers::DisplayInitComplete();
#endif
return true;
}
void Display::SetPalette(Palette *ppal)
{
SDL_Color aclr[256];
int cEntries = BigWord(ppal->cEntries);
byte *pb = (byte *)ppal->argb;
SDL_Color *pclr = aclr;
for (int i = 0; i < cEntries; i++) {
pclr->r = *pb++;
pclr->g = *pb++;
pclr->b = *pb++;
pclr++;
}
for (int i = 0; i < cEntries; i++) {
m_palette[i] = ((Uint8)aclr[i].r << 16) | ((Uint8)aclr[i].g << 8) | ((Uint8)aclr[i].b << 0);
}
}
int Display::GetModeCount()
{
return m_cmodes;
}
void Display::GetModeInfo(int imode, ModeInfo *pmode)
{
memset(pmode, 0, sizeof(*pmode));
if (imode >= 0 && imode < m_cmodes)
*pmode = m_amodeInfo[imode];
}
int Display::GetMode(ModeInfo *pmode)
{
if (pmode != NULL) {
if (m_imode == -1) {
memset(pmode, 0, sizeof(*pmode));
} else {
*pmode = m_amodeInfo[m_imode];
}
}
return m_imode;
}
bool Display::SetMode(int imode)
{
// Allocate dib
ModeInfo *pmode = &m_amodeInfo[imode];
DibBitmap *pbmBack = CreateDibBitmap(NULL, pmode->cx, pmode->cy);
if (pbmBack == NULL)
return false;
DibBitmap *pbmFront = CreateDibBitmap(m_gamePixels, pmode->cx, pmode->cy);
if (pbmFront == NULL) {
delete pbmBack;
return NULL;
}
delete m_pbmBack;
delete m_pbmFront;
m_pbmBack = pbmBack;
m_pbmFront = pbmFront;
m_imode = imode;
return true;
}
void Display::DrawText(const char *psz, int x, int y, word wf)
{
}
void Display::DrawFrameInclusive(Rect *prc)
{
}
DibBitmap *Display::GetBackDib()
{
return m_pbmBack;
}
DibBitmap *Display::GetFrontDib()
{
return m_pbmFront;
}
DibBitmap *Display::GetClippingDib()
{
DibBitmap *pbm = CreateDibBitmap(NULL, kcCopyBy4Procs * 4, kcCopyBy4Procs * 4);
if (pbm == NULL)
return NULL;
m_pbmClip = pbm;
return pbm;
}
void Display::GetHslAdjustments(short *pnHueOffset, short *pnSatMultiplier, short *pnLumOffset)
{
*pnHueOffset = 0;
*pnSatMultiplier = 0;
*pnLumOffset = 0;
}
void Display::FrameStart()
{
// surface->pixels can change every time the surface is locked.
// TODO(darrinm): problem for, e.g. scrolling optimizations?
m_pbmFront->Init(m_gamePixels, m_cx, m_cy);
}
void Display::FrameComplete(int cfrmm, UpdateMap **apupd, Rect *arc,
bool fScrolled)
{
for (int i = 0; i < m_pixelCount; i++) {
m_gamePixels32[i] = m_palette[m_gamePixels[i]];
}
RenderGameSurface();
}
void Display::RenderGameSurface() {
if (!m_fShouldRender)
return;
// Update the texture
SDL_UpdateTexture(m_texture, NULL, m_gamePixels32, m_pitch32);
// Draw any sprites onto the texture
SDL_SetRenderTarget(m_renderer, m_texture);
s_psprm->DrawSprites(m_renderer, s_siz);
SDL_SetRenderTarget(m_renderer, NULL);
// Present the renderer to the screen
SDL_RenderClear(m_renderer);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
SDL_RenderPresent(m_renderer);
}
void Display::ResetScrollOffset()
{
#if 0 // TODO(darrinm): SDL-ify
IPhone::ResetScrollOffset();
#endif
}
SpriteManager *Display::GetSpriteManager()
{
if (s_psprm == NULL)
s_psprm = new SdlSpriteManager();
return s_psprm;
}
void Display::SetFormMgrs(FormMgr *pfrmmSimUI, FormMgr *pfrmmInput)
{
#if 0 // TODO(darrinm): SDL-ify
IPhone::SetFormMgrs(pfrmmSimUI, pfrmmInput);
#endif
}
float Display::Density() {
return m_density;
}
void Display::SetShouldRender(bool fsr) {
m_fShouldRender = fsr;
}
} // namespace wi