More work. Audio driver works enough to play music now.

This commit is contained in:
elasota
2019-12-11 00:51:42 -05:00
parent b1e8e11a56
commit e368cf7235
141 changed files with 8996 additions and 1117 deletions

10
.editorconfig Normal file
View File

@@ -0,0 +1,10 @@
root=true
[*.{h,c,cpp}]
indent_style=tab
indent_size=4
tab_width=4
end_of_line=lf
charset=latin1
trim_trailing_whitespace=true
insert_final_newline=true

2
.gitignore vendored
View File

@@ -2,6 +2,8 @@
*.db
*.opendb
*.ipch
*.iobj
*.ipdb
*.pch
*.user
*.mcp

View File

@@ -11,6 +11,7 @@
#if PL_IS_CPP11
#define PL_DELETED = delete
#define PL_STATIC_ASSERT(n) static_assert((n), "Static assert failed: " #n)
#else
#ifndef nullptr
#define nullptr 0
@@ -25,10 +26,22 @@
#endif
#define PL_DELETED
#endif
template<bool TCondition>
struct __PL_StaticAssertHelper
{
};
template<>
struct __PL_StaticAssertHelper<true>
{
int staticAssertFailed;
};
#define PL_STATIC_ASSERT(n) ((void)(&static_cast<const __PL_StaticAssertHelper<(n)>*>(nullptr)->staticAssertFailed))
#endif
static const size_t PL_SYSTEM_MEMORY_ALIGNMENT = 16;
#endif

25
ConvertResources.bat Normal file
View File

@@ -0,0 +1,25 @@
x64\Release\MiniRez.exe "GpApp2\Glider PRO.r" Packaged\ApplicationResources.gpr
x64\Release\hqx2gp.exe "GpApp2\Houses\Art Museum.binhex" "Packaged\Houses\Art Museum"
x64\Release\hqx2gp.exe "GpApp2\Houses\California or Bust!.binhex" "Packaged\Houses\California or Bust!"
x64\Release\hqx2gp.exe "GpApp2\Houses\Castle o' the Air.binhex" "Packaged\Houses\Castle o' the Air"
x64\Release\hqx2gp.exe "GpApp2\Houses\CD Demo House.binhex" "Packaged\Houses\CD Demo House"
x64\Release\hqx2gp.exe "GpApp2\Houses\Davis Station.binhex" "Packaged\Houses\Davis Station"
x64\Release\hqx2gp.exe "GpApp2\Houses\Demo House.binhex" "Packaged\Houses\Demo House"
x64\Release\hqx2gp.exe "GpApp2\Houses\Empty House.binhex" "Packaged\Houses\Empty House"
x64\Release\hqx2gp.exe "GpApp2\Houses\Fun House.binhex" "Packaged\Houses\Fun House"
x64\Release\hqx2gp.exe "GpApp2\Houses\Grand Prix.binhex" "Packaged\Houses\Grand Prix"
x64\Release\hqx2gp.exe "GpApp2\Houses\ImagineHouse PRO II.binhex" "Packaged\Houses\ImagineHouse PRO II"
x64\Release\hqx2gp.exe "GpApp2\Houses\In The Mirror.binhex" "Packaged\Houses\In The Mirror"
x64\Release\hqx2gp.exe "GpApp2\Houses\Land of Illusion.binhex" "Packaged\Houses\Land of Illusion"
x64\Release\hqx2gp.exe "GpApp2\Houses\Leviathan.binhex" "Packaged\Houses\Leviathan"
x64\Release\hqx2gp.exe "GpApp2\Houses\Metropolis.binhex" "Packaged\Houses\Metropolis"
x64\Release\hqx2gp.exe "GpApp2\Houses\Nemo's Market.binhex" "Packaged\Houses\Nemo's Market"
x64\Release\hqx2gp.exe "GpApp2\Houses\Rainbow's End.binhex" "Packaged\Houses\Rainbow's End"
x64\Release\hqx2gp.exe "GpApp2\Houses\Sampler.binhex" "Packaged\Houses\Sampler"
x64\Release\hqx2gp.exe "GpApp2\Houses\Slumberland.binhex" "Packaged\Houses\Slumberland"
x64\Release\hqx2gp.exe "GpApp2\Houses\SpacePods.binhex" "Packaged\Houses\SpacePods"
x64\Release\hqx2gp.exe "GpApp2\Houses\Teddy World.binhex" "Packaged\Houses\Teddy World"
x64\Release\hqx2gp.exe "GpApp2\Houses\The Asylum Pro.binhex" "Packaged\Houses\The Asylum Pro"
x64\Release\hqx2gp.exe "GpApp2\Houses\Titanic.binhex" "Packaged\Houses\Titanic"
copy /Y "GpApp2\Houses\*.mov" "Packaged\Houses"
pause

View File

@@ -15,6 +15,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GpD3D", "GpD3D\GpD3D.vcxpro
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hqx2gp", "hqx2gp\hqx2gp.vcxproj", "{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PictChecker", "PictChecker\PictChecker.vcxproj", "{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GpAudioDriver_XAudio2", "GpAudioDriver_XAudio2\GpAudioDriver_XAudio2.vcxproj", "{E3BDC783-8646-433E-ADF0-8B6390D36669}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -71,6 +75,22 @@ Global
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Release|x64.Build.0 = Release|x64
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Release|x86.ActiveCfg = Release|Win32
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Release|x86.Build.0 = Release|Win32
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Debug|x64.ActiveCfg = Debug|x64
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Debug|x64.Build.0 = Debug|x64
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Debug|x86.ActiveCfg = Debug|Win32
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Debug|x86.Build.0 = Debug|Win32
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Release|x64.ActiveCfg = Release|x64
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Release|x64.Build.0 = Release|x64
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Release|x86.ActiveCfg = Release|Win32
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Release|x86.Build.0 = Release|Win32
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Debug|x64.ActiveCfg = Debug|x64
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Debug|x64.Build.0 = Debug|x64
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Debug|x86.ActiveCfg = Debug|Win32
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Debug|x86.Build.0 = Debug|Win32
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Release|x64.ActiveCfg = Release|x64
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Release|x64.Build.0 = Release|x64
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Release|x86.ActiveCfg = Release|Win32
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -221,7 +221,7 @@ void IncrementCursor (void)
}
}
else
SetCursor((CursPtr)*GetCursor(watchCursor));
SetBuiltinCursor(watchCursor);
}
//-------------------------------------------------------------- DecrementCursor
@@ -249,7 +249,7 @@ void DecrementCursor (void)
}
}
else
SetCursor((CursPtr)*GetCursor(watchCursor));
SetBuiltinCursor(watchCursor);
}
//-------------------------------------------------------------- SpinCursor

View File

@@ -207,7 +207,22 @@ Boolean DoWeHaveDragManager (void)
short WhatsOurDepth (void)
{
return 8;
PortabilityLayer::PixelFormat pixelFormat;
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(nil, nil, &pixelFormat);
switch (pixelFormat)
{
case PortabilityLayer::PixelFormat_8BitCustom:
case PortabilityLayer::PixelFormat_8BitStandard:
return 8;
case PortabilityLayer::PixelFormat_RGB555:
return 16;
case PortabilityLayer::PixelFormat_RGB24:
case PortabilityLayer::PixelFormat_RGB32:
return 32;
default:
return 0;
}
}
void SwitchToDepth (short, Boolean)
@@ -476,7 +491,7 @@ void GetDeviceRect(Rect *rect)
{
unsigned int width;
unsigned int height;
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(width, height);
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(&width, &height, nil);
SetRect(rect, 0, 0, static_cast<short>(width), static_cast<short>(height));
}

View File

@@ -16,7 +16,7 @@
#define kNilPointer 0L
#define kPutInFront (WindowPtr)-1L
#define kPutInFront (PL_GetPutInFrontWindowPtr())
#define kNormalUpdates TRUE
#define kOneKilobyte 1024
#define kOkayButton 1
@@ -387,4 +387,4 @@ void CloseThisWindow (WindowPtr *);
#include "GliderDefines.h"
#include "GliderStructs.h"
#include "GliderVars.h"
#include "GliderProtos.h"
#include "GliderProtos.h"

View File

@@ -1,57 +1,65 @@
#include "GpAppInterface.h"
#include "DisplayDeviceManager.h"
#include "HostFileSystem.h"
#include "HostDisplayDriver.h"
#include "HostSystemServices.h"
int gpAppMain();
class GpAppInterfaceImpl final : public GpAppInterface
{
public:
int ApplicationMain() override;
void PL_IncrementTickCounter(uint32_t count) override;
void PL_HostFileSystem_SetInstance(PortabilityLayer::HostFileSystem *instance) override;
void PL_HostDisplayDriver_SetInstance(PortabilityLayer::HostDisplayDriver *instance) override;
void PL_HostSystemServices_SetInstance(PortabilityLayer::HostSystemServices *instance) override;
void PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context) override;
};
int GpAppInterfaceImpl::ApplicationMain()
{
return gpAppMain();
}
void GpAppInterfaceImpl::PL_IncrementTickCounter(uint32_t count)
{
PortabilityLayer::DisplayDeviceManager::GetInstance()->IncrementTickCount(count);
}
void GpAppInterfaceImpl::PL_HostFileSystem_SetInstance(PortabilityLayer::HostFileSystem *instance)
{
PortabilityLayer::HostFileSystem::SetInstance(instance);
}
void GpAppInterfaceImpl::PL_HostDisplayDriver_SetInstance(PortabilityLayer::HostDisplayDriver *instance)
{
PortabilityLayer::HostDisplayDriver::SetInstance(instance);
}
void GpAppInterfaceImpl::PL_HostSystemServices_SetInstance(PortabilityLayer::HostSystemServices *instance)
{
PortabilityLayer::HostSystemServices::SetInstance(instance);
}
void GpAppInterfaceImpl::PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context)
{
PortabilityLayer::InstallHostSuspendHook(hook, context);
}
static GpAppInterfaceImpl gs_application;
extern "C" GpAppInterface *GpAppInterface_Get()
{
return &gs_application;
}
#include "GpAppInterface.h"
#include "DisplayDeviceManager.h"
#include "HostAudioDriver.h"
#include "HostFileSystem.h"
#include "HostDisplayDriver.h"
#include "HostSystemServices.h"
int gpAppMain();
class GpAppInterfaceImpl final : public GpAppInterface
{
public:
int ApplicationMain() override;
void PL_IncrementTickCounter(uint32_t count) override;
void PL_HostFileSystem_SetInstance(PortabilityLayer::HostFileSystem *instance) override;
void PL_HostDisplayDriver_SetInstance(PortabilityLayer::HostDisplayDriver *instance) override;
void PL_HostSystemServices_SetInstance(PortabilityLayer::HostSystemServices *instance) override;
void PL_HostAudioDriver_SetInstance(PortabilityLayer::HostAudioDriver *instance) override;
void PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context) override;
};
int GpAppInterfaceImpl::ApplicationMain()
{
return gpAppMain();
}
void GpAppInterfaceImpl::PL_IncrementTickCounter(uint32_t count)
{
PortabilityLayer::DisplayDeviceManager::GetInstance()->IncrementTickCount(count);
}
void GpAppInterfaceImpl::PL_HostFileSystem_SetInstance(PortabilityLayer::HostFileSystem *instance)
{
PortabilityLayer::HostFileSystem::SetInstance(instance);
}
void GpAppInterfaceImpl::PL_HostDisplayDriver_SetInstance(PortabilityLayer::HostDisplayDriver *instance)
{
PortabilityLayer::HostDisplayDriver::SetInstance(instance);
}
void GpAppInterfaceImpl::PL_HostSystemServices_SetInstance(PortabilityLayer::HostSystemServices *instance)
{
PortabilityLayer::HostSystemServices::SetInstance(instance);
}
void GpAppInterfaceImpl::PL_HostAudioDriver_SetInstance(PortabilityLayer::HostAudioDriver *instance)
{
PortabilityLayer::HostAudioDriver::SetInstance(instance);
}
void GpAppInterfaceImpl::PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context)
{
PortabilityLayer::InstallHostSuspendHook(hook, context);
}
static GpAppInterfaceImpl gs_application;
GP_APP_DLL_EXPORT_API GpAppInterface *GpAppInterface_Get()
{
return &gs_application;
}

View File

@@ -37,7 +37,6 @@ Rect houseEditText1, houseEditText2;
short houseCursorIs;
Boolean keyHit, tempPhoneBit;
extern Cursor beamCursor;
extern Boolean noRoomAtAll, changeLockStateOfHouse, saveHouseLocked;
extern Boolean phoneBitSet;
@@ -185,7 +184,7 @@ Boolean HouseFilter (DialogPtr dial, EventRecord *event, short *item)
{
if (houseCursorIs != kBeamCursor)
{
SetCursor(&beamCursor);
SetBuiltinCursor(iBeamCursor);
houseCursorIs = kBeamCursor;
}
}

View File

@@ -23,9 +23,9 @@ extern RgnHandle mirrorRgn;
extern WindowPtr mapWindow, toolsWindow, linkWindow;
extern WindowPtr menuWindow;
extern Rect shieldRect, boardSrcRect, localRoomsDest[];
extern CursHandle handCursorH, beamCursorH, vertCursorH, horiCursorH;
extern CursHandle handCursorH, vertCursorH, horiCursorH;
extern CursHandle diagCursorH;
extern Cursor handCursor, beamCursor, vertCursor, horiCursor;
extern Cursor handCursor, vertCursor, horiCursor;
extern Cursor diagCursor;
extern MenuHandle appleMenu, gameMenu, optionsMenu, houseMenu;
extern Point shieldPt;
@@ -85,12 +85,6 @@ void GetExtraCursors (void)
HLock((Handle)handCursorH);
handCursor = **handCursorH;
beamCursorH = GetCursor(iBeamCursor);
if (beamCursorH == nil)
RedAlert(kErrFailedResourceLoad);
HLock((Handle)beamCursorH);
beamCursor = **beamCursorH;
vertCursorH = GetCursor(kVertCursorID);
if (vertCursorH == nil)
RedAlert(kErrFailedResourceLoad);

View File

@@ -29,9 +29,9 @@ CTabHandle theCTab;
PixMapHandle thePMap;
ColorSpec * wasColors;
ColorSpec * newColors;
CursHandle handCursorH, beamCursorH, vertCursorH, horiCursorH;
CursHandle handCursorH, vertCursorH, horiCursorH;
CursHandle diagCursorH;
Cursor handCursor, beamCursor, vertCursor, horiCursor;
Cursor handCursor, vertCursor, horiCursor;
Cursor diagCursor;
Rect workSrcRect;
GWorldPtr workSrcMap;

View File

@@ -1,4 +1,5 @@
#define _CRT_SECURE_NO_WARNINGS
//============================================================================
//----------------------------------------------------------------------------
// Music.c
@@ -235,11 +236,11 @@ OSErr LoadMusicSounds (void)
HLock(theSound);
soundDataSize = GetHandleSize(theSound) - 20L;
HUnlock(theSound);
theMusicData[i] = NewPtr(soundDataSize);
if (theMusicData[i] == nil)
return (MemError());
HLock(theSound);
BlockMove((Ptr)(static_cast<Byte*>(*theSound) + 20L), theMusicData[i], soundDataSize);
ReleaseResource(theSound);

View File

@@ -1147,7 +1147,7 @@ void DrawCalendar (Rect *theRect)
RedAlert(kErrFailedGraphicLoad);
HLock((Handle)thePicture);
bounds = (*thePicture)->picFrame;
bounds = (*thePicture)->picFrame.ToRect();
HUnlock((Handle)thePicture);
QOffsetRect(&bounds, -bounds.left, -bounds.top);
QOffsetRect(&bounds, theRect->left, theRect->top);
@@ -1183,7 +1183,7 @@ void DrawBulletin (Rect *theRect)
RedAlert(kErrFailedGraphicLoad);
HLock((Handle)thePicture);
bounds = (*thePicture)->picFrame;
bounds = (*thePicture)->picFrame.ToRect();
HUnlock((Handle)thePicture);
QOffsetRect(&bounds, -bounds.left, -bounds.top);
QOffsetRect(&bounds, theRect->left, theRect->top);

View File

@@ -2289,7 +2289,7 @@ void GetThisRoomsObjRects (void)
else
{
HLock((Handle)thePict);
roomObjectRects[i] = (*thePict)->picFrame;
roomObjectRects[i] = (*thePict)->picFrame.ToRect();
HUnlock((Handle)thePict);
}
ZeroRectCorner(&roomObjectRects[i]);

View File

@@ -227,7 +227,7 @@ void GetObjectRect (objectPtr who, Rect *itsRect)
else
{
HLock((Handle)thePict);
*itsRect = (*thePict)->picFrame;
*itsRect = (*thePict)->picFrame.ToRect();
HUnlock((Handle)thePict);
}
ZeroRectCorner(itsRect);

View File

@@ -532,7 +532,7 @@ void PlayGame (void)
if (!thePicture)
RedAlert(kErrFailedGraphicLoad);
HLock((Handle)thePicture);
bounds = (*thePicture)->picFrame;
bounds = (*thePicture)->picFrame.ToRect();
HUnlock((Handle)thePicture);
QOffsetRect(&bounds, -bounds.left, -bounds.top);
QOffsetRect(&bounds, hOffset, 0);
@@ -583,7 +583,7 @@ void PlayGame (void)
if (!thePicture)
RedAlert(kErrFailedGraphicLoad);
HLock((Handle)thePicture);
bounds = (*thePicture)->picFrame;
bounds = (*thePicture)->picFrame.ToRect();
HUnlock((Handle)thePicture);
QOffsetRect(&bounds, -bounds.left, -bounds.top);
QOffsetRect(&bounds, hOffset, 0);

