NovaCoder |
04 November 2011 03:49 |
C/C++ WB friendly fullscreen game startup code
I thought I'd post the start-up code that I'm now using for my PC ports (it would have saved me a quite few hours!).
I'll also include some WB friendly double buffering as a side-dish.
I code using GCC with the OS3.9 SDK.
Includes (OS 3.9 SDK)
Code:
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
Member variables:
Code:
/** Hardware window */
struct Window *_hardwareWindow;
/** Hardware screen */
struct Screen *_hardwareScreen;
// Hardware double buffering.
struct ScreenBuffer *_hardwareScreenBuffer[2];
byte _currentScreenBuffer;
struct MsgPort *_dispPort;
struct MsgPort *_safePort;
bool _safeToWrite;
bool _safeToChange;
Init stuff.
Code:
_hardwareWindow = NULL;
_hardwareScreenBuffer[0] = NULL;
_hardwareScreenBuffer[1] = NULL;
_currentScreenBuffer = 0;
_dispPort = _safePort = NULL;
_safeToWrite = _safeToChange = true;
_hardwareScreen = NULL;
Open your Screen (8 bit).
Code:
struct Screen* OSystem_AmigaOS3::createHardwareScreen(uint width, uint height) {
// Create the hardware screen.
struct Screen* screen = NULL;
ULONG modeId = INVALID_ID;
modeId = BestModeID(BIDTAG_NominalWidth, width,
BIDTAG_NominalHeight, height,
BIDTAG_DesiredWidth, width,
BIDTAG_DesiredHeight, height,
BIDTAG_Depth, 8,
BIDTAG_MonitorID, VGA_MONITOR_ID,
TAG_END);
if (modeId == INVALID_ID) {
modeId = BestModeID(BIDTAG_NominalWidth, width,
BIDTAG_NominalHeight, height,
BIDTAG_DesiredWidth, width,
BIDTAG_DesiredHeight, height,
BIDTAG_Depth, 8,
BIDTAG_MonitorID, PAL_MONITOR_ID,
TAG_END);
}
if (modeId == INVALID_ID) {
modeId = BestModeID(BIDTAG_NominalWidth, width,
BIDTAG_NominalHeight, height,
BIDTAG_DesiredWidth, width,
BIDTAG_DesiredHeight, height,
BIDTAG_Depth, 8,
BIDTAG_MonitorID, NTSC_MONITOR_ID,
TAG_END);
}
if(modeId == INVALID_ID) {
error("Could not find a valid screen mode");
}
screen = OpenScreenTags(NULL,
SA_Depth, 8,
SA_DisplayID, modeId,
SA_Width, width,
SA_Height, height,
SA_Type, CUSTOMSCREEN,
SA_Overscan, OSCAN_TEXT,
SA_ShowTitle, FALSE,
SA_Draggable, FALSE,
SA_Exclusive, TRUE,
SA_AutoScroll, FALSE,
TAG_END);
return screen;
}
Setup double buffered stuff (and C2P etc)
Code:
_dispPort = CreateMsgPort();
_safePort = CreateMsgPort();
_hardwareScreenBuffer[0] = AllocScreenBuffer(_hardwareScreen, NULL, SB_SCREEN_BITMAP);
_hardwareScreenBuffer[1] = AllocScreenBuffer(_hardwareScreen, NULL, 0);
for (uint i = 0; i < 2; i++) {
_hardwareScreenBuffer[i]->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = _dispPort;
_hardwareScreenBuffer[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = _safePort;
}
_safeToWrite = _safeToChange = true;
_currentScreenBuffer = 1;
Open your Window.
Code:
struct Window* OSystem_AmigaOS3::createHardwareWindow(uint width, uint height) {
return OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, 0,
WA_Width, width,
WA_Height, height,
WA_Title, NULL,
WA_CustomScreen, (ULONG)_hardwareScreen,
WA_Backdrop, TRUE,
WA_Borderless, TRUE,
WA_DragBar, FALSE,
WA_Activate, TRUE,
WA_SmartRefresh, TRUE,
WA_NoCareRefresh, TRUE,
WA_ReportMouse, TRUE,
WA_RMBTrap, TRUE,
WA_IDCMP, IDCMP_RAWKEY|IDCMP_MOUSEMOVE|IDCMP_MOUSEBUTTONS|IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW,
TAG_END);
}
Render loop:
Code:
void OSystem_AmigaOS3::updateScreenInternal(UBYTE *buf) {
// C2P the chunky back-buffer to the screen's bitmap.
[SNIP]
// Check whether the palette was changed.
if (paletteChanged) {
updatePalette();
}
if (ChangeScreenBuffer(hardwareScreen, hardwareScreenBuffer[currentScreenBuffer])) {
// Flip.
currentScreenBuffer = currentScreenBuffer ^ 1;
}
}
Always clean up on exit like a good little coder ;)
Code:
void OSystem_AmigaOS3::deInitBackend() {
if (hardwareWindow) {
debug(1, "deleting window");
ClearPointer(hardwareWindow);
CloseWindow(hardwareWindow);
hardwareWindow = NULL;
}
if (hardwareScreenBuffer[0]) {
debug(1, "deleting screen buffer 1");
WaitBlit();
FreeScreenBuffer(hardwareScreen, hardwareScreenBuffer[0]);
}
if (hardwareScreenBuffer[1]) {
debug(1, "deleting screen buffer 2");
WaitBlit();
FreeScreenBuffer(hardwareScreen, hardwareScreenBuffer[1]);
}
if (safePort) {
debug(1, "deleting Message Port 1");
if (!safeToWrite) {
while(!GetMsg(safePort)) {
Wait(1l<<(safePort->mp_SigBit));
}
}
DeleteMsgPort(safePort);
safePort = NULL;
}
if (dispPort) {
debug(1, "deleting Message Port 2");
if (!safeToChange) {
while(!GetMsg(dispPort)) {
Wait(1l<<(dispPort->mp_SigBit));
}
}
DeleteMsgPort(dispPort);
dispPort = NULL;
}
if (hardwareScreen) {
debug(1, "deleting screen");
CloseScreen(hardwareScreen);
hardwareScreen = NULL;
}
}
|