mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-05-28 07:54:51 -04:00
Fix relocated files
This commit is contained in:
+7
-1
@@ -59,7 +59,13 @@ add_library(game_debug STATIC ${JSYSTEM_DEBUG_FILES} ${SSYSTEM_FILES})
|
||||
target_compile_definitions(game_debug PRIVATE TARGET_PC VERSION=0 $<$<CONFIG:Debug>:DEBUG=1>)
|
||||
|
||||
# Make these properties PUBLIC so that the regular game target also sees them.
|
||||
target_include_directories(game_debug PUBLIC include src assets/${DUSK_TP_VERSION} ${CMAKE_BINARY_DIR}/../${DUSK_TP_VERSION}/include build/${DUSK_TP_VERSION}/include)
|
||||
target_include_directories(game_debug PUBLIC
|
||||
include
|
||||
src
|
||||
assets/${DUSK_TP_VERSION}
|
||||
libs/JSystem/include
|
||||
${CMAKE_BINARY_DIR}/../${DUSK_TP_VERSION}/include
|
||||
build/${DUSK_TP_VERSION}/include)
|
||||
target_link_libraries(game_debug PUBLIC aurora::core aurora::gx aurora::si aurora::vi aurora::pad aurora::mtx)
|
||||
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
|
||||
+240
-240
@@ -315,243 +315,243 @@ set(SSYSTEM_FILES
|
||||
)
|
||||
|
||||
set(JSYSTEM_DEBUG_FILES
|
||||
src/JSystem/JParticle/JPAResourceManager.cpp
|
||||
src/JSystem/JParticle/JPAResource.cpp
|
||||
src/JSystem/JParticle/JPABaseShape.cpp
|
||||
src/JSystem/JParticle/JPAExtraShape.cpp
|
||||
src/JSystem/JParticle/JPAChildShape.cpp
|
||||
src/JSystem/JParticle/JPAExTexShape.cpp
|
||||
src/JSystem/JParticle/JPADynamicsBlock.cpp
|
||||
src/JSystem/JParticle/JPAFieldBlock.cpp
|
||||
src/JSystem/JParticle/JPAKeyBlock.cpp
|
||||
src/JSystem/JParticle/JPATexture.cpp
|
||||
src/JSystem/JParticle/JPAResourceLoader.cpp
|
||||
src/JSystem/JParticle/JPAEmitterManager.cpp
|
||||
src/JSystem/JParticle/JPAEmitter.cpp
|
||||
src/JSystem/JParticle/JPAParticle.cpp
|
||||
src/JSystem/JParticle/JPAMath.cpp
|
||||
src/JSystem/JFramework/JFWSystem.cpp
|
||||
src/JSystem/JFramework/JFWDisplay.cpp
|
||||
src/JSystem/J3DU/J3DUClipper.cpp
|
||||
src/JSystem/J3DU/J3DUDL.cpp
|
||||
src/JSystem/JKernel/JKRHeap.cpp
|
||||
src/JSystem/JKernel/JKRExpHeap.cpp
|
||||
src/JSystem/JKernel/JKRSolidHeap.cpp
|
||||
src/JSystem/JKernel/JKRAssertHeap.cpp
|
||||
src/JSystem/JKernel/JKRDisposer.cpp
|
||||
src/JSystem/JKernel/JKRThread.cpp
|
||||
src/JSystem/JKernel/JKRAram.cpp
|
||||
src/JSystem/JKernel/JKRAramHeap.cpp
|
||||
src/JSystem/JKernel/JKRAramBlock.cpp
|
||||
src/JSystem/JKernel/JKRAramPiece.cpp
|
||||
src/JSystem/JKernel/JKRAramStream.cpp
|
||||
src/JSystem/JKernel/JKRFileLoader.cpp
|
||||
src/JSystem/JKernel/JKRFileFinder.cpp
|
||||
src/JSystem/JKernel/JKRFileCache.cpp
|
||||
src/JSystem/JKernel/JKRArchivePub.cpp
|
||||
src/JSystem/JKernel/JKRArchivePri.cpp
|
||||
src/JSystem/JKernel/JKRMemArchive.cpp
|
||||
src/JSystem/JKernel/JKRAramArchive.cpp
|
||||
src/JSystem/JKernel/JKRDvdArchive.cpp
|
||||
src/JSystem/JKernel/JKRCompArchive.cpp
|
||||
src/JSystem/JKernel/JKRFile.cpp
|
||||
src/JSystem/JKernel/JKRDvdFile.cpp
|
||||
src/JSystem/JKernel/JKRDvdRipper.cpp
|
||||
src/JSystem/JKernel/JKRDvdAramRipper.cpp
|
||||
src/JSystem/JKernel/JKRDecomp.cpp
|
||||
src/JSystem/JMath/JMath.cpp
|
||||
src/JSystem/JMath/random.cpp
|
||||
src/JSystem/JMath/JMATrigonometric.cpp
|
||||
src/JSystem/JSupport/JSUList.cpp
|
||||
src/JSystem/JSupport/JSUInputStream.cpp
|
||||
src/JSystem/JSupport/JSUOutputStream.cpp
|
||||
src/JSystem/JSupport/JSUMemoryStream.cpp
|
||||
src/JSystem/JSupport/JSUFileStream.cpp
|
||||
src/JSystem/JUtility/JUTCacheFont.cpp
|
||||
src/JSystem/JUtility/JUTResource.cpp
|
||||
src/JSystem/JUtility/JUTTexture.cpp
|
||||
src/JSystem/JUtility/JUTPalette.cpp
|
||||
src/JSystem/JUtility/JUTNameTab.cpp
|
||||
src/JSystem/JUtility/JUTGraphFifo.cpp
|
||||
src/JSystem/JUtility/JUTFont.cpp
|
||||
src/JSystem/JUtility/JUTResFont.cpp
|
||||
src/JSystem/JUtility/JUTDbPrint.cpp
|
||||
src/JSystem/JUtility/JUTGamePad.cpp
|
||||
src/JSystem/JUtility/JUTException.cpp
|
||||
src/JSystem/JUtility/JUTDirectPrint.cpp
|
||||
src/JSystem/JUtility/JUTAssert.cpp
|
||||
src/JSystem/JUtility/JUTVideo.cpp
|
||||
src/JSystem/JUtility/JUTXfb.cpp
|
||||
src/JSystem/JUtility/JUTFader.cpp
|
||||
src/JSystem/JUtility/JUTProcBar.cpp
|
||||
src/JSystem/JUtility/JUTConsole.cpp
|
||||
src/JSystem/JUtility/JUTDirectFile.cpp
|
||||
src/JSystem/JUtility/JUTFontData_Ascfont_fix12.cpp
|
||||
src/JSystem/JStage/JSGActor.cpp
|
||||
src/JSystem/JStage/JSGAmbientLight.cpp
|
||||
src/JSystem/JStage/JSGCamera.cpp
|
||||
src/JSystem/JStage/JSGFog.cpp
|
||||
src/JSystem/JStage/JSGLight.cpp
|
||||
src/JSystem/JStage/JSGObject.cpp
|
||||
src/JSystem/JStage/JSGSystem.cpp
|
||||
src/JSystem/J2DGraph/J2DGrafContext.cpp
|
||||
src/JSystem/J2DGraph/J2DOrthoGraph.cpp
|
||||
src/JSystem/J2DGraph/J2DTevs.cpp
|
||||
src/JSystem/J2DGraph/J2DMaterial.cpp
|
||||
src/JSystem/J2DGraph/J2DMatBlock.cpp
|
||||
src/JSystem/J2DGraph/J2DMaterialFactory.cpp
|
||||
src/JSystem/J2DGraph/J2DPrint.cpp
|
||||
src/JSystem/J2DGraph/J2DPane.cpp
|
||||
src/JSystem/J2DGraph/J2DScreen.cpp
|
||||
src/JSystem/J2DGraph/J2DWindow.cpp
|
||||
src/JSystem/J2DGraph/J2DPicture.cpp
|
||||
src/JSystem/J2DGraph/J2DTextBox.cpp
|
||||
src/JSystem/J2DGraph/J2DWindowEx.cpp
|
||||
src/JSystem/J2DGraph/J2DPictureEx.cpp
|
||||
src/JSystem/J2DGraph/J2DTextBoxEx.cpp
|
||||
src/JSystem/J2DGraph/J2DAnmLoader.cpp
|
||||
src/JSystem/J2DGraph/J2DAnimation.cpp
|
||||
src/JSystem/J2DGraph/J2DManage.cpp
|
||||
src/JSystem/J3DGraphBase/J3DGD.cpp
|
||||
src/JSystem/J3DGraphBase/J3DSys.cpp
|
||||
src/JSystem/J3DGraphBase/J3DVertex.cpp
|
||||
src/JSystem/J3DGraphBase/J3DTransform.cpp
|
||||
src/JSystem/J3DGraphBase/J3DTexture.cpp
|
||||
src/JSystem/J3DGraphBase/J3DPacket.cpp
|
||||
src/JSystem/J3DGraphBase/J3DShapeMtx.cpp
|
||||
src/JSystem/J3DGraphBase/J3DShapeDraw.cpp
|
||||
src/JSystem/J3DGraphBase/J3DShape.cpp
|
||||
src/JSystem/J3DGraphBase/J3DMaterial.cpp
|
||||
src/JSystem/J3DGraphBase/J3DMatBlock.cpp
|
||||
src/JSystem/J3DGraphBase/J3DTevs.cpp
|
||||
src/JSystem/J3DGraphBase/J3DDrawBuffer.cpp
|
||||
src/JSystem/J3DGraphBase/J3DStruct.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DShapeTable.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DJointTree.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DModelData.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DMtxBuffer.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DModel.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DAnimation.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DMaterialAnm.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DSkinDeform.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DCluster.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DJoint.cpp
|
||||
src/JSystem/J3DGraphAnimator/J3DMaterialAttach.cpp
|
||||
src/JSystem/J3DGraphLoader/J3DMaterialFactory.cpp
|
||||
src/JSystem/J3DGraphLoader/J3DMaterialFactory_v21.cpp
|
||||
src/JSystem/J3DGraphLoader/J3DClusterLoader.cpp
|
||||
src/JSystem/J3DGraphLoader/J3DModelLoader.cpp
|
||||
src/JSystem/J3DGraphLoader/J3DModelLoaderCalcSize.cpp
|
||||
src/JSystem/J3DGraphLoader/J3DJointFactory.cpp
|
||||
src/JSystem/J3DGraphLoader/J3DShapeFactory.cpp
|
||||
src/JSystem/J3DGraphLoader/J3DAnmLoader.cpp
|
||||
src/JSystem/JStudio/JStudio/ctb.cpp
|
||||
src/JSystem/JStudio/JStudio/ctb-data.cpp
|
||||
src/JSystem/JStudio/JStudio/functionvalue.cpp
|
||||
src/JSystem/JStudio/JStudio/fvb.cpp
|
||||
src/JSystem/JStudio/JStudio/fvb-data.cpp
|
||||
src/JSystem/JStudio/JStudio/fvb-data-parse.cpp
|
||||
src/JSystem/JStudio/JStudio/jstudio-control.cpp
|
||||
src/JSystem/JStudio/JStudio/jstudio-data.cpp
|
||||
src/JSystem/JStudio/JStudio/jstudio-math.cpp
|
||||
src/JSystem/JStudio/JStudio/jstudio-object.cpp
|
||||
src/JSystem/JStudio/JStudio/object-id.cpp
|
||||
src/JSystem/JStudio/JStudio/stb.cpp
|
||||
src/JSystem/JStudio/JStudio/stb-data-parse.cpp
|
||||
src/JSystem/JStudio/JStudio/stb-data.cpp
|
||||
src/JSystem/JStudio/JStudio_JStage/control.cpp
|
||||
src/JSystem/JStudio/JStudio_JStage/object.cpp
|
||||
src/JSystem/JStudio/JStudio_JStage/object-actor.cpp
|
||||
src/JSystem/JStudio/JStudio_JStage/object-ambientlight.cpp
|
||||
src/JSystem/JStudio/JStudio_JStage/object-camera.cpp
|
||||
src/JSystem/JStudio/JStudio_JStage/object-fog.cpp
|
||||
src/JSystem/JStudio/JStudio_JStage/object-light.cpp
|
||||
src/JSystem/JStudio/JStudio_JAudio2/control.cpp
|
||||
src/JSystem/JStudio/JStudio_JAudio2/object-sound.cpp
|
||||
src/JSystem/JStudio/JStudio_JParticle/control.cpp
|
||||
src/JSystem/JStudio/JStudio_JParticle/object-particle.cpp
|
||||
src/JSystem/JAudio2/JASCalc.cpp
|
||||
src/JSystem/JAudio2/JASTaskThread.cpp
|
||||
src/JSystem/JAudio2/JASDvdThread.cpp
|
||||
src/JSystem/JAudio2/JASCallback.cpp
|
||||
src/JSystem/JAudio2/JASHeapCtrl.cpp
|
||||
src/JSystem/JAudio2/JASResArcLoader.cpp
|
||||
src/JSystem/JAudio2/JASProbe.cpp
|
||||
src/JSystem/JAudio2/JASReport.cpp
|
||||
src/JSystem/JAudio2/JASCmdStack.cpp
|
||||
src/JSystem/JAudio2/JASTrack.cpp
|
||||
src/JSystem/JAudio2/JASTrackPort.cpp
|
||||
src/JSystem/JAudio2/JASRegisterParam.cpp
|
||||
src/JSystem/JAudio2/JASSeqCtrl.cpp
|
||||
src/JSystem/JAudio2/JASSeqParser.cpp
|
||||
src/JSystem/JAudio2/JASSeqReader.cpp
|
||||
src/JSystem/JAudio2/JASAramStream.cpp
|
||||
src/JSystem/JAudio2/JASBank.cpp
|
||||
src/JSystem/JAudio2/JASBasicBank.cpp
|
||||
src/JSystem/JAudio2/JASVoiceBank.cpp
|
||||
src/JSystem/JAudio2/JASBasicInst.cpp
|
||||
src/JSystem/JAudio2/JASDrumSet.cpp
|
||||
src/JSystem/JAudio2/JASBasicWaveBank.cpp
|
||||
src/JSystem/JAudio2/JASSimpleWaveBank.cpp
|
||||
src/JSystem/JAudio2/JASWSParser.cpp
|
||||
src/JSystem/JAudio2/JASBNKParser.cpp
|
||||
src/JSystem/JAudio2/JASWaveArcLoader.cpp
|
||||
src/JSystem/JAudio2/JASChannel.cpp
|
||||
src/JSystem/JAudio2/JASLfo.cpp
|
||||
src/JSystem/JAudio2/JASOscillator.cpp
|
||||
src/JSystem/JAudio2/JASAiCtrl.cpp
|
||||
src/JSystem/JAudio2/JASAudioThread.cpp
|
||||
src/JSystem/JAudio2/JASAudioReseter.cpp
|
||||
src/JSystem/JAudio2/JASDSPChannel.cpp
|
||||
src/JSystem/JAudio2/JASDSPInterface.cpp
|
||||
src/JSystem/JAudio2/JASDriverIF.cpp
|
||||
src/JSystem/JAudio2/JASSoundParams.cpp
|
||||
src/JSystem/JAudio2/dspproc.cpp
|
||||
src/JSystem/JAudio2/dsptask.cpp
|
||||
src/JSystem/JAudio2/osdsp.cpp
|
||||
src/JSystem/JAudio2/osdsp_task.cpp
|
||||
src/JSystem/JAudio2/JAIAudible.cpp
|
||||
src/JSystem/JAudio2/JAIAudience.cpp
|
||||
src/JSystem/JAudio2/JAISe.cpp
|
||||
src/JSystem/JAudio2/JAISeMgr.cpp
|
||||
src/JSystem/JAudio2/JAISeq.cpp
|
||||
src/JSystem/JAudio2/JAISeqDataMgr.cpp
|
||||
src/JSystem/JAudio2/JAISeqMgr.cpp
|
||||
src/JSystem/JAudio2/JAISound.cpp
|
||||
src/JSystem/JAudio2/JAISoundChild.cpp
|
||||
src/JSystem/JAudio2/JAISoundHandles.cpp
|
||||
src/JSystem/JAudio2/JAISoundInfo.cpp
|
||||
src/JSystem/JAudio2/JAISoundParams.cpp
|
||||
src/JSystem/JAudio2/JAISoundStarter.cpp
|
||||
src/JSystem/JAudio2/JAIStream.cpp
|
||||
src/JSystem/JAudio2/JAIStreamDataMgr.cpp
|
||||
src/JSystem/JAudio2/JAIStreamMgr.cpp
|
||||
src/JSystem/JAudio2/JAUAudioArcInterpreter.cpp
|
||||
src/JSystem/JAudio2/JAUAudioArcLoader.cpp
|
||||
src/JSystem/JAudio2/JAUAudioMgr.cpp
|
||||
src/JSystem/JAudio2/JAUBankTable.cpp
|
||||
src/JSystem/JAudio2/JAUClusterSound.cpp
|
||||
src/JSystem/JAudio2/JAUInitializer.cpp
|
||||
src/JSystem/JAudio2/JAUSectionHeap.cpp
|
||||
src/JSystem/JAudio2/JAUSeqCollection.cpp
|
||||
src/JSystem/JAudio2/JAUSeqDataBlockMgr.cpp
|
||||
src/JSystem/JAudio2/JAUSoundAnimator.cpp
|
||||
src/JSystem/JAudio2/JAUSoundTable.cpp
|
||||
src/JSystem/JAudio2/JAUStreamFileTable.cpp
|
||||
src/JSystem/JMessage/control.cpp
|
||||
src/JSystem/JMessage/data.cpp
|
||||
src/JSystem/JMessage/processor.cpp
|
||||
src/JSystem/JMessage/resource.cpp
|
||||
src/JSystem/JMessage/locale.cpp
|
||||
src/JSystem/JGadget/binary.cpp
|
||||
src/JSystem/JGadget/define.cpp
|
||||
src/JSystem/JGadget/linklist.cpp
|
||||
src/JSystem/JGadget/std-vector.cpp
|
||||
src/JSystem/JHostIO/JORHostInfo.cpp
|
||||
src/JSystem/JHostIO/JORServer.cpp
|
||||
src/JSystem/JHostIO/JHIhioASync.cpp
|
||||
src/JSystem/JHostIO/JHIRMcc.cpp
|
||||
src/JSystem/JHostIO/JHIMccBuf.cpp
|
||||
libs/JSystem/src/JParticle/JPAResourceManager.cpp
|
||||
libs/JSystem/src/JParticle/JPAResource.cpp
|
||||
libs/JSystem/src/JParticle/JPABaseShape.cpp
|
||||
libs/JSystem/src/JParticle/JPAExtraShape.cpp
|
||||
libs/JSystem/src/JParticle/JPAChildShape.cpp
|
||||
libs/JSystem/src/JParticle/JPAExTexShape.cpp
|
||||
libs/JSystem/src/JParticle/JPADynamicsBlock.cpp
|
||||
libs/JSystem/src/JParticle/JPAFieldBlock.cpp
|
||||
libs/JSystem/src/JParticle/JPAKeyBlock.cpp
|
||||
libs/JSystem/src/JParticle/JPATexture.cpp
|
||||
libs/JSystem/src/JParticle/JPAResourceLoader.cpp
|
||||
libs/JSystem/src/JParticle/JPAEmitterManager.cpp
|
||||
libs/JSystem/src/JParticle/JPAEmitter.cpp
|
||||
libs/JSystem/src/JParticle/JPAParticle.cpp
|
||||
libs/JSystem/src/JParticle/JPAMath.cpp
|
||||
libs/JSystem/src/JFramework/JFWSystem.cpp
|
||||
libs/JSystem/src/JFramework/JFWDisplay.cpp
|
||||
libs/JSystem/src/J3DU/J3DUClipper.cpp
|
||||
libs/JSystem/src/J3DU/J3DUDL.cpp
|
||||
libs/JSystem/src/JKernel/JKRHeap.cpp
|
||||
libs/JSystem/src/JKernel/JKRExpHeap.cpp
|
||||
libs/JSystem/src/JKernel/JKRSolidHeap.cpp
|
||||
libs/JSystem/src/JKernel/JKRAssertHeap.cpp
|
||||
libs/JSystem/src/JKernel/JKRDisposer.cpp
|
||||
libs/JSystem/src/JKernel/JKRThread.cpp
|
||||
libs/JSystem/src/JKernel/JKRAram.cpp
|
||||
libs/JSystem/src/JKernel/JKRAramHeap.cpp
|
||||
libs/JSystem/src/JKernel/JKRAramBlock.cpp
|
||||
libs/JSystem/src/JKernel/JKRAramPiece.cpp
|
||||
libs/JSystem/src/JKernel/JKRAramStream.cpp
|
||||
libs/JSystem/src/JKernel/JKRFileLoader.cpp
|
||||
libs/JSystem/src/JKernel/JKRFileFinder.cpp
|
||||
libs/JSystem/src/JKernel/JKRFileCache.cpp
|
||||
libs/JSystem/src/JKernel/JKRArchivePub.cpp
|
||||
libs/JSystem/src/JKernel/JKRArchivePri.cpp
|
||||
libs/JSystem/src/JKernel/JKRMemArchive.cpp
|
||||
libs/JSystem/src/JKernel/JKRAramArchive.cpp
|
||||
libs/JSystem/src/JKernel/JKRDvdArchive.cpp
|
||||
libs/JSystem/src/JKernel/JKRCompArchive.cpp
|
||||
libs/JSystem/src/JKernel/JKRFile.cpp
|
||||
libs/JSystem/src/JKernel/JKRDvdFile.cpp
|
||||
libs/JSystem/src/JKernel/JKRDvdRipper.cpp
|
||||
libs/JSystem/src/JKernel/JKRDvdAramRipper.cpp
|
||||
libs/JSystem/src/JKernel/JKRDecomp.cpp
|
||||
libs/JSystem/src/JMath/JMath.cpp
|
||||
libs/JSystem/src/JMath/random.cpp
|
||||
libs/JSystem/src/JMath/JMATrigonometric.cpp
|
||||
libs/JSystem/src/JSupport/JSUList.cpp
|
||||
libs/JSystem/src/JSupport/JSUInputStream.cpp
|
||||
libs/JSystem/src/JSupport/JSUOutputStream.cpp
|
||||
libs/JSystem/src/JSupport/JSUMemoryStream.cpp
|
||||
libs/JSystem/src/JSupport/JSUFileStream.cpp
|
||||
libs/JSystem/src/JUtility/JUTCacheFont.cpp
|
||||
libs/JSystem/src/JUtility/JUTResource.cpp
|
||||
libs/JSystem/src/JUtility/JUTTexture.cpp
|
||||
libs/JSystem/src/JUtility/JUTPalette.cpp
|
||||
libs/JSystem/src/JUtility/JUTNameTab.cpp
|
||||
libs/JSystem/src/JUtility/JUTGraphFifo.cpp
|
||||
libs/JSystem/src/JUtility/JUTFont.cpp
|
||||
libs/JSystem/src/JUtility/JUTResFont.cpp
|
||||
libs/JSystem/src/JUtility/JUTDbPrint.cpp
|
||||
libs/JSystem/src/JUtility/JUTGamePad.cpp
|
||||
libs/JSystem/src/JUtility/JUTException.cpp
|
||||
libs/JSystem/src/JUtility/JUTDirectPrint.cpp
|
||||
libs/JSystem/src/JUtility/JUTAssert.cpp
|
||||
libs/JSystem/src/JUtility/JUTVideo.cpp
|
||||
libs/JSystem/src/JUtility/JUTXfb.cpp
|
||||
libs/JSystem/src/JUtility/JUTFader.cpp
|
||||
libs/JSystem/src/JUtility/JUTProcBar.cpp
|
||||
libs/JSystem/src/JUtility/JUTConsole.cpp
|
||||
libs/JSystem/src/JUtility/JUTDirectFile.cpp
|
||||
libs/JSystem/src/JUtility/JUTFontData_Ascfont_fix12.cpp
|
||||
libs/JSystem/src/JStage/JSGActor.cpp
|
||||
libs/JSystem/src/JStage/JSGAmbientLight.cpp
|
||||
libs/JSystem/src/JStage/JSGCamera.cpp
|
||||
libs/JSystem/src/JStage/JSGFog.cpp
|
||||
libs/JSystem/src/JStage/JSGLight.cpp
|
||||
libs/JSystem/src/JStage/JSGObject.cpp
|
||||
libs/JSystem/src/JStage/JSGSystem.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DGrafContext.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DOrthoGraph.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DTevs.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DMaterial.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DMatBlock.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DMaterialFactory.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DPrint.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DPane.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DScreen.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DWindow.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DPicture.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DTextBox.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DWindowEx.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DPictureEx.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DTextBoxEx.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DAnmLoader.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DAnimation.cpp
|
||||
libs/JSystem/src/J2DGraph/J2DManage.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DGD.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DSys.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DVertex.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DTransform.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DTexture.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DPacket.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DShapeMtx.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DShapeDraw.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DShape.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DMaterial.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DMatBlock.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DTevs.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DDrawBuffer.cpp
|
||||
libs/JSystem/src/J3DGraphBase/J3DStruct.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DShapeTable.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DMtxBuffer.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DModel.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DAnimation.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DMaterialAnm.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DSkinDeform.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DCluster.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DJoint.cpp
|
||||
libs/JSystem/src/J3DGraphAnimator/J3DMaterialAttach.cpp
|
||||
libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory.cpp
|
||||
libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory_v21.cpp
|
||||
libs/JSystem/src/J3DGraphLoader/J3DClusterLoader.cpp
|
||||
libs/JSystem/src/J3DGraphLoader/J3DModelLoader.cpp
|
||||
libs/JSystem/src/J3DGraphLoader/J3DModelLoaderCalcSize.cpp
|
||||
libs/JSystem/src/J3DGraphLoader/J3DJointFactory.cpp
|
||||
libs/JSystem/src/J3DGraphLoader/J3DShapeFactory.cpp
|
||||
libs/JSystem/src/J3DGraphLoader/J3DAnmLoader.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/ctb.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/ctb-data.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/functionvalue.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/fvb.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/fvb-data.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/fvb-data-parse.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/jstudio-control.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/jstudio-data.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/jstudio-math.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/jstudio-object.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/object-id.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/stb.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/stb-data-parse.cpp
|
||||
libs/JSystem/src/JStudio/JStudio/stb-data.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JStage/control.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JStage/object.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JStage/object-actor.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JStage/object-ambientlight.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JStage/object-camera.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JStage/object-fog.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JStage/object-light.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JAudio2/control.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JAudio2/object-sound.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JParticle/control.cpp
|
||||
libs/JSystem/src/JStudio/JStudio_JParticle/object-particle.cpp
|
||||
libs/JSystem/src/JAudio2/JASCalc.cpp
|
||||
libs/JSystem/src/JAudio2/JASTaskThread.cpp
|
||||
libs/JSystem/src/JAudio2/JASDvdThread.cpp
|
||||
libs/JSystem/src/JAudio2/JASCallback.cpp
|
||||
libs/JSystem/src/JAudio2/JASHeapCtrl.cpp
|
||||
libs/JSystem/src/JAudio2/JASResArcLoader.cpp
|
||||
libs/JSystem/src/JAudio2/JASProbe.cpp
|
||||
libs/JSystem/src/JAudio2/JASReport.cpp
|
||||
libs/JSystem/src/JAudio2/JASCmdStack.cpp
|
||||
libs/JSystem/src/JAudio2/JASTrack.cpp
|
||||
libs/JSystem/src/JAudio2/JASTrackPort.cpp
|
||||
libs/JSystem/src/JAudio2/JASRegisterParam.cpp
|
||||
libs/JSystem/src/JAudio2/JASSeqCtrl.cpp
|
||||
libs/JSystem/src/JAudio2/JASSeqParser.cpp
|
||||
libs/JSystem/src/JAudio2/JASSeqReader.cpp
|
||||
libs/JSystem/src/JAudio2/JASAramStream.cpp
|
||||
libs/JSystem/src/JAudio2/JASBank.cpp
|
||||
libs/JSystem/src/JAudio2/JASBasicBank.cpp
|
||||
libs/JSystem/src/JAudio2/JASVoiceBank.cpp
|
||||
libs/JSystem/src/JAudio2/JASBasicInst.cpp
|
||||
libs/JSystem/src/JAudio2/JASDrumSet.cpp
|
||||
libs/JSystem/src/JAudio2/JASBasicWaveBank.cpp
|
||||
libs/JSystem/src/JAudio2/JASSimpleWaveBank.cpp
|
||||
libs/JSystem/src/JAudio2/JASWSParser.cpp
|
||||
libs/JSystem/src/JAudio2/JASBNKParser.cpp
|
||||
libs/JSystem/src/JAudio2/JASWaveArcLoader.cpp
|
||||
libs/JSystem/src/JAudio2/JASChannel.cpp
|
||||
libs/JSystem/src/JAudio2/JASLfo.cpp
|
||||
libs/JSystem/src/JAudio2/JASOscillator.cpp
|
||||
libs/JSystem/src/JAudio2/JASAiCtrl.cpp
|
||||
libs/JSystem/src/JAudio2/JASAudioThread.cpp
|
||||
libs/JSystem/src/JAudio2/JASAudioReseter.cpp
|
||||
libs/JSystem/src/JAudio2/JASDSPChannel.cpp
|
||||
libs/JSystem/src/JAudio2/JASDSPInterface.cpp
|
||||
libs/JSystem/src/JAudio2/JASDriverIF.cpp
|
||||
libs/JSystem/src/JAudio2/JASSoundParams.cpp
|
||||
libs/JSystem/src/JAudio2/dspproc.cpp
|
||||
libs/JSystem/src/JAudio2/dsptask.cpp
|
||||
libs/JSystem/src/JAudio2/osdsp.cpp
|
||||
libs/JSystem/src/JAudio2/osdsp_task.cpp
|
||||
libs/JSystem/src/JAudio2/JAIAudible.cpp
|
||||
libs/JSystem/src/JAudio2/JAIAudience.cpp
|
||||
libs/JSystem/src/JAudio2/JAISe.cpp
|
||||
libs/JSystem/src/JAudio2/JAISeMgr.cpp
|
||||
libs/JSystem/src/JAudio2/JAISeq.cpp
|
||||
libs/JSystem/src/JAudio2/JAISeqDataMgr.cpp
|
||||
libs/JSystem/src/JAudio2/JAISeqMgr.cpp
|
||||
libs/JSystem/src/JAudio2/JAISound.cpp
|
||||
libs/JSystem/src/JAudio2/JAISoundChild.cpp
|
||||
libs/JSystem/src/JAudio2/JAISoundHandles.cpp
|
||||
libs/JSystem/src/JAudio2/JAISoundInfo.cpp
|
||||
libs/JSystem/src/JAudio2/JAISoundParams.cpp
|
||||
libs/JSystem/src/JAudio2/JAISoundStarter.cpp
|
||||
libs/JSystem/src/JAudio2/JAIStream.cpp
|
||||
libs/JSystem/src/JAudio2/JAIStreamDataMgr.cpp
|
||||
libs/JSystem/src/JAudio2/JAIStreamMgr.cpp
|
||||
libs/JSystem/src/JAudio2/JAUAudioArcInterpreter.cpp
|
||||
libs/JSystem/src/JAudio2/JAUAudioArcLoader.cpp
|
||||
libs/JSystem/src/JAudio2/JAUAudioMgr.cpp
|
||||
libs/JSystem/src/JAudio2/JAUBankTable.cpp
|
||||
libs/JSystem/src/JAudio2/JAUClusterSound.cpp
|
||||
libs/JSystem/src/JAudio2/JAUInitializer.cpp
|
||||
libs/JSystem/src/JAudio2/JAUSectionHeap.cpp
|
||||
libs/JSystem/src/JAudio2/JAUSeqCollection.cpp
|
||||
libs/JSystem/src/JAudio2/JAUSeqDataBlockMgr.cpp
|
||||
libs/JSystem/src/JAudio2/JAUSoundAnimator.cpp
|
||||
libs/JSystem/src/JAudio2/JAUSoundTable.cpp
|
||||
libs/JSystem/src/JAudio2/JAUStreamFileTable.cpp
|
||||
libs/JSystem/src/JMessage/control.cpp
|
||||
libs/JSystem/src/JMessage/data.cpp
|
||||
libs/JSystem/src/JMessage/processor.cpp
|
||||
libs/JSystem/src/JMessage/resource.cpp
|
||||
libs/JSystem/src/JMessage/locale.cpp
|
||||
libs/JSystem/src/JGadget/binary.cpp
|
||||
libs/JSystem/src/JGadget/define.cpp
|
||||
libs/JSystem/src/JGadget/linklist.cpp
|
||||
libs/JSystem/src/JGadget/std-vector.cpp
|
||||
libs/JSystem/src/JHostIO/JORHostInfo.cpp
|
||||
libs/JSystem/src/JHostIO/JORServer.cpp
|
||||
libs/JSystem/src/JHostIO/JHIhioASync.cpp
|
||||
libs/JSystem/src/JHostIO/JHIRMcc.cpp
|
||||
libs/JSystem/src/JHostIO/JHIMccBuf.cpp
|
||||
)
|
||||
|
||||
set(JSYSTEM_FILES
|
||||
@@ -1333,7 +1333,7 @@ set(DUSK_FILES
|
||||
src/dusk/imgui/debug_overlay.cpp
|
||||
src/dusk/imgui/heaps.cpp
|
||||
src/dusk/offset_ptr.cpp
|
||||
src/dolphin/os/OSContext.cpp
|
||||
src/dolphin/os/OSThread.cpp
|
||||
src/dolphin/os/OSMutex.cpp
|
||||
src/dusk/OSContext.cpp
|
||||
src/dusk/OSThread.cpp
|
||||
src/dusk/OSMutex.cpp
|
||||
)
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// OSContext.cpp - PC implementation of GameCube OSContext API
|
||||
// Replaces PowerPC assembly context switching with minimal PC stubs.
|
||||
// On PC there is no register-level context save/restore; the OS handles
|
||||
// thread contexts natively via std::thread.
|
||||
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <dolphin/os.h>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// --- Current context pointer (per-process, not per-thread) ---
|
||||
static OSContext* sCurrentContext = nullptr;
|
||||
|
||||
OSContext* OSGetCurrentContext(void) {
|
||||
return sCurrentContext;
|
||||
}
|
||||
|
||||
void OSSetCurrentContext(OSContext* context) {
|
||||
sCurrentContext = context;
|
||||
}
|
||||
|
||||
void OSClearContext(OSContext* context) {
|
||||
if (!context) return;
|
||||
context->mode = 0;
|
||||
context->state = 0;
|
||||
}
|
||||
|
||||
void OSInitContext(OSContext* context, u32 pc, u32 newsp) {
|
||||
if (!context) return;
|
||||
memset(context, 0, sizeof(OSContext));
|
||||
context->srr0 = pc;
|
||||
context->gpr[1] = newsp;
|
||||
}
|
||||
|
||||
u32 OSSaveContext(OSContext* context) {
|
||||
// On PC we don't save PowerPC registers.
|
||||
// Return 0 = "context was just saved" (as opposed to 1 = "restored from save").
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OSLoadContext(OSContext* context) {
|
||||
// No-op on PC (no PowerPC register restore)
|
||||
}
|
||||
|
||||
void OSDumpContext(OSContext* context) {
|
||||
if (!context) {
|
||||
OSReport("[PC] OSDumpContext: NULL context\n");
|
||||
return;
|
||||
}
|
||||
OSReport("[PC] OSDumpContext: context at %p (no register info on PC)\n", context);
|
||||
}
|
||||
|
||||
void OSFillFPUContext(OSContext* context) {
|
||||
// No-op on PC (no PowerPC FPU state)
|
||||
}
|
||||
|
||||
void OSLoadFPUContext(OSContext* fpucontext) {
|
||||
// No-op on PC
|
||||
}
|
||||
|
||||
void OSSaveFPUContext(OSContext* fpucontext) {
|
||||
// No-op on PC
|
||||
}
|
||||
|
||||
u32 OSGetStackPointer(void) {
|
||||
// Return approximate stack pointer
|
||||
volatile u32 dummy;
|
||||
return (u32)(uintptr_t)&dummy;
|
||||
}
|
||||
|
||||
u32 OSSwitchStack(u32 newsp) {
|
||||
// Not meaningful on PC - return current sp
|
||||
return OSGetStackPointer();
|
||||
}
|
||||
|
||||
int OSSwitchFiber(u32 pc, u32 newsp) {
|
||||
// Not meaningful on PC
|
||||
OSReport("[PC] OSSwitchFiber: not supported on PC\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __OSContextInit(void) {
|
||||
// On GC this installs the FPU exception handler.
|
||||
// On PC nothing to do.
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,243 @@
|
||||
// OSMutex.cpp - PC implementation of GameCube OSMutex/OSCond API
|
||||
// Uses std::recursive_mutex and std::condition_variable_any behind the
|
||||
// unchanged GameCube C API. The OSMutex struct layout is preserved so
|
||||
// game code can read its fields.
|
||||
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <cstdlib>
|
||||
|
||||
// ============================================================================
|
||||
// Malloc-based allocator to bypass JKRHeap operator new/delete
|
||||
// Without this, side-table allocations call operator new -> JKRHeap::alloc
|
||||
// -> OSLockMutex -> GetMutexData -> operator new ... infinite recursion.
|
||||
// ============================================================================
|
||||
|
||||
template<typename T>
|
||||
struct MallocAllocator {
|
||||
using value_type = T;
|
||||
MallocAllocator() = default;
|
||||
template<typename U> MallocAllocator(const MallocAllocator<U>&) noexcept {}
|
||||
T* allocate(std::size_t n) {
|
||||
void* p = std::malloc(n * sizeof(T));
|
||||
if (!p) throw std::bad_alloc();
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
void deallocate(T* p, std::size_t) noexcept { std::free(p); }
|
||||
template<typename U> bool operator==(const MallocAllocator<U>&) const noexcept { return true; }
|
||||
template<typename U> bool operator!=(const MallocAllocator<U>&) const noexcept { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MallocDeleter {
|
||||
void operator()(T* p) const {
|
||||
p->~T();
|
||||
std::free(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
std::unique_ptr<T, MallocDeleter<T>> make_malloc_unique(Args&&... args) {
|
||||
void* mem = std::malloc(sizeof(T));
|
||||
if (!mem) throw std::bad_alloc();
|
||||
T* obj = new (mem) T(std::forward<Args>(args)...);
|
||||
return std::unique_ptr<T, MallocDeleter<T>>(obj);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Side-table: native mutex per OSMutex
|
||||
// ============================================================================
|
||||
|
||||
struct PCMutexData {
|
||||
std::recursive_mutex nativeMutex;
|
||||
};
|
||||
|
||||
template<typename K, typename V>
|
||||
using MallocMap = std::unordered_map<K, V, std::hash<K>, std::equal_to<K>,
|
||||
MallocAllocator<std::pair<const K, V>>>;
|
||||
|
||||
// Lazy-initialized to avoid DLL static init crashes
|
||||
static std::mutex& GetMutexMapMutex() {
|
||||
static std::mutex mtx;
|
||||
return mtx;
|
||||
}
|
||||
static MallocMap<OSMutex*, std::unique_ptr<PCMutexData, MallocDeleter<PCMutexData>>>& GetMutexMap() {
|
||||
static MallocMap<OSMutex*, std::unique_ptr<PCMutexData, MallocDeleter<PCMutexData>>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
static PCMutexData& GetMutexData(OSMutex* mutex) {
|
||||
std::lock_guard<std::mutex> lock(GetMutexMapMutex());
|
||||
auto& map = GetMutexMap();
|
||||
auto it = map.find(mutex);
|
||||
if (it == map.end()) {
|
||||
auto result = map.emplace(mutex, make_malloc_unique<PCMutexData>());
|
||||
return *result.first->second;
|
||||
}
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Side-table: native condition variable per OSCond
|
||||
// ============================================================================
|
||||
|
||||
struct PCCondData {
|
||||
std::condition_variable_any cv;
|
||||
};
|
||||
|
||||
// Lazy-initialized to avoid DLL static init crashes
|
||||
static std::mutex& GetCondMapMutex() {
|
||||
static std::mutex mtx;
|
||||
return mtx;
|
||||
}
|
||||
static MallocMap<OSCond*, std::unique_ptr<PCCondData, MallocDeleter<PCCondData>>>& GetCondMap() {
|
||||
static MallocMap<OSCond*, std::unique_ptr<PCCondData, MallocDeleter<PCCondData>>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
static PCCondData& GetCondData(OSCond* cond) {
|
||||
std::lock_guard<std::mutex> lock(GetCondMapMutex());
|
||||
auto& map = GetCondMap();
|
||||
auto it = map.find(cond);
|
||||
if (it == map.end()) {
|
||||
auto result = map.emplace(cond, make_malloc_unique<PCCondData>());
|
||||
return *result.first->second;
|
||||
}
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// C API functions
|
||||
// ============================================================================
|
||||
|
||||
extern "C" {
|
||||
|
||||
void OSInitMutex(OSMutex* mutex) {
|
||||
if (!mutex) return;
|
||||
OSInitThreadQueue(&mutex->queue);
|
||||
mutex->thread = nullptr;
|
||||
mutex->count = 0;
|
||||
|
||||
// Create/reset side-table entry
|
||||
GetMutexData(mutex);
|
||||
}
|
||||
|
||||
void OSLockMutex(OSMutex* mutex) {
|
||||
if (!mutex) return;
|
||||
|
||||
PCMutexData& data = GetMutexData(mutex);
|
||||
data.nativeMutex.lock();
|
||||
|
||||
// Update GC-visible fields
|
||||
OSThread* currentThread = OSGetCurrentThread();
|
||||
mutex->thread = currentThread;
|
||||
mutex->count++;
|
||||
}
|
||||
|
||||
void OSUnlockMutex(OSMutex* mutex) {
|
||||
if (!mutex) return;
|
||||
|
||||
OSThread* currentThread = OSGetCurrentThread();
|
||||
if (mutex->thread != currentThread) return;
|
||||
|
||||
mutex->count--;
|
||||
if (mutex->count == 0) {
|
||||
mutex->thread = nullptr;
|
||||
}
|
||||
|
||||
PCMutexData& data = GetMutexData(mutex);
|
||||
data.nativeMutex.unlock();
|
||||
}
|
||||
|
||||
BOOL OSTryLockMutex(OSMutex* mutex) {
|
||||
if (!mutex) return FALSE;
|
||||
|
||||
PCMutexData& data = GetMutexData(mutex);
|
||||
if (data.nativeMutex.try_lock()) {
|
||||
OSThread* currentThread = OSGetCurrentThread();
|
||||
mutex->thread = currentThread;
|
||||
mutex->count++;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Internal: unlock all mutexes held by a thread (called on thread exit)
|
||||
// ============================================================================
|
||||
|
||||
void __OSUnlockAllMutex(OSThread* thread) {
|
||||
// On GC this walks the thread's mutex queue.
|
||||
// On PC the native mutexes are cleaned up when threads exit.
|
||||
// Clear the GC-visible queue.
|
||||
if (!thread) return;
|
||||
thread->queueMutex.head = nullptr;
|
||||
thread->queueMutex.tail = nullptr;
|
||||
}
|
||||
|
||||
int __OSCheckDeadLock(OSThread* thread) {
|
||||
// Simplified: native OS handles deadlock detection.
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __OSCheckMutexes(OSThread* thread) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Condition Variable API
|
||||
// ============================================================================
|
||||
|
||||
void OSInitCond(OSCond* cond) {
|
||||
if (!cond) return;
|
||||
OSInitThreadQueue(&cond->queue);
|
||||
GetCondData(cond);
|
||||
}
|
||||
|
||||
void OSWaitCond(OSCond* cond, OSMutex* mutex) {
|
||||
if (!cond || !mutex) return;
|
||||
|
||||
PCCondData& condData = GetCondData(cond);
|
||||
PCMutexData& mutexData = GetMutexData(mutex);
|
||||
|
||||
// Save and clear the GC mutex state
|
||||
OSThread* currentThread = OSGetCurrentThread();
|
||||
s32 savedCount = mutex->count;
|
||||
mutex->count = 0;
|
||||
mutex->thread = nullptr;
|
||||
|
||||
// Unlock the recursive mutex the same number of times it was locked
|
||||
for (s32 i = 0; i < savedCount; i++) {
|
||||
mutexData.nativeMutex.unlock();
|
||||
}
|
||||
|
||||
// Wait on the condition variable
|
||||
{
|
||||
std::unique_lock<std::recursive_mutex> lock(mutexData.nativeMutex);
|
||||
condData.cv.wait(lock);
|
||||
}
|
||||
|
||||
// Re-lock the recursive mutex the same number of times
|
||||
for (s32 i = 0; i < savedCount; i++) {
|
||||
mutexData.nativeMutex.lock();
|
||||
}
|
||||
|
||||
// Restore GC mutex state
|
||||
mutex->thread = currentThread;
|
||||
mutex->count = savedCount;
|
||||
}
|
||||
|
||||
void OSSignalCond(OSCond* cond) {
|
||||
if (!cond) return;
|
||||
PCCondData& condData = GetCondData(cond);
|
||||
condData.cv.notify_all();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,747 @@
|
||||
// OSThread.cpp - PC implementation of GameCube OSThread API
|
||||
// Maps GameCube cooperative threading to native OS threads via std::thread.
|
||||
// The OSThread struct layout is preserved so game code can read its fields.
|
||||
// A side-table stores the native std::thread and synchronization primitives.
|
||||
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <unordered_map>
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
// ============================================================================
|
||||
// Malloc-based allocator to bypass JKRHeap operator new/delete
|
||||
// ============================================================================
|
||||
|
||||
template<typename T>
|
||||
struct MallocAllocator {
|
||||
using value_type = T;
|
||||
MallocAllocator() = default;
|
||||
template<typename U> MallocAllocator(const MallocAllocator<U>&) noexcept {}
|
||||
T* allocate(std::size_t n) {
|
||||
void* p = std::malloc(n * sizeof(T));
|
||||
if (!p) throw std::bad_alloc();
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
void deallocate(T* p, std::size_t) noexcept { std::free(p); }
|
||||
template<typename U> bool operator==(const MallocAllocator<U>&) const noexcept { return true; }
|
||||
template<typename U> bool operator!=(const MallocAllocator<U>&) const noexcept { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MallocDeleter {
|
||||
void operator()(T* p) const {
|
||||
p->~T();
|
||||
std::free(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
std::unique_ptr<T, MallocDeleter<T>> make_malloc_unique(Args&&... args) {
|
||||
void* mem = std::malloc(sizeof(T));
|
||||
if (!mem) throw std::bad_alloc();
|
||||
T* obj = new (mem) T(std::forward<Args>(args)...);
|
||||
return std::unique_ptr<T, MallocDeleter<T>>(obj);
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
using MallocMap = std::unordered_map<K, V, std::hash<K>, std::equal_to<K>,
|
||||
MallocAllocator<std::pair<const K, V>>>;
|
||||
|
||||
// ============================================================================
|
||||
// Side-table: native thread data per OSThread
|
||||
// ============================================================================
|
||||
|
||||
struct PCThreadData {
|
||||
std::thread nativeThread;
|
||||
std::mutex mtx;
|
||||
std::condition_variable cv;
|
||||
void* (*func)(void*);
|
||||
void* param;
|
||||
bool started = false;
|
||||
bool suspended = false;
|
||||
};
|
||||
|
||||
// Lazy-initialized to avoid DLL static init crashes (used before DllMain completes)
|
||||
static std::mutex& GetThreadDataMutex() {
|
||||
static std::mutex mtx;
|
||||
return mtx;
|
||||
}
|
||||
static MallocMap<OSThread*, std::unique_ptr<PCThreadData, MallocDeleter<PCThreadData>>>& GetThreadDataMap() {
|
||||
static MallocMap<OSThread*, std::unique_ptr<PCThreadData, MallocDeleter<PCThreadData>>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
// Side-table for OSThreadQueue -> condition_variable (for OSSleepThread/OSWakeupThread)
|
||||
static std::mutex& GetQueueCvMutex() {
|
||||
static std::mutex mtx;
|
||||
return mtx;
|
||||
}
|
||||
static MallocMap<OSThreadQueue*, std::unique_ptr<std::condition_variable, MallocDeleter<std::condition_variable>>>& GetQueueCvMap() {
|
||||
static MallocMap<OSThreadQueue*, std::unique_ptr<std::condition_variable, MallocDeleter<std::condition_variable>>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
static std::condition_variable& GetQueueCV(OSThreadQueue* queue) {
|
||||
std::lock_guard<std::mutex> lock(GetQueueCvMutex());
|
||||
auto& map = GetQueueCvMap();
|
||||
auto it = map.find(queue);
|
||||
if (it == map.end()) {
|
||||
auto result = map.emplace(queue, make_malloc_unique<std::condition_variable>());
|
||||
return *result.first->second;
|
||||
}
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Thread-local current thread pointer
|
||||
// ============================================================================
|
||||
|
||||
static thread_local OSThread* tls_currentThread = nullptr;
|
||||
|
||||
// ============================================================================
|
||||
// Global state
|
||||
// ============================================================================
|
||||
|
||||
static OSThread sDefaultThread;
|
||||
static u8 sDefaultStack[64 * 1024];
|
||||
static u32 sDefaultStackEnd = OS_THREAD_STACK_MAGIC;
|
||||
|
||||
OSThreadQueue __OSActiveThreadQueue;
|
||||
|
||||
// Global interrupt mutex (coarse-grained lock replacing interrupt disable)
|
||||
// Lazy-initialized to avoid DLL static init crashes
|
||||
static std::recursive_mutex& GetInterruptMutex() {
|
||||
static std::recursive_mutex mtx;
|
||||
return mtx;
|
||||
}
|
||||
static thread_local int sInterruptLockCount = 0;
|
||||
|
||||
// Scheduler suspend count
|
||||
static std::atomic<s32> sSchedulerSuspendCount{0};
|
||||
|
||||
// Active thread count
|
||||
static std::atomic<s32> sActiveThreadCount{0};
|
||||
|
||||
// Switch thread callback
|
||||
static OSSwitchThreadCallback sSwitchThreadCallback = nullptr;
|
||||
|
||||
// ============================================================================
|
||||
// Internal helpers
|
||||
// ============================================================================
|
||||
|
||||
// Linked list macros for the active thread queue
|
||||
static void EnqueueActive(OSThread* thread) {
|
||||
OSThread* prev = __OSActiveThreadQueue.tail;
|
||||
if (prev == nullptr) {
|
||||
__OSActiveThreadQueue.head = thread;
|
||||
} else {
|
||||
prev->linkActive.next = thread;
|
||||
}
|
||||
thread->linkActive.prev = prev;
|
||||
thread->linkActive.next = nullptr;
|
||||
__OSActiveThreadQueue.tail = thread;
|
||||
}
|
||||
|
||||
static void DequeueActive(OSThread* thread) {
|
||||
OSThread* next = thread->linkActive.next;
|
||||
OSThread* prev = thread->linkActive.prev;
|
||||
if (next == nullptr) {
|
||||
__OSActiveThreadQueue.tail = prev;
|
||||
} else {
|
||||
next->linkActive.prev = prev;
|
||||
}
|
||||
if (prev == nullptr) {
|
||||
__OSActiveThreadQueue.head = next;
|
||||
} else {
|
||||
prev->linkActive.next = next;
|
||||
}
|
||||
thread->linkActive.next = nullptr;
|
||||
thread->linkActive.prev = nullptr;
|
||||
}
|
||||
|
||||
// Thread entry wrapper - runs on the new std::thread
|
||||
static void ThreadEntryWrapper(OSThread* thread, PCThreadData* data) {
|
||||
// Set thread-local pointer
|
||||
tls_currentThread = thread;
|
||||
|
||||
// Set context pointers for this thread
|
||||
OSClearContext(&thread->context);
|
||||
OSSetCurrentContext(&thread->context);
|
||||
|
||||
thread->state = OS_THREAD_STATE_RUNNING;
|
||||
|
||||
// Call the actual thread function
|
||||
void* result = data->func(data->param);
|
||||
|
||||
// Thread returned - equivalent to OSExitThread
|
||||
thread->val = result;
|
||||
thread->state = OS_THREAD_STATE_MORIBUND;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// C API functions
|
||||
// ============================================================================
|
||||
|
||||
extern "C" {
|
||||
|
||||
void __OSThreadInit(void) {
|
||||
memset(&sDefaultThread, 0, sizeof(OSThread));
|
||||
|
||||
sDefaultThread.state = OS_THREAD_STATE_RUNNING;
|
||||
sDefaultThread.attr = OS_THREAD_ATTR_DETACH;
|
||||
sDefaultThread.priority = 16;
|
||||
sDefaultThread.base = 16;
|
||||
sDefaultThread.suspend = 0;
|
||||
sDefaultThread.val = (void*)(intptr_t)-1;
|
||||
sDefaultThread.mutex = nullptr;
|
||||
sDefaultThread.queue = nullptr;
|
||||
|
||||
OSInitThreadQueue(&sDefaultThread.queueJoin);
|
||||
sDefaultThread.queueMutex.head = sDefaultThread.queueMutex.tail = nullptr;
|
||||
sDefaultThread.link.next = sDefaultThread.link.prev = nullptr;
|
||||
sDefaultThread.linkActive.next = sDefaultThread.linkActive.prev = nullptr;
|
||||
|
||||
// Stack pointers (JKRThread reads these)
|
||||
sDefaultThread.stackBase = sDefaultStack + sizeof(sDefaultStack);
|
||||
sDefaultThread.stackEnd = &sDefaultStackEnd;
|
||||
sDefaultStackEnd = OS_THREAD_STACK_MAGIC;
|
||||
|
||||
OSClearContext(&sDefaultThread.context);
|
||||
|
||||
sDefaultThread.error = 0;
|
||||
sDefaultThread.specific[0] = nullptr;
|
||||
sDefaultThread.specific[1] = nullptr;
|
||||
|
||||
// Set as current thread for main thread
|
||||
tls_currentThread = &sDefaultThread;
|
||||
|
||||
// Active queue
|
||||
OSInitThreadQueue(&__OSActiveThreadQueue);
|
||||
EnqueueActive(&sDefaultThread);
|
||||
sActiveThreadCount = 1;
|
||||
|
||||
OSReport("[PC-OSThread] Thread system initialized (multi-threaded mode)\n");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Thread Queue
|
||||
// ============================================================================
|
||||
|
||||
void OSInitThreadQueue(OSThreadQueue* queue) {
|
||||
if (queue) {
|
||||
queue->head = queue->tail = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Current Thread
|
||||
// ============================================================================
|
||||
|
||||
OSThread* OSGetCurrentThread(void) {
|
||||
// Lazy-init for main thread if __OSThreadInit hasn't been called yet
|
||||
if (tls_currentThread == nullptr) {
|
||||
__OSThreadInit();
|
||||
}
|
||||
return tls_currentThread;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Thread Creation
|
||||
// ============================================================================
|
||||
|
||||
int OSCreateThread(OSThread* thread, void* (*func)(void*), void* param,
|
||||
void* stack, u32 stackSize, OSPriority priority, u16 attr) {
|
||||
if (!thread) return 0;
|
||||
if (priority < OS_PRIORITY_MIN || priority > OS_PRIORITY_MAX) return 0;
|
||||
|
||||
// Ensure thread system is initialized
|
||||
OSGetCurrentThread();
|
||||
|
||||
memset(thread, 0, sizeof(OSThread));
|
||||
|
||||
thread->state = OS_THREAD_STATE_READY;
|
||||
thread->attr = attr & 1u;
|
||||
thread->base = priority;
|
||||
thread->priority = priority;
|
||||
thread->suspend = 1; // Created suspended (GC behavior)
|
||||
thread->val = (void*)(intptr_t)-1;
|
||||
thread->mutex = nullptr;
|
||||
|
||||
OSInitThreadQueue(&thread->queueJoin);
|
||||
thread->queueMutex.head = thread->queueMutex.tail = nullptr;
|
||||
thread->link.next = thread->link.prev = nullptr;
|
||||
thread->linkActive.next = thread->linkActive.prev = nullptr;
|
||||
|
||||
// Stack (stack points to TOP on GameCube)
|
||||
thread->stackBase = (u8*)stack;
|
||||
thread->stackEnd = (u32*)((uintptr_t)stack - stackSize);
|
||||
*thread->stackEnd = OS_THREAD_STACK_MAGIC;
|
||||
|
||||
OSClearContext(&thread->context);
|
||||
|
||||
thread->error = 0;
|
||||
thread->specific[0] = nullptr;
|
||||
thread->specific[1] = nullptr;
|
||||
|
||||
// Create side-table entry (but don't start the thread yet)
|
||||
{
|
||||
auto data = make_malloc_unique<PCThreadData>();
|
||||
data->func = func;
|
||||
data->param = param;
|
||||
|
||||
std::lock_guard<std::mutex> lock(GetThreadDataMutex());
|
||||
GetThreadDataMap()[thread] = std::move(data);
|
||||
}
|
||||
|
||||
// Add to active queue
|
||||
EnqueueActive(thread);
|
||||
sActiveThreadCount++;
|
||||
|
||||
OSReport("[PC-OSThread] Created thread %p (priority=%d, stackSize=%u)\n",
|
||||
thread, priority, stackSize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Resume / Suspend
|
||||
// ============================================================================
|
||||
/*
|
||||
s32 OSResumeThread(OSThread* thread) {
|
||||
if (!thread) return 0;
|
||||
|
||||
s32 prevSuspend = thread->suspend;
|
||||
if (thread->suspend > 0) {
|
||||
thread->suspend--;
|
||||
}
|
||||
|
||||
if (thread->suspend == 0) {
|
||||
std::lock_guard<std::mutex> lock(GetThreadDataMutex());
|
||||
auto it = GetThreadDataMap().find(thread);
|
||||
if (it != GetThreadDataMap().end()) {
|
||||
PCThreadData* data = it->second.get();
|
||||
if (!data->started) {
|
||||
// First resume: launch the native thread
|
||||
data->started = true;
|
||||
data->suspended = false;
|
||||
data->nativeThread = std::thread(ThreadEntryWrapper, thread, data);
|
||||
data->nativeThread.detach();
|
||||
OSReport("[PC-OSThread] Started thread %p\n", thread);
|
||||
} else if (data->suspended) {
|
||||
// Resume from suspension: signal the CV
|
||||
data->suspended = false;
|
||||
data->cv.notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return prevSuspend;
|
||||
}
|
||||
|
||||
s32 OSSuspendThread(OSThread* thread) {
|
||||
if (!thread) return 0;
|
||||
|
||||
s32 prevSuspend = thread->suspend;
|
||||
thread->suspend++;
|
||||
|
||||
if (prevSuspend == 0) {
|
||||
std::lock_guard<std::mutex> lock(GetThreadDataMutex());
|
||||
auto it = GetThreadDataMap().find(thread);
|
||||
if (it != GetThreadDataMap().end()) {
|
||||
PCThreadData* data = it->second.get();
|
||||
if (data->started) {
|
||||
data->suspended = true;
|
||||
// The thread must check its suspended flag and wait
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return prevSuspend;
|
||||
}
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// Resume / Suspend
|
||||
// ============================================================================
|
||||
|
||||
s32 OSResumeThread(OSThread* thread) {
|
||||
if (!thread)
|
||||
return 0;
|
||||
|
||||
s32 prevSuspend = thread->suspend;
|
||||
if (thread->suspend > 0) {
|
||||
thread->suspend--;
|
||||
}
|
||||
|
||||
// Only wake up if suspend count drops to 0
|
||||
if (thread->suspend == 0) {
|
||||
PCThreadData* data = nullptr;
|
||||
|
||||
// Lock the global map to safely retrieve our thread data pointer
|
||||
{
|
||||
std::lock_guard<std::mutex> mapLock(GetThreadDataMutex());
|
||||
auto it = GetThreadDataMap().find(thread);
|
||||
if (it != GetThreadDataMap().end()) {
|
||||
data = it->second.get();
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
// Lock the specific thread mutex to safely modify state and notify
|
||||
std::unique_lock<std::mutex> threadLock(data->mtx);
|
||||
|
||||
if (!data->started) {
|
||||
// First resume: launch the native thread
|
||||
data->started = true;
|
||||
data->suspended = false;
|
||||
|
||||
// Unlock before launching to avoid potential deadlocks in thread initialization
|
||||
threadLock.unlock();
|
||||
|
||||
data->nativeThread = std::thread(ThreadEntryWrapper, thread, data);
|
||||
data->nativeThread.detach();
|
||||
OSReport("[PC-OSThread] Started thread %p\n", thread);
|
||||
} else {
|
||||
// Resume from suspension: signal the condition variable
|
||||
// IMPORTANT: Set suspended to false BEFORE notifying to pass the wait predicate
|
||||
data->suspended = false;
|
||||
data->cv.notify_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return prevSuspend;
|
||||
}
|
||||
|
||||
s32 OSSuspendThread(OSThread* thread) {
|
||||
if (!thread)
|
||||
return 0;
|
||||
|
||||
s32 prevSuspend = thread->suspend;
|
||||
thread->suspend++;
|
||||
|
||||
// If transitioning from running (0) to suspended (1)
|
||||
if (prevSuspend == 0) {
|
||||
PCThreadData* data = nullptr;
|
||||
|
||||
// Lock the global map to find our thread data
|
||||
{
|
||||
std::lock_guard<std::mutex> mapLock(GetThreadDataMutex());
|
||||
auto it = GetThreadDataMap().find(thread);
|
||||
if (it != GetThreadDataMap().end()) {
|
||||
data = it->second.get();
|
||||
}
|
||||
}
|
||||
|
||||
if (data && data->started) {
|
||||
std::unique_lock<std::mutex> threadLock(data->mtx);
|
||||
data->suspended = true;
|
||||
|
||||
// FIX: If the thread is suspending ITSELF, we must block execution here.
|
||||
// This replicates the GameCube behavior where OSSuspendThread yields the CPU
|
||||
// immediately.
|
||||
if (thread == OSGetCurrentThread()) {
|
||||
// Block until 'suspended' becomes false (set by OSResumeThread)
|
||||
// The predicate protects against spurious wakeups.
|
||||
data->cv.wait(threadLock, [data] { return !data->suspended; });
|
||||
} else {
|
||||
// NOTE: Suspending *other* threads is difficult in C++ std::thread
|
||||
// without cooperative checkpoints or platform-specific hacks.
|
||||
// For now, we only set the flag. The target thread would need to check 'suspended'
|
||||
// periodically.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return prevSuspend;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Sleep / Wakeup (thread queue based)
|
||||
// ============================================================================
|
||||
|
||||
void OSSleepThread(OSThreadQueue* queue) {
|
||||
if (!queue) return;
|
||||
|
||||
OSThread* currentThread = OSGetCurrentThread();
|
||||
if (!currentThread) return;
|
||||
|
||||
currentThread->state = OS_THREAD_STATE_WAITING;
|
||||
currentThread->queue = queue;
|
||||
|
||||
// Enqueue into the thread queue
|
||||
OSThread* prev = queue->tail;
|
||||
if (prev == nullptr) {
|
||||
queue->head = currentThread;
|
||||
} else {
|
||||
prev->link.next = currentThread;
|
||||
}
|
||||
currentThread->link.prev = prev;
|
||||
currentThread->link.next = nullptr;
|
||||
queue->tail = currentThread;
|
||||
|
||||
// Wait on the condition variable for this queue
|
||||
std::condition_variable& cv = GetQueueCV(queue);
|
||||
std::unique_lock<std::mutex> lock(GetQueueCvMutex());
|
||||
cv.wait(lock, [currentThread]() {
|
||||
return currentThread->state != OS_THREAD_STATE_WAITING;
|
||||
});
|
||||
}
|
||||
|
||||
void OSWakeupThread(OSThreadQueue* queue) {
|
||||
if (!queue) return;
|
||||
|
||||
// Wake all threads in the queue
|
||||
OSThread* thread = queue->head;
|
||||
while (thread) {
|
||||
OSThread* next = thread->link.next;
|
||||
thread->state = OS_THREAD_STATE_READY;
|
||||
thread->link.next = nullptr;
|
||||
thread->link.prev = nullptr;
|
||||
thread->queue = nullptr;
|
||||
thread = next;
|
||||
}
|
||||
queue->head = queue->tail = nullptr;
|
||||
|
||||
// Notify all waiters
|
||||
std::condition_variable& cv = GetQueueCV(queue);
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Exit / Cancel / Detach / Join
|
||||
// ============================================================================
|
||||
|
||||
void OSExitThread(void* val) {
|
||||
OSThread* currentThread = OSGetCurrentThread();
|
||||
if (!currentThread) return;
|
||||
|
||||
currentThread->val = val;
|
||||
|
||||
if (currentThread->attr & OS_THREAD_ATTR_DETACH) {
|
||||
DequeueActive(currentThread);
|
||||
currentThread->state = 0;
|
||||
} else {
|
||||
currentThread->state = OS_THREAD_STATE_MORIBUND;
|
||||
}
|
||||
|
||||
// Wake anyone waiting to join
|
||||
OSWakeupThread(¤tThread->queueJoin);
|
||||
sActiveThreadCount--;
|
||||
}
|
||||
|
||||
void OSCancelThread(OSThread* thread) {
|
||||
if (!thread) return;
|
||||
|
||||
if (thread->attr & OS_THREAD_ATTR_DETACH) {
|
||||
DequeueActive(thread);
|
||||
thread->state = 0;
|
||||
} else {
|
||||
thread->state = OS_THREAD_STATE_MORIBUND;
|
||||
}
|
||||
|
||||
OSWakeupThread(&thread->queueJoin);
|
||||
sActiveThreadCount--;
|
||||
}
|
||||
|
||||
void OSDetachThread(OSThread* thread) {
|
||||
if (!thread) return;
|
||||
thread->attr |= OS_THREAD_ATTR_DETACH;
|
||||
|
||||
if (thread->state == OS_THREAD_STATE_MORIBUND) {
|
||||
DequeueActive(thread);
|
||||
thread->state = 0;
|
||||
}
|
||||
OSWakeupThread(&thread->queueJoin);
|
||||
}
|
||||
|
||||
int OSJoinThread(OSThread* thread, void* val) {
|
||||
if (!thread) return 0;
|
||||
|
||||
if (!(thread->attr & OS_THREAD_ATTR_DETACH) &&
|
||||
thread->state != OS_THREAD_STATE_MORIBUND &&
|
||||
thread->queueJoin.head == nullptr) {
|
||||
OSSleepThread(&thread->queueJoin);
|
||||
}
|
||||
|
||||
if (thread->state == OS_THREAD_STATE_MORIBUND) {
|
||||
if (val) {
|
||||
*(s32*)val = (s32)(intptr_t)thread->val;
|
||||
}
|
||||
DequeueActive(thread);
|
||||
thread->state = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Yield / Terminated / Active
|
||||
// ============================================================================
|
||||
|
||||
void OSYieldThread(void) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
BOOL OSIsThreadSuspended(OSThread* thread) {
|
||||
return (thread && thread->suspend > 0) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
BOOL OSIsThreadTerminated(OSThread* thread) {
|
||||
if (!thread) return TRUE;
|
||||
return (thread->state == OS_THREAD_STATE_MORIBUND || thread->state == 0) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
s32 OSCheckActiveThreads(void) {
|
||||
return sActiveThreadCount.load();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Priority
|
||||
// ============================================================================
|
||||
|
||||
int OSSetThreadPriority(OSThread* thread, OSPriority priority) {
|
||||
if (!thread) return 0;
|
||||
if (priority < OS_PRIORITY_MIN || priority > OS_PRIORITY_MAX) return 0;
|
||||
thread->base = priority;
|
||||
thread->priority = priority;
|
||||
return 1;
|
||||
}
|
||||
|
||||
s32 OSGetThreadPriority(OSThread* thread) {
|
||||
if (!thread) return 16;
|
||||
return thread->base;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Switch Thread Callback
|
||||
// ============================================================================
|
||||
|
||||
OSSwitchThreadCallback OSSetSwitchThreadCallback(OSSwitchThreadCallback callback) {
|
||||
OSSwitchThreadCallback prev = sSwitchThreadCallback;
|
||||
sSwitchThreadCallback = callback;
|
||||
return prev;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Scheduler (atomic counter, no real effect with native OS threads)
|
||||
// ============================================================================
|
||||
|
||||
s32 OSDisableScheduler(void) {
|
||||
return sSchedulerSuspendCount.fetch_add(1);
|
||||
}
|
||||
|
||||
s32 OSEnableScheduler(void) {
|
||||
return sSchedulerSuspendCount.fetch_sub(1);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Interrupts (global recursive mutex for mutual exclusion)
|
||||
// ============================================================================
|
||||
|
||||
BOOL OSDisableInterrupts(void) {
|
||||
GetInterruptMutex().lock();
|
||||
sInterruptLockCount++;
|
||||
return (BOOL)(sInterruptLockCount > 1); // TRUE if was already locked
|
||||
}
|
||||
|
||||
BOOL OSRestoreInterrupts(BOOL level) {
|
||||
if (sInterruptLockCount > 0) {
|
||||
sInterruptLockCount--;
|
||||
GetInterruptMutex().unlock();
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
BOOL OSEnableInterrupts(void) {
|
||||
if (sInterruptLockCount > 0) {
|
||||
sInterruptLockCount--;
|
||||
GetInterruptMutex().unlock();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Idle function (stub on PC)
|
||||
// ============================================================================
|
||||
|
||||
OSThread* OSSetIdleFunction(OSIdleFunction idleFunction, void* param, void* stack, u32 stackSize) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OSThread* OSGetIdleFunction(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Thread-specific storage
|
||||
// ============================================================================
|
||||
|
||||
void OSSetThreadSpecific(s32 index, void* ptr) {
|
||||
OSThread* thread = OSGetCurrentThread();
|
||||
if (thread && index >= 0 && index < OS_THREAD_SPECIFIC_MAX) {
|
||||
thread->specific[index] = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void* OSGetThreadSpecific(s32 index) {
|
||||
OSThread* thread = OSGetCurrentThread();
|
||||
if (thread && index >= 0 && index < OS_THREAD_SPECIFIC_MAX) {
|
||||
return thread->specific[index];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Clear stack (minimal implementation)
|
||||
// ============================================================================
|
||||
|
||||
void OSClearStack(u8 val) {
|
||||
// On PC we don't clear the stack - it's managed by the OS
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Internal functions used by OSMutex
|
||||
// ============================================================================
|
||||
|
||||
s32 __OSGetEffectivePriority(OSThread* thread) {
|
||||
// On PC with native threads, priority inversion handling is simplified.
|
||||
// Just return the base priority.
|
||||
return thread ? thread->base : 16;
|
||||
}
|
||||
|
||||
void __OSPromoteThread(OSThread* thread, s32 priority) {
|
||||
// Simplified: no real priority inheritance on PC
|
||||
if (thread && priority < thread->priority) {
|
||||
thread->priority = priority;
|
||||
}
|
||||
}
|
||||
|
||||
void __OSReschedule(void) {
|
||||
// With native OS threads, rescheduling is handled by the OS.
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Interrupt handler registration (stub)
|
||||
// ============================================================================
|
||||
|
||||
__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt,
|
||||
__OSInterruptHandler handler) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask mask) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user