View File

@@ -279,7 +279,7 @@ void ReadyBackground (short theID, short *theTiles)
}
HLock((Handle)thePicture);
dest = (*thePicture)->picFrame;
dest = (*thePicture)->picFrame.ToRect();
HUnlock((Handle)thePicture);
QOffsetRect(&dest, -dest.left, -dest.top);
DrawPicture(thePicture, &dest);

View File

@@ -148,7 +148,7 @@ void LoadGraphicSpecial (short resID)
}
HLock((Handle)thePicture);
bounds = (*thePicture)->picFrame;
bounds = (*thePicture)->picFrame.ToRect();
HUnlock((Handle)thePicture);
OffsetRect(&bounds, -bounds.left, -bounds.top);
DrawPicture(thePicture, &bounds);

View File

@@ -54,7 +54,7 @@ short tileOver, tempBack, cursorIs;
Boolean originalLeftOpen, originalTopOpen, originalRightOpen, originalBottomOpen;
Boolean originalFloor;
extern Cursor handCursor, beamCursor;
extern Cursor handCursor;
extern short houseResFork, lastBackground;
@@ -278,7 +278,7 @@ void HiliteTileOver (Point mouseIs)
{
if (cursorIs != kBeamCursor)
{
SetCursor(&beamCursor);
SetBuiltinCursor(iBeamCursor);
cursorIs = kBeamCursor;
}
}

View File

@@ -82,7 +82,7 @@ void InitScoreboardMap (void)
if (thePicture == nil)
RedAlert(kErrFailedGraphicLoad);
HLock((Handle)thePicture);
bounds = (*thePicture)->picFrame;
bounds = (*thePicture)->picFrame.ToRect();
HUnlock((Handle)thePicture);
QOffsetRect(&bounds, -bounds.left, -bounds.top);
QOffsetRect(&bounds, hOffset, 0);

View File

@@ -301,7 +301,7 @@ void LoadGraphic (short resID)
RedAlert(kErrFailedGraphicLoad);
HLock((Handle)thePicture);
bounds = (*thePicture)->picFrame;
bounds = (*thePicture)->picFrame.ToRect();
HUnlock((Handle)thePicture);
OffsetRect(&bounds, -bounds.left, -bounds.top);
DrawPicture(thePicture, &bounds);

Binary file not shown.

View File

@@ -0,0 +1,108 @@
#include "GpAudioChannelXAudio2.h"
#include "GpAudioDriverXAudio2.h"
#include "IGpAudioChannelCallbacks.h"
#include <stdlib.h>
#include <new>
GpAudioChannelXAudio2 *GpAudioChannelXAudio2::Create(GpAudioDriverXAudio2 *driver)
{
void *storage = malloc(sizeof(GpAudioChannelXAudio2));
if (!storage)
return nullptr;
GpAudioChannelXAudio2 *channel = new (storage) GpAudioChannelXAudio2(driver);
if (!channel->Init())
{
channel->Destroy();
return nullptr;
}
return channel;
}
bool GpAudioChannelXAudio2::Init()
{
const unsigned int sampleRate = m_driver->GetRealSampleRate();
IXAudio2 *const xa2 = m_driver->GetXA2();
WAVEFORMATEX format;
ZeroMemory(&format, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 1;
format.nSamplesPerSec = sampleRate;
format.wBitsPerSample = 8;
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
format.nAvgBytesPerSec = format.nBlockAlign * format.nSamplesPerSec;
XAUDIO2_SEND_DESCRIPTOR sendsList[1];
sendsList[0].Flags = 0;
sendsList[0].pOutputVoice = m_driver->GetMasteringVoice();
XAUDIO2_VOICE_SENDS sends;
sends.pSends = sendsList;
sends.SendCount = sizeof(sendsList) / sizeof(sendsList[0]);
XAUDIO2_VOICE_DETAILS dets;
m_driver->GetMasteringVoice()->GetVoiceDetails(&dets);
HRESULT hr = xa2->CreateSourceVoice(&m_sourceVoice, &format, XAUDIO2_VOICE_NOPITCH | XAUDIO2_VOICE_NOSRC, 1.0f, &m_xAudioCallbacks, nullptr, nullptr);
if (hr != S_OK)
return false;
return true;
}
void GpAudioChannelXAudio2::SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks)
{
m_contextCallbacks = callbacks;
}
void GpAudioChannelXAudio2::PostBuffer(const void *buffer, size_t bufferSize)
{
XAUDIO2_BUFFER xa2Buffer;
xa2Buffer.Flags = 0;
xa2Buffer.AudioBytes = static_cast<UINT32>(bufferSize);
xa2Buffer.pAudioData = static_cast<const BYTE*>(buffer);
xa2Buffer.PlayBegin = 0;
xa2Buffer.PlayLength = 0;
xa2Buffer.LoopBegin = 0;
xa2Buffer.LoopLength = 0;
xa2Buffer.LoopCount = 0;
xa2Buffer.pContext = nullptr;
m_sourceVoice->SubmitSourceBuffer(&xa2Buffer, nullptr);
if (m_voiceState == VoiceState_Idle)
{
m_voiceState = VoiceState_Active;
m_sourceVoice->Start(0, 0);
}
}
void GpAudioChannelXAudio2::Destroy()
{
this->~GpAudioChannelXAudio2();
free(this);
}
void GpAudioChannelXAudio2::OnBufferEnd()
{
if (m_contextCallbacks)
m_contextCallbacks->NotifyBufferFinished();
}
GpAudioChannelXAudio2::GpAudioChannelXAudio2(GpAudioDriverXAudio2 *driver)
: m_driver(driver)
, m_xAudioCallbacks(this)
, m_sourceVoice(nullptr)
, m_contextCallbacks(nullptr)
, m_voiceState(VoiceState_Idle)
{
}
GpAudioChannelXAudio2::~GpAudioChannelXAudio2()
{
if (m_sourceVoice)
m_sourceVoice->DestroyVoice();
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include "IGpAudioChannel.h"
#include "GpAudioChannelXAudio2Callbacks.h"
class GpAudioDriverXAudio2;
class GpAudioChannelXAudio2Callbacks;
struct IXAudio2SourceVoice;
class GpAudioChannelXAudio2 final : public IGpAudioChannel
{
public:
friend class GpAudioChannelXAudio2Callbacks;
static GpAudioChannelXAudio2 *Create(GpAudioDriverXAudio2 *driver);
void SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks);
void PostBuffer(const void *buffer, size_t bufferSize);
void Destroy() override;
bool Init();
protected:
void OnBufferEnd();
private:
enum VoiceState
{
VoiceState_Idle,
VoiceState_Active,
};
explicit GpAudioChannelXAudio2(GpAudioDriverXAudio2 *driver);
~GpAudioChannelXAudio2();
GpAudioDriverXAudio2 *m_driver;
IXAudio2SourceVoice *m_sourceVoice;
GpAudioChannelXAudio2Callbacks m_xAudioCallbacks;
IGpAudioChannelCallbacks *m_contextCallbacks;
VoiceState m_voiceState;
};

View File

@@ -0,0 +1,36 @@
#include "GpAudioChannelXAudio2Callbacks.h"
#include "GpAudioChannelXAudio2.h"
GpAudioChannelXAudio2Callbacks::GpAudioChannelXAudio2Callbacks(GpAudioChannelXAudio2 *owner)
: m_owner(owner)
{
}
void GpAudioChannelXAudio2Callbacks::OnVoiceProcessingPassStart(UINT32 BytesRequired)
{
}
void GpAudioChannelXAudio2Callbacks::OnVoiceProcessingPassEnd()
{
}
void GpAudioChannelXAudio2Callbacks::OnStreamEnd()
{
}
void GpAudioChannelXAudio2Callbacks::OnBufferStart(void* pBufferContext)
{
}
void GpAudioChannelXAudio2Callbacks::OnBufferEnd(void* pBufferContext)
{
m_owner->OnBufferEnd();
}
void GpAudioChannelXAudio2Callbacks::OnLoopEnd(void* pBufferContext)
{
}
void GpAudioChannelXAudio2Callbacks::OnVoiceError(void* pBufferContext, HRESULT Error)
{
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include <xaudio2.h>
class GpAudioChannelXAudio2;
class GpAudioChannelXAudio2Callbacks final : public IXAudio2VoiceCallback
{
public:
explicit GpAudioChannelXAudio2Callbacks(GpAudioChannelXAudio2 *owner);
void OnVoiceProcessingPassStart(UINT32 BytesRequired) override;
void OnVoiceProcessingPassEnd() override;
void OnStreamEnd() override;
void OnBufferStart(void* pBufferContext) override;
void OnBufferEnd(void* pBufferContext) override;
void OnLoopEnd(void* pBufferContext) override;
void OnVoiceError(void* pBufferContext, HRESULT Error) override;
private:
GpAudioChannelXAudio2 *m_owner;
};

View File

@@ -0,0 +1,13 @@
#include "GpAudioDriverFactoryXAudio2.h"
#include "GpAudioDriverXAudio2.h"
IGpAudioDriver *GpAudioDriverFactoryXAudio2::Create(const GpAudioDriverProperties &properties)
{
return GpAudioDriverXAudio2::Create(properties);
}
extern "C" __declspec(dllexport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties)
{
return GpAudioDriverFactoryXAudio2::Create(properties);
}

View File

@@ -0,0 +1,10 @@
#pragma once
class IGpAudioDriver;
struct GpAudioDriverProperties;
class GpAudioDriverFactoryXAudio2
{
public:
static IGpAudioDriver *Create(const GpAudioDriverProperties &properties);
};

View File

@@ -0,0 +1,84 @@
#include "GpAudioDriverXAudio2.h"
#include "GpAudioChannelXAudio2.h"
#include <xaudio2.h>
void GpAudioDriverXAudio2::Shutdown()
{
delete this;
}
const GpAudioDriverProperties &GpAudioDriverXAudio2::GetProperties() const
{
return m_properties;
}
IXAudio2 *GpAudioDriverXAudio2::GetXA2() const
{
return m_xa2;
}
IXAudio2MasteringVoice *GpAudioDriverXAudio2::GetMasteringVoice() const
{
return m_mv;
}
unsigned int GpAudioDriverXAudio2::GetRealSampleRate() const
{
return m_realSampleRate;
}
GpAudioDriverXAudio2 *GpAudioDriverXAudio2::Create(const GpAudioDriverProperties &properties)
{
IXAudio2 *xa = nullptr;
IXAudio2MasteringVoice *mv = nullptr;
const unsigned int realSampleRate = (properties.m_sampleRate + 50) / XAUDIO2_QUANTUM_DENOMINATOR * XAUDIO2_QUANTUM_DENOMINATOR;
if (CoInitializeEx(nullptr, COINIT_MULTITHREADED) != S_OK)
{
CoUninitialize();
return nullptr;
}
UINT flags = 0;
if (properties.m_debug)
flags |= XAUDIO2_DEBUG_ENGINE;
if (FAILED(XAudio2Create(&xa, flags, XAUDIO2_DEFAULT_PROCESSOR)))
{
CoUninitialize();
return nullptr;
}
if (FAILED(xa->CreateMasteringVoice(&mv, 2, realSampleRate, 0, nullptr, nullptr, AudioCategory_GameEffects)))
{
CoUninitialize();
xa->Release();
return nullptr;
}
return new GpAudioDriverXAudio2(properties, realSampleRate, xa, mv);
}
IGpAudioChannel *GpAudioDriverXAudio2::CreateChannel()
{
return GpAudioChannelXAudio2::Create(this);
}
GpAudioDriverXAudio2::GpAudioDriverXAudio2(const GpAudioDriverProperties &properties, unsigned int realSampleRate, IXAudio2* xa2, IXAudio2MasteringVoice *mv)
: m_properties(properties)
, m_realSampleRate(realSampleRate)
, m_xa2(xa2)
, m_mv(mv)
{
}
GpAudioDriverXAudio2::~GpAudioDriverXAudio2()
{
m_mv->DestroyVoice();
m_xa2->Release();
CoUninitialize();
}

View File

@@ -0,0 +1,32 @@
#pragma once
#include "IGpAudioDriver.h"
#include "GpCoreDefs.h"
#include "GpAudioDriverProperties.h"
struct IXAudio2;
struct IXAudio2MasteringVoice;
class GpAudioDriverXAudio2 : public IGpAudioDriver
{
public:
IGpAudioChannel *CreateChannel() override;
void Shutdown() override;
const GpAudioDriverProperties &GetProperties() const;
IXAudio2 *GetXA2() const;
IXAudio2MasteringVoice *GetMasteringVoice() const;
unsigned int GetRealSampleRate() const;
static GpAudioDriverXAudio2 *Create(const GpAudioDriverProperties &properties);
private:
GpAudioDriverXAudio2(const GpAudioDriverProperties &properties, unsigned int realSampleRate, IXAudio2* xa2, IXAudio2MasteringVoice *mv);
~GpAudioDriverXAudio2();
GpAudioDriverProperties m_properties;
IXAudio2* m_xa2;
IXAudio2MasteringVoice *m_mv;
unsigned int m_realSampleRate;
};

View File

@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{E3BDC783-8646-433E-ADF0-8B6390D36669}</ProjectGuid>
<RootNamespace>GpAudioDriverXAudio2</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="GpAudioChannelXAudio2.h" />
<ClInclude Include="GpAudioChannelXAudio2Callbacks.h" />
<ClInclude Include="GpAudioDriverFactoryXAudio2.h" />
<ClInclude Include="GpAudioDriverXAudio2.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="GpAudioChannelXAudio2.cpp" />
<ClCompile Include="GpAudioChannelXAudio2Callbacks.cpp" />
<ClCompile Include="GpAudioDriverFactoryXAudio2.cpp" />
<ClCompile Include="GpAudioDriverXAudio2.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GpAudioDriverFactoryXAudio2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioDriverXAudio2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioChannelXAudio2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioChannelXAudio2Callbacks.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="GpAudioDriverFactoryXAudio2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpAudioDriverXAudio2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpAudioChannelXAudio2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpAudioChannelXAudio2Callbacks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

10
GpCommon.props Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>$(SolutionDir)GpCommon;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />
</Project>

View File

@@ -0,0 +1,8 @@
#pragma once
enum EGpAudioDriverType
{
EGpAudioDriverType_XAudio2,
EGpAudioDriverType_Count,
};

View File

@@ -0,0 +1,13 @@
#pragma once
#include "EGpAudioDriverType.h"
class IGpAudioDriver;
struct GpAudioDriverProperties
{
EGpAudioDriverType m_type;
unsigned int m_sampleRate;
bool m_debug;
};

View File

@@ -0,0 +1,26 @@
#pragma once
#include "EGpDisplayDriverType.h"
class IGpDisplayDriver;
class GpFiber;
struct GpDisplayDriverProperties
{
typedef void(*TickFunc_t)(void *context, GpFiber *vosFiber);
EGpDisplayDriverType m_type;
unsigned int m_frameTimeLockNumerator;
unsigned int m_frameTimeLockDenominator;
unsigned int m_frameTimeLockMinNumerator;
unsigned int m_frameTimeLockMinDenominator;
unsigned int m_frameTimeLockMaxNumerator;
unsigned int m_frameTimeLockMaxDenominator;
// Tick function and context to call when a frame needs to be served.
TickFunc_t m_tickFunc;
void *m_tickFuncContext;
};

View File

@@ -0,0 +1,10 @@
#pragma once
struct IGpAudioChannelCallbacks;
struct IGpAudioChannel
{
virtual void SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks) = 0;
virtual void PostBuffer(const void *buffer, size_t bufferSize) = 0;
virtual void Destroy() = 0;
};

View File

@@ -0,0 +1,6 @@
#pragma once
struct IGpAudioChannelCallbacks
{
virtual void NotifyBufferFinished() = 0;
};

13
GpCommon/IGpAudioDriver.h Normal file
View File

@@ -0,0 +1,13 @@
#pragma once
struct IGpAudioChannel;
class IGpAudioDriver
{
public:
virtual ~IGpAudioDriver() {}
virtual IGpAudioChannel *CreateChannel() = 0;
virtual void Shutdown() = 0;
};

View File

@@ -1,4 +1,6 @@
#pragma once
#pragma once
#include "PixelFormat.h"
// Display drivers are responsible for timing and calling the game tick function.
class IGpDisplayDriver
@@ -9,5 +11,5 @@ public:
virtual void Run() = 0;
virtual void Shutdown() = 0;
virtual void GetDisplayResolution(unsigned int &width, unsigned int &height) = 0;
virtual void GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp) = 0;
};

View File

