Descent3/mac/DrawSprocket.cpp
2024-04-16 12:56:40 -06:00

386 lines
14 KiB
C++

#include <Fonts.h>
#include <sound.h>
#include <DrawSprocket.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include "game.h"
#include "gl.h"
#include "aglRenderers.h"
#include "agl.h"
#include "macdisplays.h"
#include "macapp.h"
#include "descent.h"
#include "pstypes.h"
#include "config.h"
#include "application.h"
#include "rend_opengl.h"
const RGBColor rgbBlack = {0x0000, 0x0000, 0x0000};
const RGBColor rgbWhite = {0xFFFF, 0xFFFF, 0xFFFF};
/* globals */
DSpContextAttributes gDSpContextAttributes[N_SUPPORTED_VIDRES];
DSpContextReference gDSpContext[N_SUPPORTED_VIDRES] = {NULL, NULL, NULL};
short current_context = DSP_640x480;
DSpContextReference *gpContextRefUnused = NULL;
GDHandle hGD;
void WindowReset(WindowPtr pWindow, short width, short height);
short gnumDevices = 0;
// Set up DSp screens, handles multi-monitor correctly
void SetupScreen(CGrafPtr *ppWin)
// void SetupScreen (GDHandle *hGD, CGrafPtr *ppWin)
// void SetupScreen (GDHandle *hGD, CGrafPtr *ppWin, short *numDevices)
{
DSpContextAttributes foundAttributes;
DisplayIDType displayID;
Rect rectWin;
RGBColor rgbSave;
GrafPtr pGrafSave;
OSStatus err;
int i;
// check number of screens
GDHandle hDevice = DMGetFirstScreenDevice(true);
do {
gnumDevices++;
hDevice = DMGetNextScreenDevice(hDevice, true);
} while (hDevice);
// start DSp and find a good context
err = DSpStartup();
if (err)
Error("%s:%d DSpStartup: Error %d ", __FILE__, __LINE__, err);
#ifdef DAJ_DEBUG
DSpSetDebugMode(true);
#endif
// Note: DSp currently REQUIRES the back buffer attributes even if only one buffer is required
// Also note: Choose either 16 or 32 bpp
#ifdef USE_OPENGL
for (i = 0; i < N_SUPPORTED_VIDRES; i++) {
memset(&gDSpContextAttributes[i], 0, sizeof(DSpContextAttributes));
// gDSpContextAttributes[i].frequency = 75<<16;
gDSpContextAttributes[i].displayDepthMask = kDSpDepthMask_32;
gDSpContextAttributes[i].displayBestDepth = 32;
gDSpContextAttributes[i].backBufferDepthMask = kDSpDepthMask_16;
gDSpContextAttributes[i].backBufferBestDepth = 16;
gDSpContextAttributes[i].pageCount = 1; // only the front buffer is needed
gDSpContextAttributes[i].displayWidth = Video_res_list[i].width;
gDSpContextAttributes[i].displayHeight = Video_res_list[i].height;
gDSpContextAttributes[i].colorNeeds = kDSpColorNeeds_Require;
}
#else
memset(&gDSpContextAttributes[DSP_640x480], 0, sizeof(DSpContextAttributes));
gDSpContextAttributes[DSP_640x480].displayDepthMask = kDSpDepthMask_16;
gDSpContextAttributes[DSP_640x480].displayBestDepth = 16; // Render_preferred_state.bit_depth;
gDSpContextAttributes[DSP_640x480].backBufferDepthMask = kDSpDepthMask_16;
gDSpContextAttributes[DSP_640x480].backBufferBestDepth = 16;
gDSpContextAttributes[DSP_640x480].pageCount = 1; // only the front buffer is needed
gDSpContextAttributes[DSP_640x480].displayWidth = Video_res_list[DSP_640x480].width;
gDSpContextAttributes[DSP_640x480].displayHeight = Video_res_list[DSP_640x480].height;
gDSpContextAttributes[DSP_640x480].colorNeeds = kDSpColorNeeds_Require;
#endif
// will display user dialog if context selection is required otherwise as find best context
#if 1
err = DSpUserSelectContext(&gDSpContextAttributes[current_context], 0L, nil, &gDSpContext[current_context]);
if (err == kDSpContextNotFoundErr)
exit(0);
else if (err)
Error("%s:%d DSpUserSelectContext: Error %d ", __FILE__, __LINE__, err);
#else
DSpFindBestContext(&gDSpContextAttributes[current_context], &gDSpContext[current_context]);
if (err)
Error("%s:%d DSpFindBestContext: Error %d ", __FILE__, __LINE__, err);
#endif
// see what we actually found
err = DSpContext_GetAttributes(gDSpContext[current_context], &foundAttributes);
if (err)
Error("%s:%d DSpContext_GetAttributes: Error %d ", __FILE__, __LINE__, err);
// reset width and height to full screen and handle our own centering
// HWA will not correctly center less than full screen size contexts
gDSpContextAttributes[current_context].displayWidth = foundAttributes.displayWidth;
gDSpContextAttributes[current_context].displayHeight = foundAttributes.displayHeight;
gDSpContextAttributes[current_context].pageCount = 1; // only the front buffer is needed
gDSpContextAttributes[current_context].contextOptions =
0 | kDSpContextOption_DontSyncVBL; // no page flipping and no VBL sync needed
DSpSetBlankingColor(&rgbBlack);
// get our device for future use
err = DSpContext_GetDisplayID(gDSpContext[current_context], &displayID);
if (err)
Error("%s:%d DSpContext_GetDisplayID: Error %d ", __FILE__, __LINE__, err);
// get GDHandle for ID'd device
err = DMGetGDeviceByDisplayID(displayID, &hGD, false);
if (err)
Error("%s:%d DMGetGDeviceByDisplayID: Error %d ", __FILE__, __LINE__, err);
#ifdef USE_OPENGL
#ifdef SPROCKET17
for (i = 0; i < N_SUPPORTED_VIDRES; i++) {
if (i != current_context) {
err = DSpFindBestContextOnDisplayID(&gDSpContextAttributes[i], &gDSpContext[i], displayID);
if (err)
Error("%s:%d DSpFindBestContextOnDisplayID: Error %d ", __FILE__, __LINE__, err);
}
}
// reserve our menu context
err = DSpContext_Reserve(gDSpContext[current_context], &gDSpContextAttributes[current_context]);
if (err)
Error("DSpContext_Reserve: Error %d", err);
// que up the game context for switching later
for (i = 0; i < N_SUPPORTED_VIDRES; i++) {
if (i != current_context && gDSpContext[i]) {
err = DSpContext_Queue(gDSpContext[current_context], gDSpContext[i], &gDSpContextAttributes[i]);
if (err)
Error("%s:%d DSpContext_Queue: Error %d ", __FILE__, __LINE__, err);
}
}
#else
gnumDevices--; // only count unsued screens
short indexDevice = 0;
if (gnumDevices) {
gpContextRefUnused = (DSpContextReference *)NewPtr((long)sizeof(DSpContextReference) * gnumDevices);
if (gpContextRefUnused == NULL)
Error("%s:%d NewPtr gpContextRefUnused failed", __FILE__, __LINE__);
hDevice = DMGetFirstScreenDevice(true); // check number of screens
if (hDevice == 0)
Error("%s:%d DMGetFirstScreenDevice: Error %d ", __FILE__, __LINE__, err);
do {
if (hDevice != hGD) // if this device is not the one the user chose
{
unsigned long displayID;
DSpContextAttributes contextAttributes;
err = DMGetDisplayIDByGDevice(hDevice, &displayID, false);
if (err)
Error("%s:%d DMGetDisplayIDByGDevice: Error %d ", __FILE__, __LINE__, err);
err = DSpGetFirstContext(displayID, &gpContextRefUnused[indexDevice]); // get a context and
if (err)
Error("%s:%d DSpGetFirstContext: Error %d ", __FILE__, __LINE__, err);
err = DSpContext_GetAttributes(gpContextRefUnused[indexDevice], &contextAttributes); // find attributes
if (err)
Error("%s:%d DSpContext_GetAttributes: Error %d ", __FILE__, __LINE__, err);
err = DSpContext_Reserve(gpContextRefUnused[indexDevice], &contextAttributes); // reserve it
if (err)
Error("%s:%d DSpContext_Reserve: Error %d ", __FILE__, __LINE__, err);
indexDevice++;
}
hDevice = DMGetNextScreenDevice(hDevice, true);
} while (hDevice);
}
for (i = 0; i < N_SUPPORTED_VIDRES; i++) {
if (i != current_context) {
err = DSpFindBestContext(&gDSpContextAttributes[i], &gDSpContext[i]);
if (err)
Error("%s:%d DSpFindBestContext: Error %d ", __FILE__, __LINE__, err);
err = DSpContext_GetAttributes(gDSpContext[i], &gDSpContextAttributes[i]); // see what we actually found
if (err)
Error("%s:%d DSpContext_GetAttributes: Error %d ", __FILE__, __LINE__, err);
gDSpContextAttributes[i].displayWidth = Video_res_list[i].width;
gDSpContextAttributes[i].displayHeight = Video_res_list[i].height;
gDSpContextAttributes[i].pageCount = 1; // only the front buffer is needed
gDSpContextAttributes[i].contextOptions =
0 | kDSpContextOption_DontSyncVBL; // no page flipping and no VBL sync needed
}
}
// reserve our menu context
err = DSpContext_Reserve(gDSpContext[current_context], &gDSpContextAttributes[current_context]);
if (err)
Error("%s:%d DSpContext_Reserve: Error %d ", __FILE__, __LINE__, err);
#endif
#else
err = DSpContext_Reserve(gDSpContext[DSP_640x480], &gDSpContextAttributes[DSP_640x480]);
if (err)
Error("%s:%d DSpContext_Reserve: Error %d ", __FILE__, __LINE__, err);
#endif
#ifndef DAJ_DEBUG
HideCursor();
DSpContext_FadeGammaOut(NULL, NULL); // remove for debug
#endif
// activate our context
err = DSpContext_SetState(gDSpContext[current_context], kDSpContextState_Active);
if (err)
Error("%s:%d DSpContext_SetState: Error %d ", __FILE__, __LINE__, err);
// create a new window in our context (required for multi-monitor handling (for single monitor it would be better to
// just use the context Note: OpenGL is expecting a window so it can enumerate the devices it is on, if you us a
// CGrafPtr instead it MUST be on the main device always
SetRect(&rectWin, 0, 0, 100, 100);
*ppWin = (CGrafPtr)NewCWindow(NULL, &rectWin, "\pDescent 3", 0, plainDBox, (WindowPtr)-1, 0, 0);
WindowReset((GrafPtr)*ppWin, gDSpContextAttributes[current_context].displayWidth,
gDSpContextAttributes[current_context].displayHeight);
#ifndef DAJ_DEBUG
DSpContext_FadeGammaIn(NULL, NULL);
#endif
}
//-----------------------------------------------------------------------------------------------------------------------
// clean up DSp
void ShutdownScreen(CGrafPtr *ppWin) {
OSStatus err;
#ifndef DAJ_DEBUG
DSpContext_FadeGammaOut(NULL, NULL);
#endif
if (*ppWin)
DisposeWindow((WindowPtr)*ppWin);
*ppWin = NULL;
err = DSpContext_SetState(gDSpContext[current_context], kDSpContextState_Inactive);
if (err)
Error("%s:%d DSpContext_SetState: Error %d ", __FILE__, __LINE__, err);
#ifndef DAJ_DEBUG
DSpContext_FadeGammaIn(NULL, NULL);
#endif
ShowCursor();
#ifdef USE_OPENGL
#ifdef SPROCKET17
for (int i = 0; i < N_SUPPORTED_VIDRES; i++)
if (gDSpContext[i])
DSpContext_Release(gDSpContext[i]);
#else
err = DSpContext_Release(gDSpContext[current_context]);
if (err)
Error("%s:%d DSpContext_Release: Error %d ", __FILE__, __LINE__, err);
while (gnumDevices--) // dump our reserved unused devices
{
err = DSpContext_Release(gpContextRefUnused[gnumDevices]);
if (err)
Error("%s:%d DSpContext_Release: Error %d ", __FILE__, __LINE__, err);
}
#endif
#else
DSpContext_Release(gDSpContext[DSP_640x480]);
#endif
DSpShutdown();
}
// Switch between contexts
void SwitchDSpContex(int newContext) {
extern tMacAppInfo macApp;
Rect rectWin;
OSStatus err = 0;
#ifndef USE_OPENGL
return;
#endif
if (current_context == newContext)
return;
if (gDSpContext[current_context] && gDSpContext[newContext]) {
#ifdef SPROCKET17
err = DSpContext_Switch(gDSpContext[current_context], gDSpContext[newContext]);
if (err)
Error("%s:%d DSpContext_Switch: Error %d ", __FILE__, __LINE__, err);
#else
// fade out
#ifndef DAJ_DEBUG
DSpContext_FadeGammaOut(NULL, NULL); // remove for debug
#endif
HideWindow((GrafPtr)macApp.hwnd);
// deactivate our context
err = DSpContext_SetState(gDSpContext[current_context], kDSpContextState_Inactive);
if (err)
Error("%s:%d DSpContext_SetState: Error %d ", __FILE__, __LINE__, err);
// release
err = DSpContext_Release(gDSpContext[current_context]);
if (err)
Error("%s:%d DSpContext_Release: Error %d ", __FILE__, __LINE__, err);
// reserve
err = DSpContext_Reserve(gDSpContext[newContext], &gDSpContextAttributes[newContext]);
if (err)
Error("%s:%d DSpContext_Reserve: Error %d ", __FILE__, __LINE__, err);
// activate
err = DSpContext_SetState(gDSpContext[newContext], kDSpContextState_Active);
if (err)
Error("%s:%d DSpContext_SetState: Error %d ", __FILE__, __LINE__, err);
WindowReset((GrafPtr)macApp.hwnd, gDSpContextAttributes[newContext].displayWidth,
gDSpContextAttributes[newContext].displayHeight);
// fade in
#ifndef DAJ_DEBUG
DSpContext_FadeGammaIn(NULL, NULL);
#endif
#endif
current_context = newContext;
}
}
void PauseDSpContext() {
OSStatus err = 0;
extern tMacAppInfo macApp;
if (gDSpContext[current_context] == NULL)
return;
opengl_DettachContext();
// HideWindow((GrafPtr)macApp.hwnd);
err = DSpContext_SetState(gDSpContext[current_context], kDSpContextState_Paused);
if (err)
Error("%s:%d DSpContext_SetState: Error %d ", __FILE__, __LINE__, err);
}
void ResumeDSpContext() {
OSStatus err = 0;
if (gDSpContext[current_context] == NULL)
return;
err = DSpContext_SetState(gDSpContext[current_context], kDSpContextState_Active);
if (err)
Error("%s:%d DSpContext_SetState: Error %d ", __FILE__, __LINE__, err);
extern tMacAppInfo macApp;
opengl_AttachContext((CGrafPtr)macApp.hwnd);
WindowReset((GrafPtr)macApp.hwnd, gDSpContextAttributes[current_context].displayWidth,
gDSpContextAttributes[current_context].displayHeight);
}
// Window Reset
void WindowReset(WindowPtr pWindow, short width, short height) {
RGBColor rgbSave;
GrafPtr pGrafSave;
short x, y;
y = (short)((**hGD).gdRect.top + (((**hGD).gdRect.bottom - (**hGD).gdRect.top) - height) / 2); // h start
x = (short)((**hGD).gdRect.left + (((**hGD).gdRect.right - (**hGD).gdRect.left) - width) / 2); // v start
MoveWindow(pWindow, x, y, true);
SizeWindow(pWindow, width, height, false);
ShowWindow(pWindow); // will get a white flash here if not faded
GetPort(&pGrafSave);
SetPort(pWindow);
GetForeColor(&rgbSave);
RGBForeColor(&rgbBlack);
PaintRect(&(pWindow->portRect));
RGBForeColor(&rgbSave); // ensure color is reset for proper blitting
SetPort(pGrafSave);
}