@@ -1,130 +1,139 @@
#include "GpAppEnvironment.h"
#include "GpFiberStarter.h"
#include "GpAppInterface.h"
#include "GpPLGlueDisplayDriver.h"
#include "GpFiber.h"
#include "HostSuspendCallArgument.h"
#include <assert.h>
GpAppEnvironment::GpAppEnvironment()
: m_applicationState(ApplicationState_NotStarted)
, m_displayDriver(nullptr)
, m_applicationFiber(nullptr)
, m_vosFiber(nullptr)
, m_suspendCallID(PortabilityLayer::HostSuspendCallID_Unknown)
, m_suspendArgs(nullptr)
, m_suspendReturnValue(nullptr)
{
}
GpAppEnvironment::~GpAppEnvironment()
{
assert(m_applicationFiber == nullptr);
}
void GpAppEnvironment::Init()
{
}
void GpAppEnvironment::Tick(GpFiber *vosFiber)
{
GpAppInterface_Get()->PL_IncrementTickCounter(1);
m_vosFiber = vosFiber;
if (m_applicationState == ApplicationState_WaitingForEvents)
m_applicationState = ApplicationState_Running;
for (;;)
{
switch (m_applicationState)
{
case ApplicationState_NotStarted:
InitializeApplicationState();
m_applicationFiber = GpFiberStarter::StartFiber(GpAppEnvironment::StaticAppThreadFunc, this, vosFiber);
m_applicationState = ApplicationState_Running;
break;
case ApplicationState_WaitingForEvents:
return;
case ApplicationState_Running:
m_applicationFiber->YieldTo();
break;
case ApplicationState_SystemCall:
{
PortabilityLayer::HostSuspendCallID callID = m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *args = m_suspendArgs;
PortabilityLayer::HostSuspendCallArgument *returnValue = m_suspendReturnValue;
DispatchSystemCall(callID, args, returnValue);
assert(m_applicationState != ApplicationState_SystemCall);
}
break;
case ApplicationState_TimedSuspend:
if (m_delaySuspendTicks <= 1)
m_applicationState = ApplicationState_Running;
else
{
m_delaySuspendTicks--;
return;
}
break;
default:
assert(false);
break;
};
}
}
void GpAppEnvironment::SetDisplayDriver(IGpDisplayDriver *displayDriver)
{
m_displayDriver = displayDriver;
}
void GpAppEnvironment::StaticAppThreadFunc(void *context)
{
static_cast<GpAppEnvironment*>(context)->AppThreadFunc();
}
void GpAppEnvironment::AppThreadFunc()
{
GpAppInterface_Get()->ApplicationMain();
}
void GpAppEnvironment::InitializeApplicationState()
{
GpAppInterface_Get()->PL_HostDisplayDriver_SetInstance(GpPLGlueDisplayDriver::GetInstance());
GpAppInterface_Get()->PL_InstallHostSuspendHook(GpAppEnvironment::StaticSuspendHookFunc, this);
SynchronizeState();
}
void GpAppEnvironment::SynchronizeState()
{
GpPLGlueDisplayDriver::GetInstance()->SetGpDisplayDriver(m_displayDriver);
}
void GpAppEnvironment::StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
{
GpAppEnvironment *appEnv = static_cast<GpAppEnvironment*>(context);
appEnv->m_suspendCallID = callID;
appEnv->m_suspendArgs = args;
appEnv->m_suspendReturnValue = returnValue;
appEnv->m_applicationState = ApplicationState_SystemCall;
appEnv->m_vosFiber->YieldTo();
}
void GpAppEnvironment::DispatchSystemCall(PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
{
switch (callID)
{
case PortabilityLayer::HostSuspendCallID_Delay:
m_applicationState = ApplicationState_TimedSuspend;
m_delaySuspendTicks = args[0].m_uint;
break;
default:
assert(false);
}
}
#include "GpAppEnvironment.h"
#include "GpFiberStarter.h"
#include "GpAppInterface.h"
#include "GpPLGlueAudioDriver.h"
#include "GpPLGlueDisplayDriver.h"
#include "GpFiber.h"
#include "HostSuspendCallArgument.h"
#include <assert.h>
GpAppEnvironment::GpAppEnvironment()
: m_applicationState(ApplicationState_NotStarted)
, m_displayDriver(nullptr)
, m_audioDriver(nullptr)
, m_applicationFiber(nullptr)
, m_vosFiber(nullptr)
, m_suspendCallID(PortabilityLayer::HostSuspendCallID_Unknown)
, m_suspendArgs(nullptr)
, m_suspendReturnValue(nullptr)
{
}
GpAppEnvironment::~GpAppEnvironment()
{
assert(m_applicationFiber == nullptr);
}
void GpAppEnvironment::Init()
{
}
void GpAppEnvironment::Tick(GpFiber *vosFiber)
{
GpAppInterface_Get()->PL_IncrementTickCounter(1);
m_vosFiber = vosFiber;
if (m_applicationState == ApplicationState_WaitingForEvents)
m_applicationState = ApplicationState_Running;
for (;;)
{
switch (m_applicationState)
{
case ApplicationState_NotStarted:
InitializeApplicationState();
m_applicationFiber = GpFiberStarter::StartFiber(GpAppEnvironment::StaticAppThreadFunc, this, vosFiber);
m_applicationState = ApplicationState_Running;
break;
case ApplicationState_WaitingForEvents:
return;
case ApplicationState_Running:
m_applicationFiber->YieldTo();
break;
case ApplicationState_SystemCall:
{
PortabilityLayer::HostSuspendCallID callID = m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *args = m_suspendArgs;
PortabilityLayer::HostSuspendCallArgument *returnValue = m_suspendReturnValue;
DispatchSystemCall(callID, args, returnValue);
assert(m_applicationState != ApplicationState_SystemCall);
}
break;
case ApplicationState_TimedSuspend:
if (m_delaySuspendTicks <= 1)
m_applicationState = ApplicationState_Running;
else
{
m_delaySuspendTicks--;
return;
}
break;
default:
assert(false);
break;
};
}
}
void GpAppEnvironment::SetDisplayDriver(IGpDisplayDriver *displayDriver)
{
m_displayDriver = displayDriver;
}
void GpAppEnvironment::SetAudioDriver(IGpAudioDriver *audioDriver)
{
m_audioDriver = audioDriver;
}
void GpAppEnvironment::StaticAppThreadFunc(void *context)
{
static_cast<GpAppEnvironment*>(context)->AppThreadFunc();
}
void GpAppEnvironment::AppThreadFunc()
{
GpAppInterface_Get()->ApplicationMain();
}
void GpAppEnvironment::InitializeApplicationState()
{
GpAppInterface_Get()->PL_HostDisplayDriver_SetInstance(GpPLGlueDisplayDriver::GetInstance());
GpAppInterface_Get()->PL_HostAudioDriver_SetInstance(GpPLGlueAudioDriver::GetInstance());
GpAppInterface_Get()->PL_InstallHostSuspendHook(GpAppEnvironment::StaticSuspendHookFunc, this);
SynchronizeState();
}
void GpAppEnvironment::SynchronizeState()
{
GpPLGlueDisplayDriver::GetInstance()->SetGpDisplayDriver(m_displayDriver);
GpPLGlueAudioDriver::GetInstance()->SetGpAudioDriver(m_audioDriver);
}
void GpAppEnvironment::StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
{
GpAppEnvironment *appEnv = static_cast<GpAppEnvironment*>(context);
appEnv->m_suspendCallID = callID;
appEnv->m_suspendArgs = args;
appEnv->m_suspendReturnValue = returnValue;
appEnv->m_applicationState = ApplicationState_SystemCall;
appEnv->m_vosFiber->YieldTo();
}
void GpAppEnvironment::DispatchSystemCall(PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
{
switch (callID)
{
case PortabilityLayer::HostSuspendCallID_Delay:
m_applicationState = ApplicationState_TimedSuspend;
m_delaySuspendTicks = args[0].m_uint;
break;
default:
assert(false);
}
}

View File

@@ -1,55 +1,58 @@
#pragma once
#include "HostSuspendCallID.h"
#include <stdint.h>
namespace PortabilityLayer
{
union HostSuspendCallArgument;
}
class IGpDisplayDriver;
class GpFiber;
class GpAppEnvironment
{
public:
GpAppEnvironment();
~GpAppEnvironment();
void Init();
void Tick(GpFiber *vosFiber);
void SetDisplayDriver(IGpDisplayDriver *displayDriver);
private:
enum ApplicationState
{
ApplicationState_NotStarted,
ApplicationState_WaitingForEvents,
ApplicationState_Running,
ApplicationState_Terminated,
ApplicationState_SystemCall,
ApplicationState_TimedSuspend,
};
static void StaticAppThreadFunc(void *context);
void AppThreadFunc();
void InitializeApplicationState();
void SynchronizeState();
static void StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue);
void DispatchSystemCall(PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue);
ApplicationState m_applicationState;
IGpDisplayDriver *m_displayDriver;
GpFiber *m_applicationFiber;
GpFiber *m_vosFiber;
uint32_t m_delaySuspendTicks;
PortabilityLayer::HostSuspendCallID m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *m_suspendArgs;
PortabilityLayer::HostSuspendCallArgument *m_suspendReturnValue;
};
#pragma once
#include "HostSuspendCallID.h"
#include <stdint.h>
namespace PortabilityLayer
{
union HostSuspendCallArgument;
}
class IGpDisplayDriver;
class IGpAudioDriver;
class GpFiber;
class GpAppEnvironment
{
public:
GpAppEnvironment();
~GpAppEnvironment();
void Init();
void Tick(GpFiber *vosFiber);
void SetDisplayDriver(IGpDisplayDriver *displayDriver);
void SetAudioDriver(IGpAudioDriver *audioDriver);
private:
enum ApplicationState
{
ApplicationState_NotStarted,
ApplicationState_WaitingForEvents,
ApplicationState_Running,
ApplicationState_Terminated,
ApplicationState_SystemCall,
ApplicationState_TimedSuspend,
};
static void StaticAppThreadFunc(void *context);
void AppThreadFunc();
void InitializeApplicationState();
void SynchronizeState();
static void StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue);
void DispatchSystemCall(PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue);
ApplicationState m_applicationState;
IGpDisplayDriver *m_displayDriver;
IGpAudioDriver *m_audioDriver;
GpFiber *m_applicationFiber;
GpFiber *m_vosFiber;
uint32_t m_delaySuspendTicks;
PortabilityLayer::HostSuspendCallID m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *m_suspendArgs;
PortabilityLayer::HostSuspendCallArgument *m_suspendReturnValue;
};

View File

@@ -0,0 +1,23 @@
#include "GpAudioDriverFactory.h"
#include "GpAudioDriverProperties.h"
#include <assert.h>
IGpAudioDriver *GpAudioDriverFactory::CreateAudioDriver(const GpAudioDriverProperties &properties)
{
assert(properties.m_type < EGpAudioDriverType_Count);
if (ms_registry[properties.m_type])
return ms_registry[properties.m_type](properties);
else
return nullptr;
}
void GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType type, FactoryFunc_t func)
{
assert(type < EGpAudioDriverType_Count);
ms_registry[type] = func;
}
GpAudioDriverFactory::FactoryFunc_t GpAudioDriverFactory::ms_registry[EGpAudioDriverType_Count];

View File

@@ -0,0 +1,18 @@
#pragma once
#include "EGpAudioDriverType.h"
class IGpAudioDriver;
struct GpAudioDriverProperties;
class GpAudioDriverFactory
{
public:
typedef IGpAudioDriver *(*FactoryFunc_t)(const GpAudioDriverProperties &properties);
static IGpAudioDriver *CreateAudioDriver(const GpAudioDriverProperties &properties);
static void RegisterAudioDriverFactory(EGpAudioDriverType type, FactoryFunc_t func);
private:
static FactoryFunc_t ms_registry[EGpAudioDriverType_Count];
};

View File

View File

@@ -60,21 +60,29 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
@@ -128,9 +136,9 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="GpAppEnvironment.cpp" />
<ClCompile Include="GpAudioDriverFactory.cpp" />
<ClCompile Include="GpDisplayDriverFactory.cpp" />
<ClCompile Include="GpDisplayDriverFactoryD3D11.cpp" />
<ClCompile Include="GpEvent_Win32.cpp" />
<ClCompile Include="GpFiber_Win32.cpp" />
<ClCompile Include="GpFileStream_Win32.cpp" />
<ClCompile Include="GpFileSystem_Win32.cpp" />
@@ -139,19 +147,27 @@
<ClCompile Include="GpMain_Win32.cpp" />
<ClCompile Include="GpDisplayDriverD3D11.cpp" />
<ClCompile Include="GpMemoryBuffer.cpp" />
<ClCompile Include="GpMutex_Win32.cpp" />
<ClCompile Include="GpPLGlueAudioChannel.cpp" />
<ClCompile Include="GpPLGlueAudioDriver.cpp" />
<ClCompile Include="GpPLGlueDisplayDriver.cpp" />
<ClCompile Include="GpSystemServices_Win32.cpp" />
<ClCompile Include="GpFiberStarter_Win32.cpp" />
<ClCompile Include="GpThreadEvent_Win32.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h" />
<ClInclude Include="EGpAudioDriverType.h" />
<ClInclude Include="EGpDisplayDriverType.h" />
<ClInclude Include="GpAppEnvironment.h" />
<ClInclude Include="GpAudioDriverFactory.h" />
<ClInclude Include="GpAudioDriverProperties.h" />
<ClInclude Include="GpAudioDriverXAudio2.h" />
<ClInclude Include="GpCoreDefs.h" />
<ClInclude Include="GpDisplayDriverD3D11.h" />
<ClInclude Include="GpDisplayDriverFactory.h" />
<ClInclude Include="GpDisplayDriverFactoryD3D11.h" />
<ClInclude Include="GpDisplayDriverProperties.h" />
<ClInclude Include="GpEvent.h" />
<ClInclude Include="GpFiber.h" />
<ClInclude Include="GpFiber_Win32.h" />
<ClInclude Include="GpFileStream_Win32.h" />
@@ -159,17 +175,26 @@
<ClInclude Include="GpGlobalConfig.h" />
<ClInclude Include="GpMain.h" />
<ClInclude Include="GpMemoryBuffer.h" />
<ClInclude Include="GpMutex_Win32.h" />
<ClInclude Include="GpPLGlueAudioChannel.h" />
<ClInclude Include="GpPLGlueAudioDriver.h" />
<ClInclude Include="GpPLGlueDisplayDriver.h" />
<ClInclude Include="GpRingBuffer.h" />
<ClInclude Include="GpSystemServices_Win32.h" />
<ClInclude Include="GpFiberStarter.h" />
<ClInclude Include="GpThreadEvent_Win32.h" />
<ClInclude Include="GpWindows.h" />
<ClInclude Include="IGpAudioChannel.h" />
<ClInclude Include="IGpAudioDriver.h" />
<ClInclude Include="IGpDisplayDriver.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GpApp\GpApp.vcxproj">
<Project>{6233c3f2-5781-488e-b190-4fa8836f5a77}</Project>
</ProjectReference>
<ProjectReference Include="..\GpAudioDriver_XAudio2\GpAudioDriver_XAudio2.vcxproj">
<Project>{e3bdc783-8646-433e-adf0-8b6390d36669}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@@ -36,9 +36,6 @@
<ClCompile Include="GpAppEnvironment.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpEvent_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFileSystem_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -60,6 +57,21 @@
<ClCompile Include="GpFiber_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpPLGlueAudioDriver.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpAudioDriverFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpPLGlueAudioChannel.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpMutex_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpThreadEvent_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GpWindows.h">
@@ -98,9 +110,6 @@
<ClInclude Include="GpRingBuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpEvent.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpFileSystem_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -125,5 +134,38 @@
<ClInclude Include="GpFiber.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IGpAudioDriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioDriverFactory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="EGpAudioDriverType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioDriverProperties.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpPLGlueAudioDriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioDriverXAudio2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpPLGlueAudioChannel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IGpAudioChannel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpMutex_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpThreadEvent_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -1,290 +1,294 @@
#include "GpDisplayDriverD3D11.h"
#include "GpWindows.h"
#include "GpFiber_Win32.h"
#include <d3d11.h>
#include <dxgi1_2.h>
#include <stdio.h>
#pragma comment (lib, "d3d11.lib")
void DebugPrintf(const char *fmt, ...)
{
char buf[256];
va_list argp;
va_start(argp, fmt);
vsnprintf_s(buf, 255, fmt, argp);
OutputDebugString(buf);
va_end(argp);
}
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void StartD3DForWindow(HWND hWnd, IDXGISwapChain1*& swapChain)
{
DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = 2;
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc;
ZeroMemory(&swapChainFullscreenDesc, sizeof(swapChainFullscreenDesc));
swapChainFullscreenDesc.Windowed = TRUE;
swapChainFullscreenDesc.RefreshRate.Numerator = 60;
swapChainFullscreenDesc.RefreshRate.Denominator = 1;
UINT flags = 0;
const D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_9_1
};
flags |= D3D11_CREATE_DEVICE_DEBUG;
ID3D11Device *device = NULL;
ID3D11DeviceContext *context = NULL;
D3D_FEATURE_LEVEL selectedFeatureLevel;
HRESULT result = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, featureLevels, sizeof(featureLevels) / sizeof(featureLevels[0]),
D3D11_SDK_VERSION, &device, &selectedFeatureLevel, &context);
IDXGIDevice2 *dxgiDevice = nullptr;
result = device->QueryInterface(__uuidof(IDXGIDevice2), reinterpret_cast<void**>(&dxgiDevice));
IDXGIAdapter *dxgiAdapter = nullptr;
result = dxgiDevice->GetAdapter(&dxgiAdapter);
IDXGIFactory2 *dxgiFactory = nullptr;
result = dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory));
result = dxgiFactory->CreateSwapChainForHwnd(device, hWnd, &swapChainDesc, nullptr, nullptr, &swapChain);
}
bool GpDisplayDriverD3D11::PresentFrameAndSync()
{
DXGI_PRESENT_PARAMETERS presentParams;
ZeroMemory(&presentParams, sizeof(presentParams));
UINT lastPresentCount = 0;
if (FAILED(m_SwapChain->GetLastPresentCount(&lastPresentCount)))
return false;
if (FAILED(m_SwapChain->Present1(1, 0, &presentParams)))
return false;
//DebugPrintf("r: %i\n", static_cast<int>(r));
DXGI_FRAME_STATISTICS stats;
if (FAILED(m_SwapChain->GetFrameStatistics(&stats)))
return false;
if (stats.SyncQPCTime.QuadPart != 0)
{
if (m_SyncTimeBase.QuadPart == 0)
m_SyncTimeBase = stats.SyncQPCTime;
LARGE_INTEGER timestamp;
timestamp.QuadPart = stats.SyncQPCTime.QuadPart - m_SyncTimeBase.QuadPart;
bool compacted = false;
if (m_PresentHistory.Size() > 0)
{
CompactedPresentHistoryItem &lastItem = m_PresentHistory[m_PresentHistory.Size() - 1];
LONGLONG timeDelta = timestamp.QuadPart - lastItem.m_Timestamp.QuadPart;
if (timeDelta < 0)
timeDelta = 0; // This should never happen
if (timeDelta * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockDenominator) < m_QPFrequency.QuadPart * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockNumerator))
{
lastItem.m_NumFrames++;
compacted = true;
}
}
if (!compacted)
{
if (m_PresentHistory.Size() == m_PresentHistory.CAPACITY)
m_PresentHistory.RemoveFromStart();
CompactedPresentHistoryItem *newItem = m_PresentHistory.Append();
newItem->m_Timestamp = timestamp;
newItem->m_NumFrames = 1;
}
}
if (m_PresentHistory.Size() >= 2)
{
const size_t presentHistorySizeMinusOne = m_PresentHistory.Size() - 1;
unsigned int numFrames = 0;
for (size_t i = 0; i < presentHistorySizeMinusOne; i++)
numFrames += m_PresentHistory[i].m_NumFrames;
LONGLONG timeFrame = m_PresentHistory[presentHistorySizeMinusOne].m_Timestamp.QuadPart - m_PresentHistory[0].m_Timestamp.QuadPart;
unsigned int cancelledFrames = 0;
LONGLONG cancelledTime = 0;
const int overshootTolerance = 2;
for (size_t i = 0; i < presentHistorySizeMinusOne; i++)
{
LONGLONG blockTimeframe = m_PresentHistory[i + 1].m_Timestamp.QuadPart - m_PresentHistory[i].m_Timestamp.QuadPart;
unsigned int blockNumFrames = m_PresentHistory[i].m_NumFrames;
if (blockTimeframe * static_cast<LONGLONG>(numFrames) >= timeFrame * static_cast<LONGLONG>(blockNumFrames) * overshootTolerance)
{
cancelledTime += blockTimeframe;
cancelledFrames += blockNumFrames;
}
}
numFrames -= cancelledFrames;
timeFrame -= cancelledTime;
// timeFrame / numFrames = Frame timestep
// Unless Frame timestep is within the frame lock range, a.k.a.
// timeFrame / numFrames / qpFreq >= minFrameTimeNum / minFrameTimeDenom
bool isInFrameTimeLock = false;
if (timeFrame * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockMinDenominator) >= static_cast<LONGLONG>(numFrames) * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockMinNumerator) * m_QPFrequency.QuadPart
&& timeFrame * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockMaxDenominator) <= static_cast<LONGLONG>(numFrames) * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockMaxNumerator) * m_QPFrequency.QuadPart)
{
isInFrameTimeLock = true;
}
LONGLONG frameTimeStep = m_FrameTimeSliceSize;
if (!isInFrameTimeLock)
{
const int MAX_FRAMES_PER_STEP = 4;
frameTimeStep = timeFrame / numFrames;
if (frameTimeStep > m_FrameTimeSliceSize * MAX_FRAMES_PER_STEP)
frameTimeStep = m_FrameTimeSliceSize * MAX_FRAMES_PER_STEP;
}
m_FrameTimeAccumulated += frameTimeStep;
while (m_FrameTimeAccumulated >= m_FrameTimeSliceSize)
{
m_Properties.m_TickFunc(m_Properties.m_TickFuncContext, m_vosFiber);
m_FrameTimeAccumulated -= m_FrameTimeSliceSize;
}
}
return true;
}
void GpDisplayDriverD3D11::Run()
{
HWND hWnd;
WNDCLASSEX wc;
LPVOID fiber = ConvertThreadToFiberEx(this, 0);
if (!fiber)
return; // ???
m_vosFiber = new GpFiber_Win32(fiber);
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WinProc;
wc.hInstance = g_gpWindowsGlobals.m_hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "GPD3D11WindowClass";
RegisterClassEx(&wc);
LONG windowStyle = WS_OVERLAPPEDWINDOW;
HMENU menus = NULL;
// TODO: Fix the resolution here
RECT wr = { 0, 0, m_windowWidth, m_windowHeight };
AdjustWindowRect(&wr, windowStyle, menus != NULL);
hWnd = CreateWindowExW(NULL, L"GPD3D11WindowClass", L"GlidePort", WS_OVERLAPPEDWINDOW, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, menus, g_gpWindowsGlobals.m_hInstance, NULL);
ShowWindow(hWnd, g_gpWindowsGlobals.m_nCmdShow);
StartD3DForWindow(hWnd, m_SwapChain);
LARGE_INTEGER lastTimestamp;
memset(&lastTimestamp, 0, sizeof(lastTimestamp));
MSG msg;
for (;;)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
}
else
{
PresentFrameAndSync();
}
}
// Exit
ConvertFiberToThread();
}
void GpDisplayDriverD3D11::Shutdown()
{
delete this;
}
void GpDisplayDriverD3D11::GetDisplayResolution(unsigned int &width, unsigned int &height)
{
width = m_windowWidth;
height = m_windowHeight;
}
GpDisplayDriverD3D11 *GpDisplayDriverD3D11::Create(const GpDisplayDriverProperties &properties)
{
return new GpDisplayDriverD3D11(properties);
}
GpDisplayDriverD3D11::GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties)
: m_Properties(properties)
, m_FrameTimeAccumulated(0)
, m_windowWidth(640)
, m_windowHeight(480)
, m_vosFiber(nullptr)
{
memset(&m_SyncTimeBase, 0, sizeof(m_SyncTimeBase));
QueryPerformanceFrequency(&m_QPFrequency);
m_FrameTimeSliceSize = m_QPFrequency.QuadPart * static_cast<LONGLONG>(properties.m_FrameTimeLockNumerator) / static_cast<LONGLONG>(properties.m_FrameTimeLockDenominator);
}
#include "GpDisplayDriverD3D11.h"
#include "GpWindows.h"
#include "GpFiber_Win32.h"
#include <d3d11.h>
#include <dxgi1_2.h>
#include <stdio.h>
#pragma comment (lib, "d3d11.lib")
void DebugPrintf(const char *fmt, ...)
{
char buf[256];
va_list argp;
va_start(argp, fmt);
vsnprintf_s(buf, 255, fmt, argp);
OutputDebugString(buf);
va_end(argp);
}
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void StartD3DForWindow(HWND hWnd, IDXGISwapChain1*& swapChain)
{
DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = 2;
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc;
ZeroMemory(&swapChainFullscreenDesc, sizeof(swapChainFullscreenDesc));
swapChainFullscreenDesc.Windowed = TRUE;
swapChainFullscreenDesc.RefreshRate.Numerator = 60;
swapChainFullscreenDesc.RefreshRate.Denominator = 1;
UINT flags = 0;
const D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_9_1
};
flags |= D3D11_CREATE_DEVICE_DEBUG;
ID3D11Device *device = NULL;
ID3D11DeviceContext *context = NULL;
D3D_FEATURE_LEVEL selectedFeatureLevel;
HRESULT result = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, featureLevels, sizeof(featureLevels) / sizeof(featureLevels[0]),
D3D11_SDK_VERSION, &device, &selectedFeatureLevel, &context);
IDXGIDevice2 *dxgiDevice = nullptr;
result = device->QueryInterface(__uuidof(IDXGIDevice2), reinterpret_cast<void**>(&dxgiDevice));
IDXGIAdapter *dxgiAdapter = nullptr;
result = dxgiDevice->GetAdapter(&dxgiAdapter);
IDXGIFactory2 *dxgiFactory = nullptr;
result = dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory));
result = dxgiFactory->CreateSwapChainForHwnd(device, hWnd, &swapChainDesc, nullptr, nullptr, &swapChain);
}
bool GpDisplayDriverD3D11::PresentFrameAndSync()
{
DXGI_PRESENT_PARAMETERS presentParams;
ZeroMemory(&presentParams, sizeof(presentParams));
UINT lastPresentCount = 0;
if (FAILED(m_swapChain->GetLastPresentCount(&lastPresentCount)))
return false;
if (FAILED(m_swapChain->Present1(1, 0, &presentParams)))
return false;
//DebugPrintf("r: %i\n", static_cast<int>(r));
DXGI_FRAME_STATISTICS stats;
if (FAILED(m_swapChain->GetFrameStatistics(&stats)))
return false;
if (stats.SyncQPCTime.QuadPart != 0)
{
if (m_syncTimeBase.QuadPart == 0)
m_syncTimeBase = stats.SyncQPCTime;
LARGE_INTEGER timestamp;
timestamp.QuadPart = stats.SyncQPCTime.QuadPart - m_syncTimeBase.QuadPart;
bool compacted = false;
if (m_presentHistory.Size() > 0)
{
CompactedPresentHistoryItem &lastItem = m_presentHistory[m_presentHistory.Size() - 1];
LONGLONG timeDelta = timestamp.QuadPart - lastItem.m_timestamp.QuadPart;
if (timeDelta < 0)
timeDelta = 0; // This should never happen
if (timeDelta * static_cast<LONGLONG>(m_properties.m_frameTimeLockDenominator) < m_QPFrequency.QuadPart * static_cast<LONGLONG>(m_properties.m_frameTimeLockNumerator))
{
lastItem.m_numFrames++;
compacted = true;
}
}
if (!compacted)
{
if (m_presentHistory.Size() == m_presentHistory.CAPACITY)
m_presentHistory.RemoveFromStart();
CompactedPresentHistoryItem *newItem = m_presentHistory.Append();
newItem->m_timestamp = timestamp;
newItem->m_numFrames = 1;
}
}
if (m_presentHistory.Size() >= 2)
{
const size_t presentHistorySizeMinusOne = m_presentHistory.Size() - 1;
unsigned int numFrames = 0;
for (size_t i = 0; i < presentHistorySizeMinusOne; i++)
numFrames += m_presentHistory[i].m_numFrames;
LONGLONG timeFrame = m_presentHistory[presentHistorySizeMinusOne].m_timestamp.QuadPart - m_presentHistory[0].m_timestamp.QuadPart;
unsigned int cancelledFrames = 0;
LONGLONG cancelledTime = 0;
const int overshootTolerance = 2;
for (size_t i = 0; i < presentHistorySizeMinusOne; i++)
{
LONGLONG blockTimeframe = m_presentHistory[i + 1].m_timestamp.QuadPart - m_presentHistory[i].m_timestamp.QuadPart;
unsigned int blockNumFrames = m_presentHistory[i].m_numFrames;
if (blockTimeframe * static_cast<LONGLONG>(numFrames) >= timeFrame * static_cast<LONGLONG>(blockNumFrames) * overshootTolerance)
{
cancelledTime += blockTimeframe;
cancelledFrames += blockNumFrames;
}
}
numFrames -= cancelledFrames;
timeFrame -= cancelledTime;
// timeFrame / numFrames = Frame timestep
// Unless Frame timestep is within the frame lock range, a.k.a.
// timeFrame / numFrames / qpFreq >= minFrameTimeNum / minFrameTimeDenom
bool isInFrameTimeLock = false;
if (timeFrame * static_cast<LONGLONG>(m_properties.m_frameTimeLockMinDenominator) >= static_cast<LONGLONG>(numFrames) * static_cast<LONGLONG>(m_properties.m_frameTimeLockMinNumerator) * m_QPFrequency.QuadPart
&& timeFrame * static_cast<LONGLONG>(m_properties.m_frameTimeLockMaxDenominator) <= static_cast<LONGLONG>(numFrames) * static_cast<LONGLONG>(m_properties.m_frameTimeLockMaxNumerator) * m_QPFrequency.QuadPart)
{
isInFrameTimeLock = true;
}
LONGLONG frameTimeStep = m_frameTimeSliceSize;
if (!isInFrameTimeLock)
{
const int MAX_FRAMES_PER_STEP = 4;
frameTimeStep = timeFrame / numFrames;
if (frameTimeStep > m_frameTimeSliceSize * MAX_FRAMES_PER_STEP)
frameTimeStep = m_frameTimeSliceSize * MAX_FRAMES_PER_STEP;
}
m_frameTimeAccumulated += frameTimeStep;
while (m_frameTimeAccumulated >= m_frameTimeSliceSize)
{
m_properties.m_tickFunc(m_properties.m_tickFuncContext, m_vosFiber);
m_frameTimeAccumulated -= m_frameTimeSliceSize;
}
}
return true;
}
void GpDisplayDriverD3D11::Run()
{
HWND hWnd;
WNDCLASSEX wc;
LPVOID fiber = ConvertThreadToFiberEx(this, 0);
if (!fiber)
return; // ???
m_vosFiber = new GpFiber_Win32(fiber);
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WinProc;
wc.hInstance = g_gpWindowsGlobals.m_hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "GPD3D11WindowClass";
RegisterClassEx(&wc);
LONG windowStyle = WS_OVERLAPPEDWINDOW;
HMENU menus = NULL;
// TODO: Fix the resolution here
RECT wr = { 0, 0, m_windowWidth, m_windowHeight };
AdjustWindowRect(&wr, windowStyle, menus != NULL);
hWnd = CreateWindowExW(NULL, L"GPD3D11WindowClass", L"GlidePort", WS_OVERLAPPEDWINDOW, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, menus, g_gpWindowsGlobals.m_hInstance, NULL);
ShowWindow(hWnd, g_gpWindowsGlobals.m_nCmdShow);
StartD3DForWindow(hWnd, m_swapChain);
LARGE_INTEGER lastTimestamp;
memset(&lastTimestamp, 0, sizeof(lastTimestamp));
MSG msg;
for (;;)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
}
else
{
PresentFrameAndSync();
}
}
// Exit
ConvertFiberToThread();
}
void GpDisplayDriverD3D11::Shutdown()
{
delete this;
}
void GpDisplayDriverD3D11::GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *pixelFormat)
{
if (width)
*width = m_windowWidth;
if (height)
*height = m_windowHeight;
if (pixelFormat)
*pixelFormat = PortabilityLayer::PixelFormat_8BitStandard;
}
GpDisplayDriverD3D11 *GpDisplayDriverD3D11::Create(const GpDisplayDriverProperties &properties)
{
return new GpDisplayDriverD3D11(properties);
}
GpDisplayDriverD3D11::GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties)
: m_properties(properties)
, m_frameTimeAccumulated(0)
, m_windowWidth(640)
, m_windowHeight(480)
, m_vosFiber(nullptr)
{
memset(&m_syncTimeBase, 0, sizeof(m_syncTimeBase));
QueryPerformanceFrequency(&m_QPFrequency);
m_frameTimeSliceSize = m_QPFrequency.QuadPart * static_cast<LONGLONG>(properties.m_frameTimeLockNumerator) / static_cast<LONGLONG>(properties.m_frameTimeLockDenominator);
}

View File

@@ -1,50 +1,52 @@
#pragma once
#include "GpWindows.h"
#include "GpRingBuffer.h"
#include "IGpDisplayDriver.h"
#include "GpCoreDefs.h"
#include "GpDisplayDriverProperties.h"
struct IDXGISwapChain1;
class GpDisplayDriverD3D11 : public IGpDisplayDriver
{
public:
void Run() override;
void Shutdown() override;
void GetDisplayResolution(unsigned int &width, unsigned int &height) override;
static GpDisplayDriverD3D11 *Create(const GpDisplayDriverProperties &properties);
private:
GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties);
bool PresentFrameAndSync();
IDXGISwapChain1 *m_SwapChain;
struct CompactedPresentHistoryItem
{
LARGE_INTEGER m_Timestamp;
unsigned int m_NumFrames;
};
GpRingBuffer<CompactedPresentHistoryItem, 60> m_PresentHistory;
GpDisplayDriverProperties m_Properties;
LARGE_INTEGER m_SyncTimeBase;
LARGE_INTEGER m_QPFrequency;
UINT m_ExpectedSyncDelta;
bool m_IsResettingSwapChain;
LONGLONG m_FrameTimeAccumulated;
LONGLONG m_FrameTimeSliceSize;
DWORD m_windowWidth;
DWORD m_windowHeight;
GpFiber *m_vosFiber;
};
#pragma once
#include "GpWindows.h"
#include "GpRingBuffer.h"
#include "IGpDisplayDriver.h"
#include "GpCoreDefs.h"
#include "GpDisplayDriverProperties.h"
#include "PixelFormat.h"
struct IDXGISwapChain1;
class GpDisplayDriverD3D11 : public IGpDisplayDriver
{
public:
void Run() override;
void Shutdown() override;
void GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp) override;
static GpDisplayDriverD3D11 *Create(const GpDisplayDriverProperties &properties);
private:
GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties);
bool PresentFrameAndSync();
IDXGISwapChain1 *m_swapChain;
struct CompactedPresentHistoryItem
{
LARGE_INTEGER m_timestamp;
unsigned int m_numFrames;
};
GpRingBuffer<CompactedPresentHistoryItem, 60> m_presentHistory;
GpDisplayDriverProperties m_properties;
LARGE_INTEGER m_syncTimeBase;
LARGE_INTEGER m_QPFrequency;
UINT m_expectedSyncDelta;
bool m_isResettingSwapChain;
LONGLONG m_frameTimeAccumulated;
LONGLONG m_frameTimeSliceSize;
DWORD m_windowWidth;
DWORD m_windowHeight;
GpFiber *m_vosFiber;
};

View File

@@ -5,10 +5,10 @@
IGpDisplayDriver *GpDisplayDriverFactory::CreateDisplayDriver(const GpDisplayDriverProperties &properties)
{
assert(properties.m_Type < EGpDisplayDriverType_Count);
assert(properties.m_type < EGpDisplayDriverType_Count);
if (ms_Registry[properties.m_Type])
return ms_Registry[properties.m_Type](properties);
if (ms_Registry[properties.m_type])
return ms_Registry[properties.m_type](properties);
else
return nullptr;
}

View File

@@ -1,26 +0,0 @@
#pragma once
#include "EGpDisplayDriverType.h"
class IGpDisplayDriver;
class GpFiber;
struct GpDisplayDriverProperties
{
typedef void(*TickFunc_t)(void *context, GpFiber *vosFiber);
EGpDisplayDriverType m_Type;
unsigned int m_FrameTimeLockNumerator;
unsigned int m_FrameTimeLockDenominator;
unsigned int m_FrameTimeLockMinNumerator;
unsigned int m_FrameTimeLockMinDenominator;
unsigned int m_FrameTimeLockMaxNumerator;
unsigned int m_FrameTimeLockMaxDenominator;
// Tick function and context to call when a frame needs to be served.
TickFunc_t m_TickFunc;
void *m_TickFuncContext;
};

View File

@@ -1,21 +0,0 @@
#pragma once
#include "GpCoreDefs.h"
class GpEvent final
{
public:
void Wait();
void WaitMSec(unsigned int msec);
void Signal();
void Reset();
void Destroy();
static GpEvent *Create(bool autoReset, bool startSignalled);
private:
explicit GpEvent(void *privateData);
~GpEvent();
void *m_PrivateData;
};

View File

@@ -1,49 +0,0 @@
#include "GpEvent.h"
#include "GpWindows.h"
#include <assert.h>
GpEvent::~GpEvent()
{
CloseHandle(static_cast<HANDLE>(m_PrivateData));
}
void GpEvent::Wait()
{
WaitForSingleObject(static_cast<HANDLE>(m_PrivateData), INFINITE);
}
void GpEvent::WaitMSec(unsigned int msec)
{
assert(msec < MAXDWORD);
WaitForSingleObject(static_cast<HANDLE>(m_PrivateData), static_cast<DWORD>(msec));
}
void GpEvent::Signal()
{
SetEvent(static_cast<HANDLE>(m_PrivateData));
}
void GpEvent::Reset()
{
ResetEvent(static_cast<HANDLE>(m_PrivateData));
}
void GpEvent::Destroy()
{
delete this;
}
GpEvent *GpEvent::Create(bool autoReset, bool startSignalled)
{
HANDLE handle = CreateEventA(nullptr, autoReset ? FALSE : TRUE, startSignalled ? TRUE : FALSE, nullptr);
if (!handle)
return nullptr;
return new GpEvent(handle);
}
GpEvent::GpEvent(void *privateData)
: m_PrivateData(privateData)
{
}

View File

@@ -1,48 +1,64 @@
#include "GpMain.h"
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverProperties.h"
#include "GpGlobalConfig.h"
#include "GpAppEnvironment.h"
#include "IGpDisplayDriver.h"
#include <string.h>
namespace
{
void TickAppEnvironment(void *context, GpFiber *vosFiber)
{
static_cast<GpAppEnvironment*>(context)->Tick(vosFiber);
}
}
int GpMain::Run()
{
GpAppEnvironment *appEnvironment = new GpAppEnvironment();
GpDisplayDriverProperties ddProps;
memset(&ddProps, 0, sizeof(ddProps));
ddProps.m_FrameTimeLockNumerator = 1;
ddProps.m_FrameTimeLockDenominator = 60;
// +/- 1% tolerance for frame time variance
ddProps.m_FrameTimeLockMinNumerator = 99;
ddProps.m_FrameTimeLockMinDenominator = 6000;
ddProps.m_FrameTimeLockMaxNumerator = 101;
ddProps.m_FrameTimeLockMaxDenominator = 6000;
ddProps.m_TickFunc = TickAppEnvironment;
ddProps.m_TickFuncContext = appEnvironment;
ddProps.m_Type = g_gpGlobalConfig.m_displayDriverType;
IGpDisplayDriver *displayDriver = GpDisplayDriverFactory::CreateDisplayDriver(ddProps);
appEnvironment->Init();
appEnvironment->SetDisplayDriver(displayDriver);
// Start the display loop
displayDriver->Run();
return 0;
}
#include "GpMain.h"
#include "GpAudioDriverFactory.h"
#include "GpAudioDriverProperties.h"
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverProperties.h"
#include "GpGlobalConfig.h"
#include "GpAppEnvironment.h"
#include "IGpAudioDriver.h"
#include "IGpDisplayDriver.h"
#include <string.h>
namespace
{
void TickAppEnvironment(void *context, GpFiber *vosFiber)
{
static_cast<GpAppEnvironment*>(context)->Tick(vosFiber);
}
}
int GpMain::Run()
{
GpAppEnvironment *appEnvironment = new GpAppEnvironment();
GpDisplayDriverProperties ddProps;
memset(&ddProps, 0, sizeof(ddProps));
ddProps.m_type = EGpDisplayDriverType_D3D11;
ddProps.m_frameTimeLockNumerator = 1;
ddProps.m_frameTimeLockDenominator = 60;
// +/- 1% tolerance for frame time variance
ddProps.m_frameTimeLockMinNumerator = 99;
ddProps.m_frameTimeLockMinDenominator = 6000;
ddProps.m_frameTimeLockMaxNumerator = 101;
ddProps.m_frameTimeLockMaxDenominator = 6000;
ddProps.m_tickFunc = TickAppEnvironment;
ddProps.m_tickFuncContext = appEnvironment;
ddProps.m_type = g_gpGlobalConfig.m_displayDriverType;
GpAudioDriverProperties adProps;
memset(&adProps, 0, sizeof(adProps));
// The sample rate used in all of Glider PRO's sound is 0x56ee8ba3
// This appears to be the "standard" Mac sample rate, probably rounded from 244800/11.
adProps.m_type = EGpAudioDriverType_XAudio2;
adProps.m_sampleRate = (244800 * 2 + 11) / (11 * 2);
adProps.m_debug = true;
IGpDisplayDriver *displayDriver = GpDisplayDriverFactory::CreateDisplayDriver(ddProps);
IGpAudioDriver *audioDriver = GpAudioDriverFactory::CreateAudioDriver(adProps);
appEnvironment->Init();
appEnvironment->SetDisplayDriver(displayDriver);
appEnvironment->SetAudioDriver(audioDriver);
// Start the display loop
displayDriver->Run();
return 0;
}

View File

@@ -1,33 +1,36 @@
#include "GpWindows.h"
#include "GpMain.h"
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverFactoryD3D11.h"
#include "GpGlobalConfig.h"
#include "GpFileSystem_Win32.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Win32.h"
#include "HostFileSystem.h"
#include <d3d11.h>
#include <stdio.h>
GPWindowsGlobals g_gpWindowsGlobals;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Win32::GetInstance());
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Win32::GetInstance());
g_gpWindowsGlobals.m_hInstance = hInstance;
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
g_gpWindowsGlobals.m_cmdLine = lpCmdLine;
g_gpWindowsGlobals.m_nCmdShow = nCmdShow;
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDisplayDriverFactoryD3D11::Create);
return GpMain::Run();
}
#include "GpMain.h"
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverFactoryD3D11.h"
#include "GpGlobalConfig.h"
#include "GpFileSystem_Win32.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Win32.h"
#include "HostFileSystem.h"
#include "GpWindows.h"
#include <stdio.h>
GPWindowsGlobals g_gpWindowsGlobals;
extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Win32::GetInstance());
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Win32::GetInstance());
g_gpWindowsGlobals.m_hInstance = hInstance;
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
g_gpWindowsGlobals.m_cmdLine = lpCmdLine;
g_gpWindowsGlobals.m_nCmdShow = nCmdShow;
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDisplayDriverFactoryD3D11::Create);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);
return GpMain::Run();
}

42
GpD3D/GpMutex_Win32.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include "GpMutex_Win32.h"
#include "GpWindows.h"
#include <stdlib.h>
#include <new>
void GpMutex_Win32::Destroy()
{
this->~GpMutex_Win32();
free(this);
}
void GpMutex_Win32::Lock()
{
EnterCriticalSection(&m_critSection);
}
void GpMutex_Win32::Unlock()
{
LeaveCriticalSection(&m_critSection);
}
GpMutex_Win32 *GpMutex_Win32::Create()
{
void *storage = malloc(sizeof(GpMutex_Win32));
if (!storage)
return nullptr;
return new (storage) GpMutex_Win32();
}
GpMutex_Win32::GpMutex_Win32()
{
InitializeCriticalSection(&m_critSection);
}
GpMutex_Win32::~GpMutex_Win32()
{
DeleteCriticalSection(&m_critSection);
}

21
GpD3D/GpMutex_Win32.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#include "HostMutex.h"
#include "GpWindows.h"
class GpMutex_Win32 final : public PortabilityLayer::HostMutex
{
public:
void Destroy() override;
void Lock() override;
void Unlock() override;
static GpMutex_Win32 *Create();
private:
const GpMutex_Win32();
~GpMutex_Win32();
CRITICAL_SECTION m_critSection;
};

View File

@@ -0,0 +1,49 @@
#include "GpPLGlueAudioChannel.h"
#include "ClientAudioChannelContext.h"
#include "IGpAudioChannel.h"
#include <stdlib.h>
#include <new>
void GpPLGlueAudioChannel::SetClientAudioChannelContext(PortabilityLayer::ClientAudioChannelContext *context)
{
m_clientContext = context;
m_audioChannel->SetAudioChannelContext(this);
}
void GpPLGlueAudioChannel::PostBuffer(const void *buffer, size_t bufferSize)
{
m_audioChannel->PostBuffer(buffer, bufferSize);
}
void GpPLGlueAudioChannel::Destroy()
{
this->~GpPLGlueAudioChannel();
free(this);
}
void GpPLGlueAudioChannel::NotifyBufferFinished()
{
if (m_clientContext)
m_clientContext->NotifyBufferFinished();
}
GpPLGlueAudioChannel *GpPLGlueAudioChannel::Create(IGpAudioChannel *audioChannel)
{
void *storage = malloc(sizeof(GpPLGlueAudioChannel));
if (!storage)
return nullptr;
return new (storage) GpPLGlueAudioChannel(audioChannel);
}
GpPLGlueAudioChannel::GpPLGlueAudioChannel(IGpAudioChannel *audioChannel)
: m_audioChannel(audioChannel)
, m_clientContext(nullptr)
{
}
GpPLGlueAudioChannel::~GpPLGlueAudioChannel()
{
m_audioChannel->Destroy();
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include "HostAudioChannel.h"
#include "IGpAudioChannelCallbacks.h"
struct IGpAudioChannel;
class GpPLGlueAudioChannel final : public PortabilityLayer::HostAudioChannel, public IGpAudioChannelCallbacks
{
public:
void SetClientAudioChannelContext(PortabilityLayer::ClientAudioChannelContext *context) override;
void PostBuffer(const void *buffer, size_t bufferSize) override;
void Destroy() override;
void NotifyBufferFinished() override;
static GpPLGlueAudioChannel *Create(IGpAudioChannel *audioChannel);
private:
explicit GpPLGlueAudioChannel(IGpAudioChannel *audioChannel);
~GpPLGlueAudioChannel();
PortabilityLayer::ClientAudioChannelContext *m_clientContext;
IGpAudioChannel *m_audioChannel;
};

View File

@@ -0,0 +1,38 @@
#include "GpPLGlueAudioDriver.h"
#include "GpPLGlueAudioChannel.h"
#include "IGpAudioChannel.h"
#include "IGpAudioDriver.h"
GpPLGlueAudioDriver::GpPLGlueAudioDriver()
: m_audioDriver(nullptr)
{
}
PortabilityLayer::HostAudioChannel *GpPLGlueAudioDriver::CreateChannel()
{
IGpAudioChannel *channel = m_audioDriver->CreateChannel();
if (!channel)
return nullptr;
PortabilityLayer::HostAudioChannel *glueChannel = GpPLGlueAudioChannel::Create(channel);
if (!glueChannel)
{
channel->Destroy();
return nullptr;
}
return glueChannel;
}
GpPLGlueAudioDriver *GpPLGlueAudioDriver::GetInstance()
{
return &ms_instance;
}
void GpPLGlueAudioDriver::SetGpAudioDriver(IGpAudioDriver *audioDriver)
{
m_audioDriver = audioDriver;
}
GpPLGlueAudioDriver GpPLGlueAudioDriver::ms_instance;

View File

@@ -0,0 +1,22 @@
#pragma once
#include "HostAudioDriver.h"
class IGpAudioDriver;
class GpPLGlueAudioDriver final : public PortabilityLayer::HostAudioDriver
{
public:
GpPLGlueAudioDriver();
PortabilityLayer::HostAudioChannel *CreateChannel() override;
void SetGpAudioDriver(IGpAudioDriver *audioDriver);
static GpPLGlueAudioDriver *GetInstance();
private:
IGpAudioDriver *m_audioDriver;
static GpPLGlueAudioDriver ms_instance;
};

View File

@@ -6,9 +6,9 @@ GpPLGlueDisplayDriver::GpPLGlueDisplayDriver()
{
}
void GpPLGlueDisplayDriver::GetDisplayResolution(unsigned int &width, unsigned int &height)
void GpPLGlueDisplayDriver::GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp)
{
m_displayDriver->GetDisplayResolution(width, height);
m_displayDriver->GetDisplayResolution(width, height, bpp);
}
void GpPLGlueDisplayDriver::HideCursor()

View File

@@ -9,7 +9,7 @@ class GpPLGlueDisplayDriver final : public PortabilityLayer::HostDisplayDriver
public:
GpPLGlueDisplayDriver();
void GetDisplayResolution(unsigned int &width, unsigned int &height) override;
void GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp) override;
void HideCursor() override;
void SetGpDisplayDriver(IGpDisplayDriver *displayDriver);

View File

@@ -1,19 +1,40 @@
#include "GpSystemServices_Win32.h"
#include "GpSystemServices_Win32.h"
#include "GpMutex_Win32.h"
#include "GpThreadEvent_Win32.h"
#include <assert.h>
#pragma push_macro("CreateMutex")
#ifdef CreateMutex
#undef CreateMutex
#endif
GpSystemServices_Win32::GpSystemServices_Win32()
{
}
uint32_t GpSystemServices_Win32::GetTime() const
{
// PL_NotYetImplemented
return 0;
}
PortabilityLayer::HostMutex *GpSystemServices_Win32::CreateMutex()
{
return GpMutex_Win32::Create();
}
#include <assert.h>
GpSystemServices_Win32::GpSystemServices_Win32()
{
}
uint32_t GpSystemServices_Win32::GetTime() const
{
return 0;
}
GpSystemServices_Win32 *GpSystemServices_Win32::GetInstance()
{
return &ms_instance;
}
GpSystemServices_Win32 GpSystemServices_Win32::ms_instance;
PortabilityLayer::HostThreadEvent *GpSystemServices_Win32::CreateThreadEvent(bool autoReset, bool startSignaled)
{
return GpThreadEvent_Win32::Create(autoReset, startSignaled);
}
GpSystemServices_Win32 *GpSystemServices_Win32::GetInstance()
{
return &ms_instance;
}
GpSystemServices_Win32 GpSystemServices_Win32::ms_instance;
#pragma pop_macro("CreateMutex")

View File

@@ -1,19 +1,28 @@
#pragma once
#include "HostSystemServices.h"
#include "GpCoreDefs.h"
#include "GpWindows.h"
class GpSystemServices_Win32 final : public PortabilityLayer::HostSystemServices
{
public:
GpSystemServices_Win32();
uint32_t GetTime() const override;
static GpSystemServices_Win32 *GetInstance();
private:
static GpSystemServices_Win32 ms_instance;
};
#pragma once
#include "HostSystemServices.h"
#include "GpCoreDefs.h"
#include "GpWindows.h"
#pragma push_macro("CreateMutex")
#ifdef CreateMutex
#undef CreateMutex
#endif
class GpSystemServices_Win32 final : public PortabilityLayer::HostSystemServices
{
public:
GpSystemServices_Win32();
uint32_t GetTime() const override;
PortabilityLayer::HostMutex *CreateMutex() override;
PortabilityLayer::HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
static GpSystemServices_Win32 *GetInstance();
private:
static GpSystemServices_Win32 ms_instance;
};
#pragma pop_macro("CreateMutex")

View File

@@ -0,0 +1,51 @@
#include "GpThreadEvent_Win32.h"
#include <stdlib.h>
#include <new>
void GpThreadEvent_Win32::Wait()
{
WaitForSingleObject(m_event, INFINITE);
}
void GpThreadEvent_Win32::WaitTimed(uint32_t msec)
{
WaitForSingleObject(m_event, static_cast<DWORD>(msec));
}
void GpThreadEvent_Win32::Signal()
{
SetEvent(m_event);
}
void GpThreadEvent_Win32::Destroy()
{
this->~GpThreadEvent_Win32();
free(this);
}
GpThreadEvent_Win32 *GpThreadEvent_Win32::Create(bool autoReset, bool startSignaled)
{
HANDLE handle = CreateEventA(nullptr, autoReset ? FALSE : TRUE, startSignaled ? TRUE : FALSE, nullptr);
if (handle == nullptr)
return nullptr;
void *storage = malloc(sizeof(GpThreadEvent_Win32));
if (!storage)
{
CloseHandle(handle);
return nullptr;
}
return new (storage) GpThreadEvent_Win32(handle);
}
GpThreadEvent_Win32::GpThreadEvent_Win32(const HANDLE &handle)
: m_event(handle)
{
}
GpThreadEvent_Win32::~GpThreadEvent_Win32()
{
CloseHandle(m_event);
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include "HostThreadEvent.h"
#include "GpWindows.h"
class GpThreadEvent_Win32 final : public PortabilityLayer::HostThreadEvent
{
public:
void Wait() override;
void WaitTimed(uint32_t msec) override;
void Signal() override;
void Destroy() override;
static GpThreadEvent_Win32 *Create(bool autoReset, bool startSignaled);
private:
explicit GpThreadEvent_Win32(const HANDLE &handle);
~GpThreadEvent_Win32();
HANDLE m_event;
};

12
GpMainApp.props Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>GP_APP_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

1318
PictChecker/PictChecker.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}</ProjectGuid>
<RootNamespace>PictChecker</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Common.props" />
<Import Project="..\PortabilityLayer.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Common.props" />
<Import Project="..\PortabilityLayer.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Common.props" />
<Import Project="..\PortabilityLayer.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Common.props" />
<Import Project="..\PortabilityLayer.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="PictChecker.cpp" />
<ClCompile Include="stb_image_write.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PortabilityLayer\PortabilityLayer.vcxproj">
<Project>{6ec62b0f-9353-40a4-a510-3788f1368b33}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stb_image_write.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="PictChecker.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stb_image_write.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stb_image_write.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,2 @@
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

File diff suppressed because it is too large Load Diff

View File

@@ -101,7 +101,7 @@ namespace PortabilityLayer
return 0;
long oldPos = ftell(m_file);
fseek(m_file, SEEK_END, 0);
fseek(m_file, 0, SEEK_END);
const UFilePos_t endPos = static_cast<UFilePos_t>(ftell(m_file));
fseek(m_file, oldPos, SEEK_SET);

View File

@@ -0,0 +1,12 @@
#pragma once
#include <stdint.h>
namespace PortabilityLayer
{
class ClientAudioChannelContext
{
public:
virtual void NotifyBufferFinished() = 0;
};
}

View File

@@ -1,7 +1,7 @@
#include "DisplayDeviceManager.h"
#include "HostDisplayDriver.h"
#include "PLQuickdraw.h"
#include "MemoryManager.h"
namespace PortabilityLayer
@@ -37,7 +37,9 @@ namespace PortabilityLayer
void DisplayDeviceManagerImpl::Init()
{
m_mainDevice = MemoryManager::GetInstance()->NewHandle<GDevice>();
m_mainDevice = MemoryManager::GetInstance()->NewHandle<GDevice>();
HostDisplayDriver::GetInstance()->GetDisplayResolution(nullptr, nullptr, &(*m_mainDevice)->pixelFormat);
}
void DisplayDeviceManagerImpl::Shutdown()

View File

@@ -1,42 +1,44 @@
#pragma once
#ifndef __GPAPP_INTERFACE_H__
#define __GPAPP_INTERFACE_H__
#include "HostSuspendHook.h"
#include <stdint.h>
#ifdef GP_APP_DLL
#ifdef GP_APP_DLL_EXPORT
#define GP_APP_DLL_EXPORT_API extern "C" __declspec(dllexport)
#else
#define GP_APP_DLL_EXPORT_API extern "C" __declspec(dllimport)
#endif
#else
#define GP_APP_DLL_EXPORT_API extern "C"
#endif
namespace PortabilityLayer
{
class HostFileSystem;
class HostDisplayDriver;
class HostSystemServices;
}
class GpAppInterface
{
public:
virtual int ApplicationMain() = 0;
virtual void PL_IncrementTickCounter(uint32_t count) = 0;
virtual void PL_HostFileSystem_SetInstance(PortabilityLayer::HostFileSystem *instance) = 0;
virtual void PL_HostDisplayDriver_SetInstance(PortabilityLayer::HostDisplayDriver *instance) = 0;
virtual void PL_HostSystemServices_SetInstance(PortabilityLayer::HostSystemServices *instance) = 0;
virtual void PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context) = 0;
};
GP_APP_DLL_EXPORT_API GpAppInterface *GpAppInterface_Get();
#endif
#pragma once
#ifndef __GPAPP_INTERFACE_H__
#define __GPAPP_INTERFACE_H__
#include "HostSuspendHook.h"
#include <stdint.h>
#ifdef GP_APP_DLL
#ifdef GP_APP_DLL_EXPORT
#define GP_APP_DLL_EXPORT_API extern "C" __declspec(dllexport)
#else
#define GP_APP_DLL_EXPORT_API extern "C" __declspec(dllimport)
#endif
#else
#define GP_APP_DLL_EXPORT_API extern "C"
#endif
namespace PortabilityLayer
{
class HostAudioDriver;
class HostFileSystem;
class HostDisplayDriver;
class HostSystemServices;
}
class GpAppInterface
{
public:
virtual int ApplicationMain() = 0;
virtual void PL_IncrementTickCounter(uint32_t count) = 0;
virtual void PL_HostFileSystem_SetInstance(PortabilityLayer::HostFileSystem *instance) = 0;
virtual void PL_HostDisplayDriver_SetInstance(PortabilityLayer::HostDisplayDriver *instance) = 0;
virtual void PL_HostSystemServices_SetInstance(PortabilityLayer::HostSystemServices *instance) = 0;
virtual void PL_HostAudioDriver_SetInstance(PortabilityLayer::HostAudioDriver *instance) = 0;
virtual void PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context) = 0;
};
GP_APP_DLL_EXPORT_API GpAppInterface *GpAppInterface_Get();
#endif

View File

@@ -0,0 +1,14 @@
#pragma once
namespace PortabilityLayer
{
class ClientAudioChannelContext;
class HostAudioChannel
{
public:
virtual void SetClientAudioChannelContext(ClientAudioChannelContext *context) = 0;
virtual void PostBuffer(const void *buffer, size_t bufferSize) = 0;
virtual void Destroy() = 0;
};
}

View File

@@ -0,0 +1,16 @@
#include "HostAudioDriver.h"
namespace PortabilityLayer
{
HostAudioDriver *HostAudioDriver::GetInstance()
{
return ms_instance;
}
void HostAudioDriver::SetInstance(HostAudioDriver *instance)
{
ms_instance = instance;
}
HostAudioDriver *HostAudioDriver::ms_instance;
}

View File

@@ -0,0 +1,18 @@
#pragma once
namespace PortabilityLayer
{
class HostAudioChannel;
class HostAudioDriver
{
public:
virtual HostAudioChannel *CreateChannel() = 0;
static HostAudioDriver *GetInstance();
static void SetInstance(HostAudioDriver *instance);
private:
static HostAudioDriver *ms_instance;
};
}

View File

@@ -1,21 +1,23 @@
#pragma once
#ifndef __PL_HOST_DISPLAY_DRIVER_H__
#define __PL_HOST_DISPLAY_DRIVER_H__
namespace PortabilityLayer
{
class HostDisplayDriver
{
public:
virtual void GetDisplayResolution(unsigned int &width, unsigned int &height) = 0;
virtual void HideCursor() = 0;
static void SetInstance(HostDisplayDriver *instance);
static HostDisplayDriver *GetInstance();
private:
static HostDisplayDriver *ms_instance;
};
}
#endif
#pragma once
#ifndef __PL_HOST_DISPLAY_DRIVER_H__
#define __PL_HOST_DISPLAY_DRIVER_H__
#include "PixelFormat.h"
namespace PortabilityLayer
{
class HostDisplayDriver
{
public:
virtual void GetDisplayResolution(unsigned int *width, unsigned int *height, PixelFormat *pixelFormat) = 0;
virtual void HideCursor() = 0;
static void SetInstance(HostDisplayDriver *instance);
static HostDisplayDriver *GetInstance();
private:
static HostDisplayDriver *ms_instance;
};
}
#endif

View File

@@ -0,0 +1,13 @@
#pragma once
namespace PortabilityLayer
{
class HostMutex
{
public:
virtual void Destroy() = 0;
virtual void Lock() = 0;
virtual void Unlock() = 0;
};
}

View File

@@ -2,14 +2,23 @@
#ifndef __PL_HOST_SYSTEM_SERVICES_H__
#define __PL_HOST_SYSTEM_SERVICES_H__
#include <stdint.h>
#include <stdint.h>
#ifdef CreateMutex
#error "CreateMutex was macrod"
#endif
namespace PortabilityLayer
{
{
class HostMutex;
class HostThreadEvent;
class HostSystemServices
{
public:
virtual uint32_t GetTime() const = 0;
virtual uint32_t GetTime() const = 0;
virtual HostMutex *CreateMutex() = 0;
virtual HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) = 0;
static void SetInstance(HostSystemServices *instance);
static HostSystemServices *GetInstance();

View File

@@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
namespace PortabilityLayer
{
class HostThreadEvent
{
public:
virtual void Wait() = 0;
virtual void WaitTimed(uint32_t msec) = 0;
virtual void Signal() = 0;
virtual void Destroy() = 0;
};
}

View File

@@ -5,6 +5,8 @@
#include <stdlib.h>
#include <new>
#include <assert.h>
#include <string.h>
namespace PortabilityLayer
{
@@ -13,16 +15,19 @@ namespace PortabilityLayer
public:
void Init() override;
void Shutdown() override;
void *Alloc(size_t size) override;
void Release(void *buf) override;
void *Alloc(size_t size) override;
void *Realloc(void *buf, size_t newSize) override;
void Release(void *buf) override;
MMHandleBlock *AllocHandle(size_t size) override;
bool ResizeHandle(MMHandleBlock *hdl, size_t newSize) override;
void ReleaseHandle(MMHandleBlock *hdl) override;
static MemoryManagerImpl *GetInstance();
private:
static MemoryManagerImpl ms_instance;
};
@@ -32,6 +37,41 @@ namespace PortabilityLayer
void MemoryManagerImpl::Shutdown()
{
}
void *MemoryManagerImpl::Realloc(void *buf, size_t newSize)
{
assert(buf != nullptr);
const size_t mmBlockSize = MMBlock::AlignedSize();
uint8_t *oldBufBytes = static_cast<uint8_t*>(buf);
const MMBlock *oldBufMMBlock = reinterpret_cast<const MMBlock*>(oldBufBytes - MMBlock::AlignedSize());
const size_t oldBufOffsetFromAlignLoc = oldBufMMBlock->m_offsetFromAllocLocation;
uint8_t *oldBufBase = oldBufBytes - MMBlock::AlignedSize() - oldBufOffsetFromAlignLoc;
const size_t mmBlockSizeWithMaxPadding = MMBlock::AlignedSize() + PL_SYSTEM_MEMORY_ALIGNMENT - 1;
if (SIZE_MAX - newSize < mmBlockSizeWithMaxPadding)
return nullptr;
const size_t newBufferSize = newSize + mmBlockSizeWithMaxPadding;
uint8_t *newBuffer = static_cast<uint8_t*>(realloc(oldBufBase, newSize + mmBlockSizeWithMaxPadding));
if (!newBuffer)
return nullptr;
const intptr_t offsetFromAlignPoint = reinterpret_cast<intptr_t>(newBuffer) & static_cast<intptr_t>(PL_SYSTEM_MEMORY_ALIGNMENT - 1);
intptr_t alignPadding = 0;
if (offsetFromAlignPoint != 0)
alignPadding = static_cast<intptr_t>(PL_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint;
// Check if the alignment changed, if so relocate
if (static_cast<size_t>(alignPadding) != oldBufOffsetFromAlignLoc)
memmove(newBuffer + alignPadding, newBuffer + oldBufOffsetFromAlignLoc, MMBlock::AlignedSize() + newSize);
MMBlock *newMMBlock = reinterpret_cast<MMBlock*>(newBuffer + alignPadding);
newMMBlock->m_offsetFromAllocLocation = static_cast<SmallestUInt<PL_SYSTEM_MEMORY_ALIGNMENT>::ValueType_t>(alignPadding);
return newBuffer + alignPadding + MMBlock::AlignedSize();
}
void *MemoryManagerImpl::Alloc(size_t size)
@@ -77,6 +117,24 @@ namespace PortabilityLayer
MMHandleBlock *handleBlock = static_cast<MMHandleBlock*>(Alloc(sizeof(MMHandleBlock)));
return new (handleBlock) MMHandleBlock(contents, size);
}
bool MemoryManagerImpl::ResizeHandle(MMHandleBlock *hdl, size_t newSize)
{
if (hdl->m_contents == nullptr)
return false;
if (newSize != hdl->m_size)
{
void *newBuf = Realloc(hdl->m_contents, newSize);
if (!newBuf)
return false;
hdl->m_contents = newBuf;
hdl->m_size = newSize;
}
return true;
}
void MemoryManagerImpl::ReleaseHandle(MMHandleBlock *hdl)
@@ -84,8 +142,10 @@ namespace PortabilityLayer
if (!hdl)
return;
if (hdl->m_rmSelfRef != nullptr)
hdl->m_rmSelfRef->m_handle = nullptr;
assert(hdl->m_rmSelfRef == nullptr);
if (hdl->m_contents)
Release(hdl->m_contents);
hdl->~MMHandleBlock();

View File

@@ -1,51 +1,53 @@
#pragma once
#ifndef __PL_MEMORY_MANAGER_H__
#define __PL_MEMORY_MANAGER_H__
#include <stdint.h>
namespace PortabilityLayer
{
struct MMHandleBlock;
class MemoryManager
{
public:
virtual void Init() = 0;
virtual void Shutdown() = 0;
virtual void *Alloc(size_t size) = 0;
virtual void Release(void *buf) = 0;
virtual MMHandleBlock *AllocHandle(size_t size) = 0;
virtual void ReleaseHandle(MMHandleBlock *hdl) = 0;
template<class T>
T **NewHandle();
static MemoryManager *GetInstance();
};
}
#include <new>
#include "CoreDefs.h"
#include "MMHandleBlock.h"
namespace PortabilityLayer
{
template<class T>
T **MemoryManager::NewHandle()
{
MMHandleBlock *hdl = this->AllocHandle(sizeof(T));
if (!hdl)
return nullptr;
T **objectHdl = reinterpret_cast<T**>(hdl);
T *objectPtr = *objectHdl;
new (objectPtr) T();
return objectHdl;
}
}
#endif
#pragma once
#ifndef __PL_MEMORY_MANAGER_H__
#define __PL_MEMORY_MANAGER_H__
#include <stdint.h>
namespace PortabilityLayer
{
struct MMHandleBlock;
class MemoryManager
{
public:
virtual void Init() = 0;
virtual void Shutdown() = 0;
virtual void *Alloc(size_t size) = 0;
virtual void Release(void *buf) = 0;
virtual void *Realloc(void *buf, size_t newSize) = 0;
virtual MMHandleBlock *AllocHandle(size_t size) = 0;
virtual bool ResizeHandle(MMHandleBlock *hdl, size_t newSize) = 0;
virtual void ReleaseHandle(MMHandleBlock *hdl) = 0;
template<class T>
T **NewHandle();
static MemoryManager *GetInstance();
};
}
#include <new>
#include "CoreDefs.h"
#include "MMHandleBlock.h"
namespace PortabilityLayer
{
template<class T>
T **MemoryManager::NewHandle()
{
MMHandleBlock *hdl = this->AllocHandle(sizeof(T));
if (!hdl)
return nullptr;
T **objectHdl = reinterpret_cast<T**>(hdl);
T *objectPtr = *objectHdl;
new (objectPtr) T();
return objectHdl;
}
}
#endif

View File

@@ -37,7 +37,7 @@ public:
BEInteger<T> operator++(int);
private:
T m_beValue;
uint8_t m_beValueBytes[sizeof(T)];
};
template<class T>
@@ -83,30 +83,32 @@ struct BEInteger_SwapHelper<uint32_t>
}
};
// Int16
#include <string.h>
template<class T>
inline BEInteger<T>::BEInteger()
: m_beValue(0)
{
memset(m_beValueBytes, 0, sizeof(T));
}
template<class T>
inline BEInteger<T>::BEInteger(const BEInteger<T> &other)
: m_beValue(other.m_beValue)
{
memcpy(m_beValueBytes, other.m_beValueBytes, sizeof(T));
}
template<class T>
inline BEInteger<T>::BEInteger(T i)
: m_beValue(i)
{
BEInteger_SwapHelper<T>::Swap(m_beValue);
BEInteger_SwapHelper<T>::Swap(i);
memcpy(m_beValueBytes, &i, sizeof(T));
}
template<class T>
inline BEInteger<T>::operator T() const
{
int16_t result = m_beValue;
T result;
memcpy(&result, m_beValueBytes, sizeof(T));
BEInteger_SwapHelper<T>::Swap(result);
return result;
}
@@ -115,7 +117,7 @@ template<class T>
inline BEInteger<T> &BEInteger<T>::operator=(T value)
{
BEInteger_SwapHelper<T>::Swap(value);
m_beValue = value;
memcpy(m_beValueBytes, &value, sizeof(T));
return *this;
}
@@ -123,9 +125,14 @@ template<class T>
template<class TOther>
BEInteger<T> &BEInteger<T>::operator+=(TOther value)
{
BEInteger_SwapHelper<T>::Swap(m_beValue);
m_beValue += value;
BEInteger_SwapHelper<T>::Swap(m_beValue);
T storedValue;
memcpy(&storedValue, m_beValueBytes, sizeof(T));
BEInteger_SwapHelper<T>::Swap(storedValue);
storedValue += value;
BEInteger_SwapHelper<T>::Swap(storedValue);
memcpy(m_beValueBytes, &storedValue, sizeof(T));
return *this;
}
@@ -133,9 +140,14 @@ template<class T>
template<class TOther>
BEInteger<T> &BEInteger<T>::operator-=(TOther value)
{
BEInteger_SwapHelper<T>::Swap(m_beValue);
m_beValue -= value;
BEInteger_SwapHelper<T>::Swap(m_beValue);
T storedValue;
memcpy(&storedValue, m_beValueBytes, sizeof(T));
BEInteger_SwapHelper<T>::Swap(storedValue);
storedValue -= value;
BEInteger_SwapHelper<T>::Swap(storedValue);
memcpy(m_beValueBytes, &storedValue, sizeof(T));
return *this;
}
@@ -143,9 +155,14 @@ template<class T>
template<class TOther>
BEInteger<T> &BEInteger<T>::operator*=(TOther value)
{
BEInteger_SwapHelper<T>::Swap(m_beValue);
m_beValue *= value;
BEInteger_SwapHelper<T>::Swap(m_beValue);
T storedValue;
memcpy(&storedValue, m_beValueBytes, sizeof(T));
BEInteger_SwapHelper<T>::Swap(storedValue);
storedValue *= value;
BEInteger_SwapHelper<T>::Swap(storedValue);
memcpy(m_beValueBytes, &storedValue, sizeof(T));
return *this;
}
@@ -153,9 +170,14 @@ template<class T>
template<class TOther>
BEInteger<T> &BEInteger<T>::operator/=(TOther value)
{
BEInteger_SwapHelper<T>::Swap(m_beValue);
m_beValue /= value;
BEInteger_SwapHelper<T>::Swap(m_beValue);
T storedValue;
memcpy(&storedValue, m_beValueBytes, sizeof(T));
BEInteger_SwapHelper<T>::Swap(storedValue);
storedValue /= value;
BEInteger_SwapHelper<T>::Swap(storedValue);
memcpy(m_beValueBytes, &storedValue, sizeof(T));
return *this;
}
@@ -163,18 +185,28 @@ template<class T>
template<class TOther>
BEInteger<T> &BEInteger<T>::operator%=(TOther value)
{
BEInteger_SwapHelper<T>::Swap(m_beValue);
m_beValue %= value;
BEInteger_SwapHelper<T>::Swap(m_beValue);
T storedValue;
memcpy(&storedValue, m_beValueBytes, sizeof(T));
BEInteger_SwapHelper<T>::Swap(storedValue);
storedValue %= value;
BEInteger_SwapHelper<T>::Swap(storedValue);
memcpy(m_beValueBytes, &storedValue, sizeof(T));
return *this;
}
template<class T>
BEInteger<T>& BEInteger<T>::operator--()
{
BEInteger_SwapHelper<T>::Swap(m_beValue);
m_beValue--;
BEInteger_SwapHelper<T>::Swap(m_beValue);
T storedValue;
memcpy(&storedValue, m_beValueBytes, sizeof(T));
BEInteger_SwapHelper<T>::Swap(storedValue);
storedValue--;
BEInteger_SwapHelper<T>::Swap(storedValue);
memcpy(m_beValueBytes, &storedValue, sizeof(T));
return *this;
}
@@ -189,9 +221,14 @@ BEInteger<T> BEInteger<T>::operator--(int)
template<class T>
BEInteger<T>& BEInteger<T>::operator++()
{
BEInteger_SwapHelper<T>::Swap(m_beValue);
m_beValue++;
BEInteger_SwapHelper<T>::Swap(m_beValue);
T storedValue;
memcpy(&storedValue, m_beValueBytes, sizeof(T));
BEInteger_SwapHelper<T>::Swap(storedValue);
storedValue++;
BEInteger_SwapHelper<T>::Swap(storedValue);
memcpy(m_beValueBytes, &storedValue, sizeof(T));
return *this;
}
@@ -209,4 +246,10 @@ typedef BEInteger<int32_t> BEInt32_t;
typedef BEInteger<uint16_t> BEUInt16_t;
typedef BEInteger<uint32_t> BEUInt32_t;
struct BEFixed32_t
{
BEInt16_t m_intPart;
BEUInt16_t m_fracPart;
};
#endif

View File

@@ -12,9 +12,14 @@
#include "HostSystemServices.h"
#include "ResourceManager.h"
#include "MemoryManager.h"
#include "MemReaderStream.h"
#include "MMHandleBlock.h"
#include "ResTypeID.h"
#include "RandomNumberGenerator.h"
#include "PLBigEndian.h"
#include "QDManager.h"
#include "WindowDef.h"
#include "WindowManager.h"
#include <assert.h>
@@ -22,6 +27,17 @@ void InitCursor()
{
}
Rect BERect::ToRect() const
{
Rect rect;
rect.top = this->top;
rect.bottom = this->bottom;
rect.left = this->left;
rect.right = this->right;
return rect;
}
OSErr FSClose(short fsRef)
{
PL_NotYetImplemented();
@@ -62,6 +78,11 @@ void SetCursor(CursPtr cursor)
PL_NotYetImplemented();
}
void SetBuiltinCursor(int builtinCursor)
{
PL_NotYetImplemented();
}
void DisposeCCursor(CCrsrHandle handle)
{
PL_NotYetImplemented();
@@ -168,8 +189,24 @@ void GetWindowBounds(WindowPtr window, WindowRegionType windowRegion, Rect *rect
WindowPtr GetNewCWindow(int resID, void *storage, WindowPtr behind)
{
PL_NotYetImplemented();
return nullptr;
Handle windowResource = GetResource('WIND', resID);
if (!windowResource)
return nullptr;
long resSize = GetHandleSize(windowResource);
PortabilityLayer::MemReaderStream stream(*windowResource, resSize);
PortabilityLayer::WindowDef def;
if (!def.Deserialize(&stream))
return nullptr;
WindowPtr window = PortabilityLayer::WindowManager::GetInstance()->CreateWindow(def);
if (window)
PortabilityLayer::WindowManager::GetInstance()->PutWindowBehind(window, behind);
return window;
}
WindowPtr NewCWindow(void *storage, const Rect *bounds, const PLPasStr &title, Boolean visible, int wdef, WindowPtr behind, Boolean hasCloseBox, long userdata)
@@ -186,17 +223,21 @@ WindowPtr NewWindow(void *storage, const Rect *bounds, const PLPasStr &title, Bo
void SizeWindow(WindowPtr window, int width, int height, Boolean addToUpdateRegion)
{
PL_NotYetImplemented();
PortabilityLayer::WindowManager::GetInstance()->ResizeWindow(window, width, height);
}
void MoveWindow(WindowPtr window, int x, int y, Boolean moveToFront)
{
PL_NotYetImplemented();
PortabilityLayer::WindowManager *windowManager = PortabilityLayer::WindowManager::GetInstance();
windowManager->MoveWindow(window, x, y);
if (moveToFront != 0)
windowManager->PutWindowBehind(window, windowManager->GetPutInFrontSentinel());
}
void ShowWindow(WindowPtr window)
{
PL_NotYetImplemented();
PortabilityLayer::WindowManager::GetInstance()->ShowWindow(window);
}
void SetWTitle(WindowPtr window, const PLPasStr &title)
@@ -286,7 +327,27 @@ OSErr FindFolder(int refNum, int posType, bool createFolder, short *volumeRef, l
void GetIndString(unsigned char *str, int stringsID, int fnameIndex)
{
PL_NotYetImplemented();
if (fnameIndex < 1)
return;
PortabilityLayer::MMHandleBlock *istrRes = PortabilityLayer::ResourceManager::GetInstance()->GetResource('STR#', stringsID);
if (istrRes && istrRes->m_contents)
{
const uint8_t *contentsBytes = static_cast<const uint8_t *>(istrRes->m_contents);
const BEUInt16_t *pArraySize = reinterpret_cast<const BEUInt16_t*>(contentsBytes);
const uint16_t arraySize = *pArraySize;
if (fnameIndex > static_cast<int>(arraySize))
return;
const uint8_t *strStart = contentsBytes + 2;
for (int i = 1; i < fnameIndex; i++)
strStart += (*strStart) + 1;
str[0] = strStart[0];
memcpy(str + 1, strStart + 1, *strStart);
}
}
OSErr PBDirCreate(HFileParam *fileParam, bool asynchronous)
@@ -489,13 +550,16 @@ Handle NewHandle(Size size)
void DisposeHandle(Handle handle)
{
PL_NotYetImplemented();
PortabilityLayer::MemoryManager::GetInstance()->ReleaseHandle(reinterpret_cast<PortabilityLayer::MMHandleBlock*>(handle));
}
long GetHandleSize(Handle handle)
{
PL_NotYetImplemented();
return 0;
if (!handle)
return 0;
PortabilityLayer::MMHandleBlock *block = reinterpret_cast<PortabilityLayer::MMHandleBlock*>(handle);
return static_cast<long>(block->m_size);
}
void HNoPurge(Handle hdl)
@@ -527,14 +591,16 @@ void SetHandleSize(Handle hdl, Size newSize)
void *NewPtr(Size size)
{
PL_NotYetImplemented();
return nullptr;
return PortabilityLayer::MemoryManager::GetInstance()->Alloc(size);
}
void *NewPtrClear(Size size)
{
PL_NotYetImplemented();
return nullptr;
void *data = NewPtr(size);
if (data != nullptr && size != 0)
memset(data, 0, size);
return data;
}
void DisposePtr(void *ptr)
@@ -572,7 +638,7 @@ OSErr MemError()
void BlockMove(const void *src, void *dest, Size size)
{
PL_NotYetImplemented();
memcpy(dest, src, size);
}
Boolean WaitNextEvent(int eventMask, EventRecord *eventOut, long sleep, void *unknown)
@@ -611,4 +677,15 @@ void PL_Init()
PortabilityLayer::ResourceManager::GetInstance()->Init();
PortabilityLayer::DisplayDeviceManager::GetInstance()->Init();
PortabilityLayer::AEManager::GetInstance()->Init();
PortabilityLayer::QDManager::GetInstance()->Init();
}
WindowPtr PL_GetPutInFrontWindowPtr()
{
return PortabilityLayer::WindowManager::GetInstance()->GetPutInFrontSentinel();
}
Window::Window()
: m_port(PortabilityLayer::QDPortType_Window)
{
}

View File

@@ -4,6 +4,8 @@
#include "DataTypes.h"
#include "PLErrorCodes.h"
#include "SharedTypes.h"
#include "QDPort.h"
#ifdef _MSC_VER
#pragma warning(error:4311) // Pointer truncation to int
@@ -33,24 +35,11 @@ typedef unsigned char Str255[256];
typedef unsigned char *StringPtr;
class PLPasStr;
struct CGraf;
struct Region;
#define PL_DEAD(n) ((void)0)
typedef struct Point
{
short v;
short h;
} Point;
// FIXME: Audit
struct Rect
{
short top;
short left;
short bottom;
short right;
};
struct FinderInfoBlock
{
Int32 fdType;
@@ -93,21 +82,18 @@ struct CCursor
{
};
struct CGraf
{
};
struct Window
{
Window();
PortabilityLayer::QDPort m_port; // Must be the first item
};
struct Menu
{
};
struct Region
{
};
struct DateTimeRec
{
@@ -280,6 +266,7 @@ void SetCCursor(CCrsrHandle handle);
void HideCursor();
void SetCursor(CursPtr cursor);
void SetBuiltinCursor(int builtinCursor);
void DisposeCCursor(CCrsrHandle handle);
@@ -402,6 +389,7 @@ void DebugStr(const PLPasStr &str);
static const Boolean PL_TRUE = 1;
static const Boolean PL_FALSE = 0;
WindowPtr PL_GetPutInFrontWindowPtr();
void PL_NotYetImplemented();
void PL_NotYetImplemented_Minor();

View File

@@ -6,7 +6,7 @@
class PLPasStr;
struct Dialog
struct Dialog : public PortabilityLayer::QDPort
{
};

View File

@@ -1,6 +1,6 @@
#pragma once
#ifndef __PL_ERROR_CODES_H__
#define __PL_ERROR_CODES_H__
#pragma once
#ifndef __PL_ERROR_CODES_H__
#define __PL_ERROR_CODES_H__
enum ErrorCodes
{
@@ -25,6 +25,7 @@ enum ErrorCodes
volOffLinErr,
permErr,
wrPermErr,
queueFull,
genericErr,
};

View File

@@ -1,11 +1,10 @@
#include "PLMovies.h"
OSErr EnterMovies()
{
PL_NotYetImplemented();
return noErr;
}
#include "PLMovies.h"
OSErr EnterMovies()
{
return noErr;
}
UserData GetMovieUserData(Movie movie)
{
PL_NotYetImplemented();
@@ -137,5 +136,5 @@ void SetMovieBox(Movie movie, const Rect *rect)
void SetMovieDisplayClipRgn(Movie movie, RgnHandle region)
{
PL_NotYetImplemented();
}
PL_NotYetImplemented();
}

View File

@@ -1,10 +1,240 @@
#include "PLQDOffscreen.h"
#include "PLQDOffscreen.h"
#include "MemoryManager.h"
#include "MemReaderStream.h"
#include "ResourceManager.h"
#include "Rect2i.h"
#include "ResTypeID.h"
#include "QDStandardPalette.h"
#include "QDManager.h"
#include "QDGraf.h"
#include "QDPictDecoder.h"
#include "QDPictEmitContext.h"
#include "QDPictEmitScanlineParameters.h"
#include "QDPictHeader.h"
#include "QDPictOpcodes.h"
#include "QDPixMap.h"
#include "Vec2i.h"
#include <string.h>
#include <assert.h>
namespace PortabilityLayer
{
class PixMapBlitEmitter final : public QDPictEmitContext
{
public:
PixMapBlitEmitter(const Vec2i &drawOrigin, PixMapImpl *pixMap);
~PixMapBlitEmitter();
bool SpecifyFrame(const Rect &rect) override;
Rect ConstrainRegion(const Rect &rect) const override;
void Start(QDPictBlitSourceType sourceType, const QDPictEmitScanlineParameters &params) override;
void BlitScanlineAndAdvance(const void *) override;
bool AllocTempBuffers(uint8_t *&buffer1, size_t buffer1Size, uint8_t *&buffer2, size_t buffer2Size) override;
private:
PixMapImpl *m_pixMap;
Vec2i m_drawOrigin;
uint8_t *m_tempBuffer;
Rect m_specFrame;
QDPictBlitSourceType m_blitType;
QDPictEmitScanlineParameters m_params;
size_t m_constraintRegionWidth;
size_t m_constraintRegionStartIndex;
size_t m_constraintRegionEndIndex;
size_t m_outputIndexStart;
uint8_t m_paletteMap[256];
bool m_sourceAndDestPalettesAreSame;
};
PixMapBlitEmitter::PixMapBlitEmitter(const Vec2i &drawOrigin, PixMapImpl *pixMap)
: m_pixMap(pixMap)
, m_drawOrigin(drawOrigin)
, m_tempBuffer(nullptr)
, m_sourceAndDestPalettesAreSame(false)
{
}
PixMapBlitEmitter::~PixMapBlitEmitter()
{
if (m_tempBuffer)
PortabilityLayer::MemoryManager::GetInstance()->Release(m_tempBuffer);
}
bool PixMapBlitEmitter::SpecifyFrame(const Rect &rect)
{
m_specFrame = rect;
return true;
}
Rect PixMapBlitEmitter::ConstrainRegion(const Rect &rect) const
{
const Rect pixMapRect = m_pixMap->m_rect;
const Rect2i rectInDrawSpace = Rect2i(rect) + m_drawOrigin;
const Rect2i constrainedRectInDrawSpace = rectInDrawSpace.Intersect(Rect2i(pixMapRect));
// If this got completely culled away, return an empty rect, but avoid int truncation
if (!constrainedRectInDrawSpace.IsValid())
return Rect::Create(rect.top, rect.left, rect.top, rect.left);
// Otherwise, it should still be valid in the picture space
const Rect2i constrainedRectInPictSpace = constrainedRectInDrawSpace - m_drawOrigin;
return constrainedRectInPictSpace.ToShortRect();
}
void PixMapBlitEmitter::Start(QDPictBlitSourceType sourceType, const QDPictEmitScanlineParameters &params)
{
// FIXME: Detect different system palette (if we ever do that)
if (QDPictBlitSourceType_IsIndexed(sourceType))
{
if (params.m_numColors == 256 && !memcmp(params.m_colors, StandardPalette::GetInstance()->GetColors(), sizeof(RGBAColor) * 256))
m_sourceAndDestPalettesAreSame = true;
else
{
assert(false);
}
}
m_blitType = sourceType;
m_params = params;
m_constraintRegionWidth = params.m_constrainedRegionRight - params.m_constrainedRegionLeft;
m_constraintRegionStartIndex = params.m_constrainedRegionLeft - params.m_scanlineOriginX;
m_constraintRegionEndIndex = params.m_constrainedRegionRight - params.m_scanlineOriginX;
const size_t firstCol = params.m_constrainedRegionLeft + m_drawOrigin.m_x - m_pixMap->m_rect.left;
const size_t firstRow = params.m_firstY + m_drawOrigin.m_y - m_pixMap->m_rect.top;
m_outputIndexStart = firstRow * m_pixMap->GetPitch() + firstCol;
}
void PixMapBlitEmitter::BlitScanlineAndAdvance(const void *data)
{
const int32_t crRight = m_params.m_constrainedRegionRight;
const int32_t crLeft = m_params.m_constrainedRegionLeft;
const size_t constraintRegionStartIndex = m_constraintRegionStartIndex;
const uint8_t *dataBytes = static_cast<const uint8_t*>(data);
const size_t outputIndexStart = m_outputIndexStart;
const size_t planarSeparation = m_params.m_planarSeparation;
const size_t constraintRegionWidth = m_constraintRegionWidth;
const uint8_t *paletteMapping = nullptr;
const uint8_t staticMapping1Bit[] = { 0, 255 };
void *imageData = m_pixMap->GetPixelData();
if (m_pixMap->GetPixelFormat() == PixelFormat_8BitStandard)
{
switch (m_blitType)
{
case QDPictBlitSourceType_Indexed1Bit:
for (size_t i = 0; i < constraintRegionWidth; i++)
{
const size_t itemIndex = i + constraintRegionStartIndex;
const int bitShift = 7 - (itemIndex & 7);
const int colorIndex = (dataBytes[itemIndex / 8] >> bitShift) & 0x1;
static_cast<uint8_t*>(imageData)[i + outputIndexStart] = paletteMapping[colorIndex];
}
break;
case QDPictBlitSourceType_Indexed2Bit:
for (size_t i = 0; i < constraintRegionWidth; i++)
{
const size_t itemIndex = i + constraintRegionStartIndex;
const int bitShift = 6 - (2 * (itemIndex & 1));
const int colorIndex = (dataBytes[itemIndex / 4] >> bitShift) & 0x3;
static_cast<uint8_t*>(imageData)[i + outputIndexStart] = paletteMapping[colorIndex];
}
break;
case QDPictBlitSourceType_Indexed4Bit:
for (size_t i = 0; i < constraintRegionWidth; i++)
{
const size_t itemIndex = i + constraintRegionStartIndex;
const int bitShift = 4 - (4 * (itemIndex & 1));
const int colorIndex = (dataBytes[itemIndex / 2] >> bitShift) & 0xf;
static_cast<uint8_t*>(imageData)[i + outputIndexStart] = paletteMapping[colorIndex];
}
break;
case QDPictBlitSourceType_Indexed8Bit:
if (m_sourceAndDestPalettesAreSame)
memcpy(static_cast<uint8_t*>(imageData) + outputIndexStart, dataBytes + constraintRegionStartIndex, m_constraintRegionWidth);
else
{
for (size_t i = 0; i < constraintRegionWidth; i++)
{
const size_t itemIndex = i + constraintRegionStartIndex;
const uint8_t colorIndex = dataBytes[itemIndex];
static_cast<uint8_t*>(imageData)[i + outputIndexStart] = paletteMapping[colorIndex];
}
}
break;
case QDPictBlitSourceType_1Bit:
for (size_t i = 0; i < constraintRegionWidth; i++)
{
const size_t itemIndex = i + constraintRegionStartIndex;
const int bitShift = 7 - (itemIndex & 7);
const int colorIndex = (dataBytes[itemIndex / 8] >> bitShift) & 0x1;
static_cast<uint8_t*>(imageData)[i + outputIndexStart] = staticMapping1Bit[colorIndex];
}
break;
case QDPictBlitSourceType_RGB15:
for (size_t i = 0; i < constraintRegionWidth; i++)
{
const size_t itemIndex = i + constraintRegionStartIndex;
const uint16_t item = *reinterpret_cast<const uint16_t*>(dataBytes + itemIndex * 2);
uint8_t &outputItem = static_cast<uint8_t*>(imageData)[i + outputIndexStart];
outputItem = StandardPalette::GetInstance()->MapColorLUT((item >> 1) & 0xf, (item >> 6) & 0xf, (item >> 11) & 0x1f);
}
break;
case QDPictBlitSourceType_RGB24_Multiplane:
for (size_t i = 0; i < m_constraintRegionWidth; i++)
{
const size_t itemIndex = i + constraintRegionStartIndex;
uint8_t &outputItem = static_cast<uint8_t*>(imageData)[i + outputIndexStart];
const uint8_t r = dataBytes[itemIndex];
const uint8_t g = dataBytes[itemIndex + planarSeparation];
const uint8_t b = dataBytes[itemIndex + planarSeparation * 2];
outputItem = StandardPalette::GetInstance()->MapColorLUT(r, g, b);
}
break;
default:
assert(false);
}
}
m_outputIndexStart += m_pixMap->GetPitch();
}
bool PixMapBlitEmitter::AllocTempBuffers(uint8_t *&buffer1, size_t buffer1Size, uint8_t *&buffer2, size_t buffer2Size)
{
m_tempBuffer = static_cast<uint8_t*>(PortabilityLayer::MemoryManager::GetInstance()->Alloc(buffer1Size + buffer2Size));
if (!m_tempBuffer)
return false;
buffer1 = m_tempBuffer;
buffer2 = m_tempBuffer + buffer1Size;
return true;
}
}
OSErr NewGWorld(GWorldPtr *gworld, int depth, Rect *bounds, CTabHandle colorTable, GDHandle device, int flags)
{
PL_NotYetImplemented();
return noErr;
return PortabilityLayer::QDManager::GetInstance()->NewGWorld(gworld, depth, *bounds, colorTable, device, flags);
}
void DisposeGWorld(GWorldPtr gworld)
@@ -14,37 +244,90 @@ void DisposeGWorld(GWorldPtr gworld)
PixMapHandle GetGWorldPixMap(GWorldPtr gworld)
{
PL_NotYetImplemented();
return nullptr;
if (!gworld)
return nullptr;
return gworld->m_port.GetPixMap();
}
void LockPixels(PixMapHandle pixmap)
{
PL_NotYetImplemented();
(void)pixmap;
}
PicHandle GetPicture(short resID)
{
PL_NotYetImplemented();
return nullptr;
return reinterpret_cast<PicHandle>(PortabilityLayer::ResourceManager::GetInstance()->GetResource('PICT', resID));
}
void OffsetRect(Rect *rect, int right, int down)
{
PL_NotYetImplemented();
rect->left += right;
rect->right += right;
rect->top += down;
rect->bottom += down;
}
void DrawPicture(PicHandle pict, Rect *bounds)
{
PL_NotYetImplemented();
if (!pict)
return;
PicPtr picPtr = *pict;
if (!picPtr)
return;
const Rect picRect = picPtr->picFrame.ToRect();
if (bounds->right - bounds->left != picRect.right - picRect.left || bounds->bottom - bounds->top != picRect.bottom - picRect.top)
{
// Scaled pict draw (not supported)
assert(false);
return;
}
PortabilityLayer::QDManager *qdManager = PortabilityLayer::QDManager::GetInstance();
PortabilityLayer::QDPort *port;
qdManager->GetPort(&port, nullptr);
if (!port)
return;
PortabilityLayer::PixMapImpl *pixMap = static_cast<PortabilityLayer::PixMapImpl*>(*port->GetPixMap());
long handleSize = GetHandleSize(reinterpret_cast<Handle>(pict));
PortabilityLayer::MemReaderStream stream(picPtr, handleSize);
switch (pixMap->GetPixelFormat())
{
case PortabilityLayer::PixelFormat_8BitStandard:
{
PortabilityLayer::PixMapBlitEmitter blitEmitter(PortabilityLayer::Vec2i(bounds->left, bounds->top), pixMap);
PortabilityLayer::QDPictDecoder decoder;
decoder.DecodePict(&stream, &blitEmitter);
}
break;
default:
// TODO: Implement higher-resolution pixel blitters
assert(false);
return;
};
}
void GetGWorld(CGrafPtr *gw, GDHandle *gdHandle)
{
PL_NotYetImplemented();
PortabilityLayer::QDPort *port;
PortabilityLayer::QDManager::GetInstance()->GetPort(&port, gdHandle);
CGrafPtr grafPtr = reinterpret_cast<CGrafPtr>(port);
assert(&grafPtr->m_port == port);
*gw = grafPtr;
}
void SetGWorld(CGrafPtr gw, GDHandle gdHandle)
{
PL_NotYetImplemented();
PortabilityLayer::QDManager::GetInstance()->SetPort(&gw->m_port, gdHandle);
}

View File

@@ -9,14 +9,7 @@ struct ColorTable
{
};
struct PixMap
{
};
struct Picture
{
Rect picFrame;
};
struct PixMap;
typedef ColorTable *CTabPtr;
typedef CTabPtr *CTabHandle;

View File

@@ -1,5 +1,15 @@
#include "PLQuickdraw.h"
#include "QDManager.h"
#include "QDState.h"
#include "DisplayDeviceManager.h"
#include "MMHandleBlock.h"
#include "ResourceManager.h"
#include "ResTypeID.h"
#include "RGBAColor.h"
#include "WindowManager.h"
#include "QDGraf.h"
#include "QDPixMap.h"
#include "QDUtils.h"
void GetPort(GrafPtr *graf)
{
@@ -8,15 +18,19 @@ void GetPort(GrafPtr *graf)
void SetPort(GrafPtr graf)
{
PL_NotYetImplemented();
PortabilityLayer::QDManager *qd = PortabilityLayer::QDManager::GetInstance();
GDHandle device;
qd->GetPort(nullptr, &device);
qd->SetPort(graf, device);
}
void BeginUpdate(GrafPtr graf)
void BeginUpdate(WindowPtr graf)
{
PL_NotYetImplemented();
}
void EndUpdate(GrafPtr graf)
void EndUpdate(WindowPtr graf)
{
PL_NotYetImplemented();
}
@@ -65,7 +79,11 @@ GDHandle GetMainDevice()
void SetPortWindowPort(WindowPtr window)
{
PL_NotYetImplemented();
PortabilityLayer::WindowManager *wm = PortabilityLayer::WindowManager::GetInstance();
GDevice **device = wm->GetWindowDevice(window);
PortabilityLayer::QDManager::GetInstance()->SetPort(&window->m_port, device);
}
void SetPortDialogPort(Dialog *dialog)
@@ -73,20 +91,19 @@ void SetPortDialogPort(Dialog *dialog)
PL_NotYetImplemented();
}
void TextSize(int sz)
{
PL_NotYetImplemented();
PortabilityLayer::QDManager::GetInstance()->GetState()->m_textSize = sz;
}
void TextFace(int face)
{
PL_NotYetImplemented();
PortabilityLayer::QDManager::GetInstance()->GetState()->m_textFace = face;
}
void TextFont(int fontID)
{
PL_NotYetImplemented();
PortabilityLayer::QDManager::GetInstance()->GetState()->m_fontID = fontID;
}
int TextWidth(const PLPasStr &str, int firstChar1Based, int length)
@@ -110,14 +127,69 @@ void SetOrigin(int x, int y)
PL_NotYetImplemented();
}
namespace
{
static bool SystemColorToRGBAColor(SystemColorID color, PortabilityLayer::RGBAColor &rgbaColor)
{
switch (color)
{
default:
return false;
case whiteColor:
rgbaColor.r = rgbaColor.g = rgbaColor.b = 255;
break;
case blackColor:
rgbaColor.r = rgbaColor.g = rgbaColor.b = 0;
break;
case yellowColor:
rgbaColor.r = rgbaColor.g = 255;
rgbaColor.b = 0;
break;
case magentaColor:
rgbaColor.r = rgbaColor.b = 255;
rgbaColor.g = 0;
break;
case redColor:
rgbaColor.r = 255;
rgbaColor.g = rgbaColor.b = 0;
break;
case cyanColor:
rgbaColor.g = rgbaColor.b = 255;
rgbaColor.r = 0;
break;
case greenColor:
rgbaColor.g = 255;
rgbaColor.r = rgbaColor.b = 0;
break;
case blueColor:
rgbaColor.b = 255;
rgbaColor.r = rgbaColor.g = 0;
break;
}
rgbaColor.a = 255;
return true;
}
}
void ForeColor(SystemColorID color)
{
PL_NotYetImplemented();
PortabilityLayer::RGBAColor rgbaColor;
if (SystemColorToRGBAColor(color, rgbaColor))
{
PortabilityLayer::QDState *qdState = PortabilityLayer::QDManager::GetInstance()->GetState();
qdState->SetForeColor(rgbaColor);
}
}
void BackColor(SystemColorID color)
{
PL_NotYetImplemented();
PortabilityLayer::RGBAColor rgbaColor;
if (SystemColorToRGBAColor(color, rgbaColor))
{
PortabilityLayer::QDState *qdState = PortabilityLayer::QDManager::GetInstance()->GetState();
qdState->SetBackColor(rgbaColor);
}
}
void GetForeColor(RGBColor *color)
@@ -142,7 +214,59 @@ void DrawString(const PLPasStr &str)
void PaintRect(const Rect *rect)
{
PL_NotYetImplemented();
if (!rect->IsValid())
return;
PortabilityLayer::QDPort *qdPort;
PortabilityLayer::QDManager::GetInstance()->GetPort(&qdPort, nullptr);
PortabilityLayer::PixelFormat pixelFormat = qdPort->GetPixelFormat();
Rect constrainedRect = *rect;
PortabilityLayer::QDState *qdState = qdPort->GetState();
if (qdState->m_clipRegion)
{
const Region &region = **qdState->m_clipRegion;
if (region.size > sizeof(Region))
PL_NotYetImplemented();
constrainedRect = constrainedRect.Intersect(region.rect);
}
constrainedRect = constrainedRect.Intersect(qdPort->GetRect());
if (!constrainedRect.IsValid())
return;
PortabilityLayer::PixMapImpl *pixMap = static_cast<PortabilityLayer::PixMapImpl*>(*qdPort->GetPixMap());
const size_t pitch = pixMap->GetPitch();
const size_t firstIndex = static_cast<size_t>(constrainedRect.top) * pitch + static_cast<size_t>(constrainedRect.left);
const size_t numLines = static_cast<size_t>(constrainedRect.bottom - constrainedRect.top);
const size_t numCols = static_cast<size_t>(constrainedRect.right - constrainedRect.left);
uint8_t *pixData = static_cast<uint8_t*>(pixMap->GetPixelData());
switch (pixelFormat)
{
case PortabilityLayer::PixelFormat_8BitStandard:
{
const uint8_t color = qdState->ResolveForeColor8(nullptr, 0);
size_t scanlineIndex = 0;
for (size_t ln = 0; ln < numLines; ln++)
{
const size_t firstLineIndex = firstIndex + ln * pitch;
for (size_t col = 0; col < numCols; col++)
pixData[firstLineIndex + col] = color;
}
}
break;
default:
PL_NotYetImplemented();
return;
}
}
void PaintOval(const Rect *rect)
@@ -157,7 +281,14 @@ void PaintRgn(RgnHandle region)
void ClipRect(const Rect *rect)
{
PL_NotYetImplemented();
if (!rect->IsValid())
return;
PortabilityLayer::QDState *qdState = PortabilityLayer::QDManager::GetInstance()->GetState();
if (!qdState->m_clipRegion)
qdState->m_clipRegion = PortabilityLayer::QDUtils::CreateRegion(*rect);
else
PortabilityLayer::QDUtils::ResetRegionToRect(qdState->m_clipRegion, *rect);
}
void FrameRect(const Rect *rect)
@@ -239,7 +370,17 @@ Pattern *GetQDGlobalsBlack(Pattern *pattern)
void GetIndPattern(Pattern *pattern, int patListID, int index)
{
PL_NotYetImplemented();
if (index < 1)
return;
PortabilityLayer::MMHandleBlock *patternList = PortabilityLayer::ResourceManager::GetInstance()->GetResource('PAT#', patListID);
const uint8_t *patternRes = static_cast<const uint8_t*>(patternList->m_contents);
int numPatterns = (patternRes[0] << 8) | patternRes[1];
if (index > numPatterns)
return;
memcpy(pattern, patternRes + 2 + (index - 1) * 8, 8);
}

View File

@@ -3,6 +3,8 @@
#define __PL_QUICKDRAW_H__
#include "PLCore.h"
#include "QDGraf.h"
#include "SharedTypes.h"
struct Dialog;
@@ -100,12 +102,9 @@ struct CIcon
{
};
struct GDevice
{
};
struct BitMap
{
Rect m_rect;
};
struct RGBColor
@@ -121,7 +120,8 @@ typedef GDPtr *GDHandle;
typedef CIcon *CIconPtr;
typedef CIconPtr *CIconHandle;
typedef WindowPtr GrafPtr;
typedef PortabilityLayer::QDPort GrafPort;
typedef GrafPort *GrafPtr;
typedef Byte Pattern[8];
@@ -130,8 +130,8 @@ void SetPort(GrafPtr graf);
void SetPortWindowPort(WindowPtr window);
void SetPortDialogPort(Dialog *dialog);
void BeginUpdate(GrafPtr graf);
void EndUpdate(GrafPtr graf);
void BeginUpdate(WindowPtr graf);
void EndUpdate(WindowPtr graf);
OSErr GetIconSuite(Handle *suite, short resID, IconSuiteFlags flags);
OSErr PlotIconSuite(Rect *rect, IconAlignmentType alignType, IconTransformType transformType, Handle iconSuite);

Some files were not shown because too many files have changed in this diff Show More