From 344348bc0508cc132b77bfb81404bfdb99ae3fcf Mon Sep 17 00:00:00 2001 From: elijah-thomas774 Date: Sun, 5 May 2024 22:27:50 -0400 Subject: [PATCH] nw4r ut almost matching --- config/SOUE01/config.yml | 2 + config/SOUE01/splits.txt | 24 +- config/SOUE01/symbols.txt | 269 ++++++------ configure.py | 17 +- include/MSL_C/MSL_Common/Src/ansi_files.h | 25 +- include/nw4r/ut/ut_CharWriter.h | 1 + include/nw4r/ut/ut_DvdFileStream.h | 18 +- include/nw4r/ut/ut_DvdLockedFileStream.h | 23 +- include/nw4r/ut/ut_Font.h | 5 +- include/nw4r/ut/ut_IOStream.h | 6 +- include/nw4r/ut/ut_NandFileStream.h | 30 +- include/nw4r/ut/ut_ResFont.h | 5 +- include/nw4r/ut/ut_ResFontBase.h | 49 ++- include/nw4r/ut/ut_RomFont.h | 3 +- include/nw4r/ut/ut_TextWriterBase.h | 51 ++- include/rvl/DVD.h | 3 + include/rvl/DVD/dvd.h | 101 ++++- include/rvl/DVD/dvd_broadway.h | 28 +- include/rvl/DVD/dvderror.h | 38 ++ include/rvl/DVD/dvdfs.h | 36 +- include/rvl/DVD/dvdidutils.h | 14 +- include/rvl/DVD/dvdqueue.h | 28 ++ include/rvl/GX/GXInit.h | 13 +- include/rvl/GX/GXPixel.h | 2 +- include/rvl/GX/GXTransform.h | 2 +- include/rvl/GX/GXTypes.h | 113 +++-- include/rvl/NAND/nand.h | 9 +- src/egg/core/eggAsyncDisplay.cpp | 4 +- src/nw4r/ut/ut_CharWriter.cpp | 260 ++++++++++++ src/nw4r/ut/ut_DvdFileStream.cpp | 180 ++++++++ src/nw4r/ut/ut_DvdLockedFileStream.cpp | 93 ++++ src/nw4r/ut/ut_Font.cpp | 25 ++ src/nw4r/ut/ut_IOStream.cpp | 2 +- src/nw4r/ut/ut_LockedCache.cpp | 104 +++++ src/nw4r/ut/ut_NandFileStream.cpp | 178 ++++++++ src/nw4r/ut/ut_ResFont.cpp | 121 ++++++ src/nw4r/ut/ut_ResFontBase.cpp | 221 ++++++++++ src/nw4r/ut/ut_RomFont.cpp | 226 ++++++++++ src/nw4r/ut/ut_TextWriterBase.cpp | 494 ++++++++++++++++++++++ 39 files changed, 2477 insertions(+), 346 deletions(-) create mode 100644 include/rvl/DVD/dvderror.h create mode 100644 include/rvl/DVD/dvdqueue.h create mode 100644 src/nw4r/ut/ut_RomFont.cpp diff --git a/config/SOUE01/config.yml b/config/SOUE01/config.yml index 6b77249c..3615db70 100644 --- a/config/SOUE01/config.yml +++ b/config/SOUE01/config.yml @@ -10,6 +10,8 @@ force_active: [ "ProcessTab__Q34nw4r2ut19TagProcessorBaseFPQ34nw4r2ut15PrintContext", "ProcessLinefeed__Q34nw4r2ut19TagProcessorBaseFPQ34nw4r2ut15PrintContext", "ProcessTab__Q34nw4r2ut19TagProcessorBaseFPQ34nw4r2ut15PrintContext", + # "RemoveResourceBuffer__Q44nw4r2ut6detail11ResFontBaseFv", + "RemoveResource__Q34nw4r2ut7ResFontFv", ] # modules: # - object: orig/SOUE01/rels/d_a_asura_bulletNP.rel diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index 4973c05f..b30c84e6 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -253,34 +253,56 @@ nw4r/ut/ut_FileStream.cpp: nw4r/ut/ut_DvdFileStream.cpp: .text start:0x8042B6F0 end:0x8042BDAC .ctors start:0x804DB940 end:0x804DB944 + .data start:0x8056BD78 end:0x8056BDE0 + .sbss start:0x805765A0 end:0x805765A8 nw4r/ut/ut_DvdLockedFileStream.cpp: .text start:0x8042BDB0 end:0x8042C1DC .ctors start:0x804DB944 end:0x804DB948 + .data start:0x8056BDE0 end:0x8056BE48 + .sbss start:0x805765A8 end:0x805765C0 + .bss start:0x80636B20 end:0x80636B38 nw4r/ut/ut_NandFileStream.cpp: .text start:0x8042C1E0 end:0x8042CA4C .ctors start:0x804DB948 end:0x804DB94C + .data start:0x8056BE48 end:0x8056BEA8 + .sbss start:0x805765C0 end:0x805765C8 nw4r/ut/ut_LockedCache.cpp: .text start:0x8042CA50 end:0x8042CC28 .ctors start:0x804DB94C end:0x804DB950 + .bss start:0x80636B38 end:0x80636B58 nw4r/ut/ut_Font.cpp: - .text start:0x8042CC30 end:0x8042CD20 + .text start:0x8042CC30 end:0x8042CCD4 + .data start:0x8056BEA8 end:0x8056BED8 + +nw4r/ut/ut_RomFont.cpp: + .text start:0x8042CCE0 end:0x8042CD20 + .data start:0x8056BED8 end:0x8056BF38 nw4r/ut/ut_ResFontBase.cpp: .text start:0x8042CD20 end:0x8042D4B8 + .data start:0x8056BF38 end:0x8056BFA0 nw4r/ut/ut_ResFont.cpp: .text start:0x8042D4C0 end:0x8042D7CC + .data start:0x8056BFA0 end:0x8056C000 nw4r/ut/ut_CharWriter.cpp: .text start:0x8042D7D0 end:0x8042EF1C + .sbss start:0x805765C8 end:0x805765D0 + .sdata2 start:0x8057EB70 end:0x8057EB90 + .bss start:0x80636B58 end:0x80636B68 nw4r/ut/ut_TextWriterBase.cpp: .text start:0x8042EF20 end:0x80434294 .ctors start:0x804DB950 end:0x804DB954 + .sdata start:0x80574DC0 end:0x80574DC8 + .sbss start:0x805765D0 end:0x805765E8 + .sdata2 start:0x8057EB90 end:0x8057EBA8 + .bss start:0x80636B68 end:0x80636B80 nw4r/db/db_directPrint.cpp: .text start:0x804342A0 end:0x80434E9C diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index f3114665..c0fbc182 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -17361,7 +17361,7 @@ searchBaseByGroupType__10fManager_cFUcPC7fBase_c = .text:0x802E2980; // type:fun mainLoop__10fManager_cFv = .text:0x802E29E0; // type:function size:0xC0 __sinit_\f_manager_cpp = .text:0x802E2AA0; // type:function size:0x138 scope:local __ct__9fLiMgBa_cFv = .text:0x802E2BE0; // type:function size:0x10 -__arraydtor$4018 = .text:0x802E2BF0; // type:function size:0x1C scope:local +__arraydtor$4110 = .text:0x802E2BF0; // type:function size:0x1C scope:local walkPack__11fTrMgPTMF_cFv = .text:0x802E2C10; // type:function size:0x84 searchNodeByProfName__9fTrMgBa_cCFUsPC9fTrNdBa_c = .text:0x802E2CA0; // type:function size:0x68 searchNodeByGroupType__9fTrMgBa_cCFUcPC9fTrNdBa_c = .text:0x802E2D10; // type:function size:0x68 @@ -21895,37 +21895,37 @@ DCInvalidateRange = .text:0x803A4560; // type:function size:0x2C scope:global DCFlushRange = .text:0x803A4590; // type:function size:0x30 scope:global DCStoreRange = .text:0x803A45C0; // type:function size:0x30 DCFlushRangeNoSync = .text:0x803A45F0; // type:function size:0x2C scope:global -fn_803A4620 = .text:0x803A4620; // type:function size:0x2C +DCStoreRangeNoSync = .text:0x803A4620; // type:function size:0x2C DCZeroRange = .text:0x803A4650; // type:function size:0x2C scope:global ICInvalidateRange = .text:0x803A4680; // type:function size:0x34 scope:global ICFlashInvalidate = .text:0x803A46C0; // type:function size:0x10 scope:global ICEnable = .text:0x803A46D0; // type:function size:0x14 scope:global -fn_803A46F0 = .text:0x803A46F0; // type:function size:0xCC -fn_803A47C0 = .text:0x803A47C0; // type:function size:0x38 +__LCEnable = .text:0x803A46F0; // type:function size:0xCC +LCEnable = .text:0x803A47C0; // type:function size:0x38 LCDisable = .text:0x803A4800; // type:function size:0x28 scope:global -fn_803A4830 = .text:0x803A4830; // type:function size:0x24 -fn_803A4860 = .text:0x803A4860; // type:function size:0x24 -fn_803A4890 = .text:0x803A4890; // type:function size:0xA0 -fn_803A4930 = .text:0x803A4930; // type:function size:0xC -fn_803A4940 = .text:0x803A4940; // type:function size:0x14 +LCLoadBlocks = .text:0x803A4830; // type:function size:0x24 +LCStoreBlocks = .text:0x803A4860; // type:function size:0x24 +LCStoreData = .text:0x803A4890; // type:function size:0xA0 +LCQueueLength = .text:0x803A4930; // type:function size:0xC +LCQueueWait = .text:0x803A4940; // type:function size:0x14 DMAErrorHandler = .text:0x803A4960; // type:function size:0x148 scope:global __OSCacheInit = .text:0x803A4AB0; // type:function size:0xE8 scope:global __OSLoadFPUContext = .text:0x803A4BA0; // type:function size:0x124 scope:local __OSSaveFPUContext = .text:0x803A4CD0; // type:function size:0x128 scope:local OSSaveFPUContext = .text:0x803A4E00; // type:function size:0x8 scope:global OSSetCurrentContext = .text:0x803A4E10; // type:function size:0x5C scope:global -fn_803A4E70 = .text:0x803A4E70; // type:function size:0xC -fn_803A4E80 = .text:0x803A4E80; // type:function size:0x80 +OSGetCurrentContext = .text:0x803A4E70; // type:function size:0xC +OSSaveContext = .text:0x803A4E80; // type:function size:0x80 OSLoadContext = .text:0x803A4F00; // type:function size:0xD8 scope:global OSGetStackPointer = .text:0x803A4FE0; // type:function size:0x8 scope:global -fn_803A4FF0 = .text:0x803A4FF0; // type:function size:0x30 -fn_803A5020 = .text:0x803A5020; // type:function size:0x30 +OSSwitchFiber = .text:0x803A4FF0; // type:function size:0x30 +OSSwitchFiberEx = .text:0x803A5020; // type:function size:0x30 OSClearContext = .text:0x803A5050; // type:function size:0x24 scope:global -fn_803A5080 = .text:0x803A5080; // type:function size:0xBC +OSInitContext = .text:0x803A5080; // type:function size:0xBC OSDumpContext = .text:0x803A5140; // type:function size:0x260 scope:global OSSwitchFPUContext = .text:0x803A53A0; // type:function size:0x84 scope:local __OSContextInit = .text:0x803A5430; // type:function size:0x38 scope:global -fn_803A5470 = .text:0x803A5470; // type:function size:0x12C +OSFillFPUContext = .text:0x803A5470; // type:function size:0x12C OSSetErrorHandler = .text:0x803A55A0; // type:function size:0x28C scope:global __OSUnhandledException = .text:0x803A5830; // type:function size:0x2FC scope:global fn_803A5B30 = .text:0x803A5B30; // type:function size:0x180 @@ -22000,7 +22000,7 @@ OSInitMutex = .text:0x803AAA90; // type:function size:0x38 OSLockMutex = .text:0x803AAAD0; // type:function size:0xDC OSUnlockMutex = .text:0x803AABB0; // type:function size:0xC8 fn_803AAC80 = .text:0x803AAC80; // type:function size:0x6C -fn_803AACF0 = .text:0x803AACF0; // type:function size:0xBC +OSTryLockMutex = .text:0x803AACF0; // type:function size:0xBC fn_803AADB0 = .text:0x803AADB0; // type:function size:0x6C fn_803AAE20 = .text:0x803AAE20; // type:function size:0x14 OSRegisterShutdownFunction = .text:0x803AAE40; // type:function size:0x88 scope:global @@ -22043,7 +22043,7 @@ fn_803AC810 = .text:0x803AC810; // type:function size:0x1A8 fn_803AC9C0 = .text:0x803AC9C0; // type:function size:0x50 SelectThread = .text:0x803ACA10; // type:function size:0x22C scope:local __OSReschedule = .text:0x803ACC40; // type:function size:0x18 scope:global -fn_803ACC60 = .text:0x803ACC60; // type:function size:0x3C +OSYieldThread = .text:0x803ACC60; // type:function size:0x3C OSCreateThread = .text:0x803ACCA0; // type:function size:0x26C fn_803ACF10 = .text:0x803ACF10; // type:function size:0xE4 OSCancelThread = .text:0x803AD000; // type:function size:0x1D4 scope:global @@ -22479,30 +22479,30 @@ fn_803C6650 = .text:0x803C6650; // type:function size:0x188 fn_803C67E0 = .text:0x803C67E0; // type:function size:0x24 fn_803C6810 = .text:0x803C6810; // type:function size:0x31C fn_803C6B30 = .text:0x803C6B30; // type:function size:0x5B0 -fn_803C70E0 = .text:0x803C70E0; // type:function size:0x9E0 -fn_803C7AC0 = .text:0x803C7AC0; // type:function size:0xE4 +cbForStateBusy = .text:0x803C70E0; // type:function size:0x9E0 +DVDReadAbsAsyncPrio = .text:0x803C7AC0; // type:function size:0xE4 DVDInquiryAsync = .text:0x803C7BB0; // type:function size:0xD8 scope:global -fn_803C7C90 = .text:0x803C7C90; // type:function size:0xC8 -fn_803C7D60 = .text:0x803C7D60; // type:function size:0x9C -fn_803C7E00 = .text:0x803C7E00; // type:function size:0x10 -fn_803C7E10 = .text:0x803C7E10; // type:function size:0x50 -fn_803C7E60 = .text:0x803C7E60; // type:function size:0x364 -fn_803C81D0 = .text:0x803C81D0; // type:function size:0xC0 -fn_803C8290 = .text:0x803C8290; // type:function size:0x8 -fn_803C82A0 = .text:0x803C82A0; // type:function size:0x8 +DVDGetCommandBlockStatus = .text:0x803C7C90; // type:function size:0xC8 +DVDGetDriveStatus = .text:0x803C7D60; // type:function size:0x9C +DVDSetAutoInvalidation = .text:0x803C7E00; // type:function size:0x10 +DVDResume = .text:0x803C7E10; // type:function size:0x50 +DVDCancelAsync = .text:0x803C7E60; // type:function size:0x364 +DVDCancel = .text:0x803C81D0; // type:function size:0xC0 +cbForCancelSync = .text:0x803C8290; // type:function size:0x8 +__BS2DVDLowCallback = .text:0x803C82A0; // type:function size:0x8 __DVDGetCoverStatus = .text:0x803C82B0; // type:function size:0xCC scope:global -fn_803C8380 = .text:0x803C8380; // type:function size:0x238 -fn_803C85C0 = .text:0x803C85C0; // type:function size:0x11C -fn_803C86E0 = .text:0x803C86E0; // type:function size:0xC +DVDCheckDiskAsync = .text:0x803C8380; // type:function size:0x238 +__DVDPrepareResetAsync = .text:0x803C85C0; // type:function size:0x11C +Callback = .text:0x803C86E0; // type:function size:0xC __DVDPrepareReset = .text:0x803C86F0; // type:function size:0x138 scope:global -fn_803C8830 = .text:0x803C8830; // type:function size:0x20 -fn_803C8850 = .text:0x803C8850; // type:function size:0x8 -fn_803C8860 = .text:0x803C8860; // type:function size:0x4 +__DVDTestAlarm = .text:0x803C8830; // type:function size:0x20 +__DVDStopMotorAsync = .text:0x803C8850; // type:function size:0x8 +__DVDRestartMotor = .text:0x803C8860; // type:function size:0x4 __DVDClearWaitingQueue = .text:0x803C8870; // type:function size:0x38 scope:global -fn_803C88B0 = .text:0x803C88B0; // type:function size:0x68 -fn_803C8920 = .text:0x803C8920; // type:function size:0xA0 -fn_803C89C0 = .text:0x803C89C0; // type:function size:0x58 -fn_803C8A20 = .text:0x803C8A20; // type:function size:0x64 +__DVDPushWaitingQueue = .text:0x803C88B0; // type:function size:0x68 +__DVDPopWaitingQueue = .text:0x803C8920; // type:function size:0xA0 +__DVDCheckWaitingQueue = .text:0x803C89C0; // type:function size:0x58 +__DVDGetNextWaitingQueue = .text:0x803C8A20; // type:function size:0x64 fn_803C8A90 = .text:0x803C8A90; // type:function size:0x60 fn_803C8AF0 = .text:0x803C8AF0; // type:function size:0x2C fn_803C8B20 = .text:0x803C8B20; // type:function size:0x5C @@ -22639,18 +22639,18 @@ fn_803D0D60 = .text:0x803D0D60; // type:function size:0x78 fn_803D0DE0 = .text:0x803D0DE0; // type:function size:0xB0 fn_803D0E90 = .text:0x803D0E90; // type:function size:0x98 fn_803D0F30 = .text:0x803D0F30; // type:function size:0xC0 -fn_803D0FF0 = .text:0x803D0FF0; // type:function size:0x68 -fn_803D1060 = .text:0x803D1060; // type:function size:0x78 -fn_803D10E0 = .text:0x803D10E0; // type:function size:0x68 -fn_803D1150 = .text:0x803D1150; // type:function size:0x78 -fn_803D11D0 = .text:0x803D11D0; // type:function size:0x98 -fn_803D1270 = .text:0x803D1270; // type:function size:0xA8 +NANDRead = .text:0x803D0FF0; // type:function size:0x68 +NANDReadAsync = .text:0x803D1060; // type:function size:0x78 +NANDWrite = .text:0x803D10E0; // type:function size:0x68 +NANDWriteAsync = .text:0x803D1150; // type:function size:0x78 +NANDSeek = .text:0x803D11D0; // type:function size:0x98 +NANDSeekAsync = .text:0x803D1270; // type:function size:0xA8 fn_803D1320 = .text:0x803D1320; // type:function size:0x144 fn_803D1470 = .text:0x803D1470; // type:function size:0x74 fn_803D14F0 = .text:0x803D14F0; // type:function size:0x78 fn_803D1570 = .text:0x803D1570; // type:function size:0x1A8 fn_803D1720 = .text:0x803D1720; // type:function size:0x64 -fn_803D1790 = .text:0x803D1790; // type:function size:0x88 +NANDGetLength = .text:0x803D1790; // type:function size:0x88 fn_803D1820 = .text:0x803D1820; // type:function size:0x54 fn_803D1880 = .text:0x803D1880; // type:function size:0x8C fn_803D1910 = .text:0x803D1910; // type:function size:0x154 @@ -22661,22 +22661,22 @@ fn_803D1BF0 = .text:0x803D1BF0; // type:function size:0x8 fn_803D1C00 = .text:0x803D1C00; // type:function size:0x8 fn_803D1C10 = .text:0x803D1C10; // type:function size:0x334 nandOpen = .text:0x803D1F50; // type:function size:0x110 scope:local -fn_803D2060 = .text:0x803D2060; // type:function size:0x8C -fn_803D20F0 = .text:0x803D20F0; // type:function size:0x8C -fn_803D2180 = .text:0x803D2180; // type:function size:0x78 +NANDOpen = .text:0x803D2060; // type:function size:0x8C +NANDPrivateOpen = .text:0x803D20F0; // type:function size:0x8C +NANDOpenAsync = .text:0x803D2180; // type:function size:0x78 NANDPrivateOpenAsync = .text:0x803D2200; // type:function size:0x78 scope:global nandOpenCallback = .text:0x803D2280; // type:function size:0x78 scope:local -fn_803D2300 = .text:0x803D2300; // type:function size:0x6C -fn_803D2370 = .text:0x803D2370; // type:function size:0x88 -fn_803D2400 = .text:0x803D2400; // type:function size:0xC -fn_803D2410 = .text:0x803D2410; // type:function size:0x3A8 -fn_803D27C0 = .text:0x803D27C0; // type:function size:0x8 -fn_803D27D0 = .text:0x803D27D0; // type:function size:0x1D4 -fn_803D29B0 = .text:0x803D29B0; // type:function size:0x5C -fn_803D2A10 = .text:0x803D2A10; // type:function size:0x1AC -fn_803D2BC0 = .text:0x803D2BC0; // type:function size:0xD4 -fn_803D2CA0 = .text:0x803D2CA0; // type:function size:0xD4 -fn_803D2D80 = .text:0x803D2D80; // type:function size:0x98 +NANDClose = .text:0x803D2300; // type:function size:0x6C +NANDCloseAsync = .text:0x803D2370; // type:function size:0x88 +NANDSimpleSafeOpen = .text:0x803D2400; // type:function size:0xC +nandSafeOpen = .text:0x803D2410; // type:function size:0x3A8 +NANDSimpleSafeClose = .text:0x803D27C0; // type:function size:0x8 +nandSafeClose = .text:0x803D27D0; // type:function size:0x1D4 +nandCloseCallback = .text:0x803D29B0; // type:function size:0x5C +NANDSimpleSafeCancel = .text:0x803D2A10; // type:function size:0x1AC +nandRemoveTailToken = .text:0x803D2BC0; // type:function size:0xD4 +nandGetHeadToken = .text:0x803D2CA0; // type:function size:0xD4 +nandGetRelativeName = .text:0x803D2D80; // type:function size:0x98 nandConvertPath = .text:0x803D2E20; // type:function size:0x13C scope:global fn_803D2F60 = .text:0x803D2F60; // type:function size:0x1C nandIsPrivatePath = .text:0x803D2F80; // type:function size:0x34 scope:global @@ -23984,19 +23984,19 @@ PeekAsync__Q34nw4r2ut13DvdFileStreamFPvUlPFlPQ34nw4r2ut8IOStreamPv_vPv = .text:0 Seek__Q34nw4r2ut13DvdFileStreamFlUl = .text:0x8042BC60; // type:function size:0x8 Cancel__Q34nw4r2ut13DvdFileStreamFv = .text:0x8042BC70; // type:function size:0x8 CancelAsync__Q34nw4r2ut13DvdFileStreamFPFlPQ34nw4r2ut8IOStreamPv_vPv = .text:0x8042BC80; // type:function size:0x5C -GetBufferAlign__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BCE0; // type:function size:0x8 -GetSizeAlign__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BCF0; // type:function size:0x8 -GetOffsetAlign__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD00; // type:function size:0x8 -CanCancel__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD10; // type:function size:0x8 -CanWrite__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD20; // type:function size:0x8 -CanRead__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD30; // type:function size:0x8 -CanSeek__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD40; // type:function size:0x8 -CanAsync__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD50; // type:function size:0x8 -GetSize__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD60; // type:function size:0x8 -Tell__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD70; // type:function size:0x8 -IsBusy__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD80; // type:function size:0x8 -GetRuntimeTypeInfo__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD90; // type:function size:0x8 -__sinit_\ut_DvdFileStream_cpp = .text:0x8042BDA0; // type:function size:0xC +GetBufferAlign__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BCE0; // type:function size:0x8 scope:weak +GetSizeAlign__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BCF0; // type:function size:0x8 scope:weak +GetOffsetAlign__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD00; // type:function size:0x8 scope:weak +CanCancel__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD10; // type:function size:0x8 scope:weak +CanWrite__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD20; // type:function size:0x8 scope:weak +CanRead__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD30; // type:function size:0x8 scope:weak +CanSeek__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD40; // type:function size:0x8 scope:weak +CanAsync__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD50; // type:function size:0x8 scope:weak +GetSize__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD60; // type:function size:0x8 scope:weak +Tell__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD70; // type:function size:0x8 scope:weak +IsBusy__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD80; // type:function size:0x8 scope:weak +GetRuntimeTypeInfo__Q34nw4r2ut13DvdFileStreamCFv = .text:0x8042BD90; // type:function size:0x8 scope:weak +__sinit_\ut_DvdFileStream_cpp = .text:0x8042BDA0; // type:function size:0xC scope:local __ct__Q34nw4r2ut19DvdLockedFileStreamFl = .text:0x8042BDB0; // type:function size:0x84 __ct__Q34nw4r2ut19DvdLockedFileStreamFPC11DVDFileInfob = .text:0x8042BE40; // type:function size:0x84 __dt__Q34nw4r2ut19DvdLockedFileStreamFv = .text:0x8042BED0; // type:function size:0x58 @@ -24004,11 +24004,11 @@ Close__Q34nw4r2ut19DvdLockedFileStreamFv = .text:0x8042BF30; // type:function si Read__Q34nw4r2ut19DvdLockedFileStreamFPvUl = .text:0x8042BF70; // type:function size:0xD4 Peek__Q34nw4r2ut19DvdLockedFileStreamFPvUl = .text:0x8042C050; // type:function size:0xD4 Cancel__Q34nw4r2ut19DvdLockedFileStreamFv = .text:0x8042C130; // type:function size:0x58 -CanAsync__Q34nw4r2ut19DvdLockedFileStreamCFv = .text:0x8042C190; // type:function size:0x8 -PeekAsync__Q34nw4r2ut19DvdLockedFileStreamFPvUlPFlPQ34nw4r2ut8IOStreamPv_vPv = .text:0x8042C1A0; // type:function size:0x8 -ReadAsync__Q34nw4r2ut19DvdLockedFileStreamFPvUlPFlPQ34nw4r2ut8IOStreamPv_vPv = .text:0x8042C1B0; // type:function size:0x8 -GetRuntimeTypeInfo__Q34nw4r2ut19DvdLockedFileStreamCFv = .text:0x8042C1C0; // type:function size:0x8 -__sinit_\ut_DvdLockedFileStream_cpp = .text:0x8042C1D0; // type:function size:0xC +CanAsync__Q34nw4r2ut19DvdLockedFileStreamCFv = .text:0x8042C190; // type:function size:0x8 scope:weak +PeekAsync__Q34nw4r2ut19DvdLockedFileStreamFPvUlPFlPQ34nw4r2ut8IOStreamPv_vPv = .text:0x8042C1A0; // type:function size:0x8 scope:weak +ReadAsync__Q34nw4r2ut19DvdLockedFileStreamFPvUlPFlPQ34nw4r2ut8IOStreamPv_vPv = .text:0x8042C1B0; // type:function size:0x8 scope:weak +GetRuntimeTypeInfo__Q34nw4r2ut19DvdLockedFileStreamCFv = .text:0x8042C1C0; // type:function size:0x8 scope:weak +__sinit_\ut_DvdLockedFileStream_cpp = .text:0x8042C1D0; // type:function size:0xC scope:local NandAsyncCallback___Q34nw4r2ut14NandFileStreamFlP16NANDCommandBlock = .text:0x8042C1E0; // type:function size:0x2C __ct__Q34nw4r2ut14NandFileStreamFPCcUl = .text:0x8042C210; // type:function size:0x70 __ct__Q34nw4r2ut14NandFileStreamFPC12NANDFileInfoUlb = .text:0x8042C280; // type:function size:0x70 @@ -24021,19 +24021,19 @@ ReadAsync__Q34nw4r2ut14NandFileStreamFPvUlPFlPQ34nw4r2ut8IOStreamPv_vPv = .text: Write__Q34nw4r2ut14NandFileStreamFPCvUl = .text:0x8042C840; // type:function size:0x7C WriteAsync__Q34nw4r2ut14NandFileStreamFPCvUlPFlPQ34nw4r2ut8IOStreamPv_vPv = .text:0x8042C8C0; // type:function size:0xA8 Seek__Q34nw4r2ut14NandFileStreamFlUl = .text:0x8042C970; // type:function size:0x8 -GetBufferAlign__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C980; // type:function size:0x8 -GetSizeAlign__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C990; // type:function size:0x8 -GetOffsetAlign__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9A0; // type:function size:0x8 -CanCancel__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9B0; // type:function size:0x8 -CanWrite__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9C0; // type:function size:0x8 -CanRead__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9D0; // type:function size:0x8 -CanSeek__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9E0; // type:function size:0x8 -CanAsync__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9F0; // type:function size:0x8 -GetSize__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042CA00; // type:function size:0x8 -Tell__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042CA10; // type:function size:0x8 -IsBusy__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042CA20; // type:function size:0x8 -GetRuntimeTypeInfo__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042CA30; // type:function size:0x8 -__sinit_\ut_NandFileStream_cpp = .text:0x8042CA40; // type:function size:0xC +GetBufferAlign__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C980; // type:function size:0x8 scope:weak +GetSizeAlign__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C990; // type:function size:0x8 scope:weak +GetOffsetAlign__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9A0; // type:function size:0x8 scope:weak +CanCancel__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9B0; // type:function size:0x8 scope:weak +CanWrite__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9C0; // type:function size:0x8 scope:weak +CanRead__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9D0; // type:function size:0x8 scope:weak +CanSeek__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9E0; // type:function size:0x8 scope:weak +CanAsync__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042C9F0; // type:function size:0x8 scope:weak +GetSize__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042CA00; // type:function size:0x8 scope:weak +Tell__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042CA10; // type:function size:0x8 scope:weak +IsBusy__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042CA20; // type:function size:0x8 scope:weak +GetRuntimeTypeInfo__Q34nw4r2ut14NandFileStreamCFv = .text:0x8042CA30; // type:function size:0x8 scope:weak +__sinit_\ut_NandFileStream_cpp = .text:0x8042CA40; // type:function size:0xC scope:local Enable__Q34nw4r2ut2LCFv = .text:0x8042CA50; // type:function size:0x60 Disable__Q34nw4r2ut2LCFv = .text:0x8042CAB0; // type:function size:0x78 Lock__Q34nw4r2ut2LCFv = .text:0x8042CB30; // type:function size:0x70 @@ -24041,9 +24041,9 @@ Unlock__Q34nw4r2ut2LCFv = .text:0x8042CBA0; // type:function size:0x40 LoadBlocks__Q34nw4r2ut2LCFPvPvUl = .text:0x8042CBE0; // type:function size:0x4 StoreBlocks__Q34nw4r2ut2LCFPvPvUl = .text:0x8042CBF0; // type:function size:0x4 StoreData__Q34nw4r2ut2LCFPvPvUl = .text:0x8042CC00; // type:function size:0x4 -__sinit_\ut_LockedCache_cpp = .text:0x8042CC10; // type:function size:0x18 +__sinit_\ut_LockedCache_cpp = .text:0x8042CC10; // type:function size:0x18 scope:local InitReaderFunc__Q34nw4r2ut4FontFQ34nw4r2ut12FontEncoding = .text:0x8042CC30; // type:function size:0xA4 -__dt__Q34nw4r2ut4FontFv = .text:0x8042CCE0; // type:function size:0x40 +__dt__Q34nw4r2ut4FontFv = .text:0x8042CCE0; // type:function size:0x40 scope:weak __ct__Q44nw4r2ut6detail11ResFontBaseFv = .text:0x8042CD20; // type:function size:0x54 __dt__Q44nw4r2ut6detail11ResFontBaseFv = .text:0x8042CD80; // type:function size:0x40 SetResourceBuffer__Q44nw4r2ut6detail11ResFontBaseFPvPQ34nw4r2ut15FontInformation = .text:0x8042CDC0; // type:function size:0xC @@ -36945,14 +36945,17 @@ jumptable_8056BCD8 = .data:0x8056BCD8; // type:object size:0x20 scope:local lbl_8056BD20 = .data:0x8056BD20; // type:object size:0x30 __vt__Q34nw4r2ut19TagProcessorBase = .data:0x8056BD50; // type:object size:0x14 scope:weak __vt__Q34nw4r2ut19TagProcessorBase = .data:0x8056BD64; // type:object size:0x14 scope:weak -lbl_8056BD78 = .data:0x8056BD78; // type:object size:0x68 -lbl_8056BDE0 = .data:0x8056BDE0; // type:object size:0x68 -lbl_8056BE48 = .data:0x8056BE48; // type:object size:0x60 -lbl_8056BEA8 = .data:0x8056BEA8; // type:object size:0x30 data:4byte -lbl_8056BED8 = .data:0x8056BED8; // type:object size:0x60 -lbl_8056BF38 = .data:0x8056BF38; // type:object size:0xC data:4byte -lbl_8056BF44 = .data:0x8056BF44; // type:object size:0x5C -lbl_8056BFA0 = .data:0x8056BFA0; // type:object size:0x60 +__vt__Q34nw4r2ut13DvdFileStream = .data:0x8056BD78; // type:object size:0x64 +__vt__Q34nw4r2ut19DvdLockedFileStream = .data:0x8056BDE0; // type:object size:0x64 +__vt__Q34nw4r2ut14NandFileStream = .data:0x8056BE48; // type:object size:0x5C +lbl_8056BEA8 = .data:0x8056BEA8; // type:object size:0xC scope:local data:4byte +lbl_8056BEB4 = .data:0x8056BEB4; // type:object size:0xC scope:local data:4byte +lbl_8056BEC0 = .data:0x8056BEC0; // type:object size:0xC scope:local data:4byte +lbl_8056BECC = .data:0x8056BECC; // type:object size:0xC scope:local data:4byte +__vt__Q34nw4r2ut4Font = .data:0x8056BED8; // type:object size:0x5C scope:weak +@3746 = .data:0x8056BF38; // type:object size:0xC scope:local data:4byte +__vt__Q44nw4r2ut6detail11ResFontBase = .data:0x8056BF44; // type:object size:0x5C +__vt__Q34nw4r2ut7ResFont = .data:0x8056BFA0; // type:object size:0x5C twiceBit__Q24nw4r2db = .data:0x8056C000; // type:object size:0x10 scope:local lbl_8056C010 = .data:0x8056C010; // type:object size:0x10 lbl_8056C020 = .data:0x8056C020; // type:object size:0x18 @@ -39538,8 +39541,8 @@ __fsFd = .sdata:0x80574DA0; // type:object size:0x4 scope:local data:4byte @1688 = .sdata:0x80574DA8; // type:object size:0x8 scope:local data:string lbl_80574DB0 = .sdata:0x80574DB0; // type:object size:0x8 lbl_80574DB8 = .sdata:0x80574DB8; // type:object size:0x8 data:byte -lbl_80574DC0 = .sdata:0x80574DC0; // type:object size:0x4 data:4byte -lbl_80574DC4 = .sdata:0x80574DC4; // type:object size:0x4 data:4byte +mFormatBufferSize__Q34nw4r2ut17TextWriterBase = .sdata:0x80574DC0; // type:object size:0x4 scope:weak data:4byte +mFormatBufferSize__Q34nw4r2ut17TextWriterBase = .sdata:0x80574DC4; // type:object size:0x4 scope:weak data:4byte lbl_80574DC8 = .sdata:0x80574DC8; // type:object size:0x4 data:string lbl_80574DCC = .sdata:0x80574DCC; // type:object size:0x4 lbl_80574DD0 = .sdata:0x80574DD0; // type:object size:0x4 data:string @@ -40604,8 +40607,8 @@ FstStart = .sbss:0x80576248; // type:object size:0x4 scope:local data:4byte BootInfo = .sbss:0x8057624C; // type:object size:0x4 scope:local data:4byte lbl_80576260 = .sbss:0x80576260; // type:object size:0x4 data:4byte lbl_80576264 = .sbss:0x80576264; // type:object size:0x4 data:4byte -lbl_80576268 = .sbss:0x80576268; // type:object size:0x4 data:4byte -lbl_8057626C = .sbss:0x8057626C; // type:object size:0x4 data:4byte +PausingFlag = .sbss:0x80576268; // type:object size:0x4 scope:local data:4byte +FatalErrorFlag = .sbss:0x8057626C; // type:object size:0x4 scope:local data:4byte lbl_80576270 = .sbss:0x80576270; // type:object size:0x4 data:4byte lbl_80576274 = .sbss:0x80576274; // type:object size:0x4 data:4byte lbl_80576278 = .sbss:0x80576278; // type:object size:0x4 data:4byte @@ -40634,7 +40637,7 @@ lbl_805762E0 = .sbss:0x805762E0; // type:object size:0x4 data:4byte lbl_805762E4 = .sbss:0x805762E4; // type:object size:0x4 data:4byte bootInfo = .sbss:0x805762E8; // type:object size:0x4 scope:local data:4byte IDShouldBe = .sbss:0x805762EC; // type:object size:0x4 scope:local data:4byte -lbl_805762F0 = .sbss:0x805762F0; // type:object size:0x4 data:4byte +executing = .sbss:0x805762F0; // type:object size:0x4 scope:local data:4byte lbl_805762F4 = .sbss:0x805762F4; // type:object size:0x4 data:4byte lbl_805762F8 = .sbss:0x805762F8; // type:object size:0x4 data:4byte lbl_805762FC = .sbss:0x805762FC; // type:object size:0x4 data:4byte @@ -40810,19 +40813,19 @@ lbl_80576584 = .sbss:0x80576584; // type:object size:0x4 data:4byte lbl_80576588 = .sbss:0x80576588; // type:object size:0x8 data:4byte typeInfo__Q34nw4r2ut8IOStream = .sbss:0x80576590; // type:object size:0x4 data:4byte typeInfo__Q34nw4r2ut10FileStream = .sbss:0x80576598; // type:object size:0x4 data:4byte -lbl_805765A0 = .sbss:0x805765A0; // type:object size:0x8 data:4byte -lbl_805765A8 = .sbss:0x805765A8; // type:object size:0x8 data:4byte -lbl_805765B0 = .sbss:0x805765B0; // type:object size:0x8 -lbl_805765B8 = .sbss:0x805765B8; // type:object size:0x8 data:byte -lbl_805765C0 = .sbss:0x805765C0; // type:object size:0x8 data:4byte -lbl_805765C8 = .sbss:0x805765C8; // type:object size:0x1 data:byte -lbl_805765CC = .sbss:0x805765CC; // type:object size:0x4 data:4byte -lbl_805765D0 = .sbss:0x805765D0; // type:object size:0x4 data:4byte -lbl_805765D4 = .sbss:0x805765D4; // type:object size:0x4 -lbl_805765D8 = .sbss:0x805765D8; // type:object size:0x4 data:4byte -lbl_805765DC = .sbss:0x805765DC; // type:object size:0x4 -lbl_805765E0 = .sbss:0x805765E0; // type:object size:0x1 data:byte -lbl_805765E1 = .sbss:0x805765E1; // type:object size:0x7 data:byte +typeInfo__Q34nw4r2ut13DvdFileStream = .sbss:0x805765A0; // type:object size:0x4 data:4byte +typeInfo__Q34nw4r2ut19DvdLockedFileStream = .sbss:0x805765A8; // type:object size:0x4 data:4byte +sThreadQueue__Q34nw4r2ut19DvdLockedFileStream = .sbss:0x805765B0; // type:object size:0x8 +sInitialized__Q34nw4r2ut19DvdLockedFileStream = .sbss:0x805765B8; // type:object size:0x1 data:byte +typeInfo__Q34nw4r2ut14NandFileStream = .sbss:0x805765C0; // type:object size:0x4 data:4byte +@GUARD@SetupGXCommon__27@unnamed@ut_CharWriter_cpp@Fv@fog = .sbss:0x805765C8; // type:object size:0x1 scope:local data:byte +@LOCAL@SetupGXCommon__27@unnamed@ut_CharWriter_cpp@Fv@fog = .sbss:0x805765CC; // type:object size:0x4 scope:local data:4byte +mFormatBuffer__Q34nw4r2ut17TextWriterBase = .sbss:0x805765D0; // type:object size:0x4 scope:weak data:4byte +mDefaultTagProcessor__Q34nw4r2ut17TextWriterBase = .sbss:0x805765D4; // type:object size:0x4 scope:weak +mFormatBuffer__Q34nw4r2ut17TextWriterBase = .sbss:0x805765D8; // type:object size:0x4 scope:weak data:4byte +mDefaultTagProcessor__Q34nw4r2ut17TextWriterBase = .sbss:0x805765DC; // type:object size:0x4 scope:weak +@GUARD@mDefaultTagProcessor__Q34nw4r2ut17TextWriterBase = .sbss:0x805765E0; // type:object size:0x1 scope:weak data:byte +@GUARD@mDefaultTagProcessor__Q34nw4r2ut17TextWriterBase = .sbss:0x805765E1; // type:object size:0x1 scope:weak data:byte sInitialized__Q24nw4r2db = .sbss:0x805765E8; // type:object size:0x4 scope:local data:4byte lbl_805765F0 = .sbss:0x805765F0; // type:object size:0x4 data:4byte lbl_805765F4 = .sbss:0x805765F4; // type:object size:0x1 data:byte @@ -47230,16 +47233,16 @@ lbl_8057EB54 = .sdata2:0x8057EB54; // type:object size:0x1 data:byte lbl_8057EB55 = .sdata2:0x8057EB55; // type:object size:0x1 data:byte lbl_8057EB58 = .sdata2:0x8057EB58; // type:object size:0x8 lbl_8057EB60 = .sdata2:0x8057EB60; // type:object size:0x8 data:double -lbl_8057EB68 = .sdata2:0x8057EB68; // type:object size:0x8 data:double -lbl_8057EB70 = .sdata2:0x8057EB70; // type:object size:0x4 data:float -lbl_8057EB74 = .sdata2:0x8057EB74; // type:object size:0x4 data:float -lbl_8057EB78 = .sdata2:0x8057EB78; // type:object size:0x8 data:double -lbl_8057EB80 = .sdata2:0x8057EB80; // type:object size:0x4 data:float -lbl_8057EB88 = .sdata2:0x8057EB88; // type:object size:0x8 data:double -lbl_8057EB90 = .sdata2:0x8057EB90; // type:object size:0x4 data:float -lbl_8057EB94 = .sdata2:0x8057EB94; // type:object size:0x4 data:float -lbl_8057EB98 = .sdata2:0x8057EB98; // type:object size:0x8 data:double -lbl_8057EBA0 = .sdata2:0x8057EBA0; // type:object size:0x8 data:float +lbl_8057EB68 = .sdata2:0x8057EB68; // type:object size:0x8 scope:local data:double +lbl_8057EB70 = .sdata2:0x8057EB70; // type:object size:0x4 scope:local data:float +lbl_8057EB74 = .sdata2:0x8057EB74; // type:object size:0x4 scope:local data:float +lbl_8057EB78 = .sdata2:0x8057EB78; // type:object size:0x8 scope:local data:double +lbl_8057EB80 = .sdata2:0x8057EB80; // type:object size:0x4 scope:local data:float +lbl_8057EB88 = .sdata2:0x8057EB88; // type:object size:0x8 scope:local data:double +lbl_8057EB90 = .sdata2:0x8057EB90; // type:object size:0x4 scope:local data:float +lbl_8057EB94 = .sdata2:0x8057EB94; // type:object size:0x4 scope:local data:float +lbl_8057EB98 = .sdata2:0x8057EB98; // type:object size:0x8 scope:local data:double +lbl_8057EBA0 = .sdata2:0x8057EBA0; // type:object size:0x4 scope:local data:float lbl_8057EBA8 = .sdata2:0x8057EBA8; // type:object size:0x8 data:float lbl_8057EBB0 = .sdata2:0x8057EBB0; // type:object size:0x4 data:float lbl_8057EBB4 = .sdata2:0x8057EBB4; // type:object size:0x4 data:float @@ -49215,7 +49218,7 @@ lbl_805E8910 = .bss:0x805E8910; // type:object size:0x730 data:4byte __DVDTicketViewBuffer = .bss:0x805E9040; // type:object size:0xE0 scope:local __DVDTmdBuffer = .bss:0x805E9140; // type:object size:0x4A00 scope:local lbl_805EDB40 = .bss:0x805EDB40; // type:object size:0x20 -lbl_805EDB60 = .bss:0x805EDB60; // type:object size:0x30 +DummyCommandBlock = .bss:0x805EDB60; // type:object size:0x30 scope:local lbl_805EDB90 = .bss:0x805EDB90; // type:object size:0x30 lbl_805EDBC0 = .bss:0x805EDBC0; // type:object size:0x40 lbl_805EDC00 = .bss:0x805EDC00; // type:object size:0x20 @@ -49287,11 +49290,11 @@ __timeout_alarm = .bss:0x80632FB0; // type:object size:0x30 scope:local lbl_80632FE0 = .bss:0x80632FE0; // type:object size:0x40 lbl_80633020 = .bss:0x80633020; // type:object size:0x80 data:4byte lbl_806330A0 = .bss:0x806330A0; // type:object size:0x3A80 data:4byte -lbl_80636B20 = .bss:0x80636B20; // type:object size:0x18 -lbl_80636B38 = .bss:0x80636B38; // type:object size:0x20 data:byte -lbl_80636B58 = .bss:0x80636B58; // type:object size:0x10 data:4byte -lbl_80636B68 = .bss:0x80636B68; // type:object size:0xC -lbl_80636B74 = .bss:0x80636B74; // type:object size:0xC +sMutex__Q34nw4r2ut19DvdLockedFileStream = .bss:0x80636B20; // type:object size:0x18 +sLCImpl__Q34nw4r2ut28@unnamed@ut_LockedCache_cpp@ = .bss:0x80636B38; // type:object size:0x1C data:byte +mLoadingTexture__Q34nw4r2ut10CharWriter = .bss:0x80636B58; // type:object size:0x10 data:4byte +@3766 = .bss:0x80636B68; // type:object size:0xC scope:local +@3896 = .bss:0x80636B74; // type:object size:0xC scope:local sFrameBufferInfo__Q24nw4r2db = .bss:0x80636B80; // type:object size:0x10 data:4byte sFrameBufferColor__Q24nw4r2db = .bss:0x80636B90; // type:object size:0x14 data:byte lbl_80636BA8 = .bss:0x80636BA8; // type:object size:0x18 diff --git a/configure.py b/configure.py index 3123135c..cb417508 100644 --- a/configure.py +++ b/configure.py @@ -334,14 +334,15 @@ config.libs = [ Object(Matching, "nw4r/ut/ut_IOStream.cpp"), Object(Matching, "nw4r/ut/ut_TagProcessorBase.cpp"), Object(Matching, "nw4r/ut/ut_FileStream.cpp"), - Object(NonMatching, "nw4r/ut/ut_DvdFileStream.cpp"), - Object(NonMatching, "nw4r/ut/ut_DvdLockedFileStream.cpp"), - Object(NonMatching, "nw4r/ut/ut_NandFileStream.cpp"), - Object(NonMatching, "nw4r/ut/ut_LockedCache.cpp"), - Object(NonMatching, "nw4r/ut/ut_Font.cpp"), - Object(NonMatching, "nw4r/ut/ut_ResFontBase.cpp"), - Object(NonMatching, "nw4r/ut/ut_ResFont.cpp"), - Object(NonMatching, "nw4r/ut/ut_CharWriter.cpp"), + Object(Matching, "nw4r/ut/ut_DvdFileStream.cpp"), + Object(Matching, "nw4r/ut/ut_DvdLockedFileStream.cpp"), + Object(Matching, "nw4r/ut/ut_NandFileStream.cpp"), + Object(Matching, "nw4r/ut/ut_LockedCache.cpp"), + Object(Matching, "nw4r/ut/ut_Font.cpp"), + Object(Matching, "nw4r/ut/ut_RomFont.cpp"), + Object(Matching, "nw4r/ut/ut_ResFontBase.cpp"), + Object(Matching, "nw4r/ut/ut_ResFont.cpp"), + Object(Matching, "nw4r/ut/ut_CharWriter.cpp"), Object(NonMatching, "nw4r/ut/ut_TextWriterBase.cpp"), ], ), diff --git a/include/MSL_C/MSL_Common/Src/ansi_files.h b/include/MSL_C/MSL_Common/Src/ansi_files.h index 4aee7fc1..8e8d7673 100644 --- a/include/MSL_C/MSL_Common/Src/ansi_files.h +++ b/include/MSL_C/MSL_Common/Src/ansi_files.h @@ -17,10 +17,10 @@ typedef unsigned long fpos_t; typedef unsigned short wchar_t; #endif -#define set_error(file) \ - do { \ - (file)->file_state.error = 1; \ - (file)->buffer_length = 0; \ +#define set_error(file) \ + do { \ + (file)->file_state.error = 1; \ + (file)->buffer_length = 0; \ } while (0) enum __file_kinds { @@ -73,9 +73,8 @@ typedef struct _file_states { } file_states; typedef void (*__idle_proc)(void); -typedef int (*__pos_proc)(__file_handle file, fpos_t* position, int mode, __idle_proc idle_proc); -typedef int (*__io_proc)(__file_handle file, unsigned char* buff, size_t* count, - __idle_proc idle_proc); +typedef int (*__pos_proc)(__file_handle file, fpos_t *position, int mode, __idle_proc idle_proc); +typedef int (*__io_proc)(__file_handle file, unsigned char *buff, size_t *count, __idle_proc idle_proc); typedef int (*__close_proc)(__file_handle file); typedef struct _FILE { @@ -88,9 +87,9 @@ typedef struct _FILE { /* 0x0F */ char ungetc_buffer[2]; /* 0x12 */ wchar_t ungetc_wide_buffer[2]; /* 0x18 */ unsigned long position; - /* 0x1C */ unsigned char* buffer; + /* 0x1C */ unsigned char *buffer; /* 0x20 */ unsigned long buffer_size; - /* 0x24 */ unsigned char* buffer_ptr; + /* 0x24 */ unsigned char *buffer_ptr; /* 0x28 */ unsigned long buffer_length; /* 0x2C */ unsigned long buffer_alignment; /* 0x30 */ unsigned long save_buffer_length; @@ -100,7 +99,7 @@ typedef struct _FILE { /* 0x40 */ __io_proc write_fn; /* 0x44 */ __close_proc close_fn; /* 0x48 */ __idle_proc idle_fn; - /* 0x4C */ struct _FILE* next_file; + /* 0x4C */ struct _FILE *next_file; } FILE; typedef struct _files { @@ -116,10 +115,8 @@ typedef struct _files { extern files __files; extern int __close_console(__file_handle file); -extern int __write_console(__file_handle file, unsigned char* buf, size_t* count, - __idle_proc idle_fn); -extern int __read_console(__file_handle file, unsigned char* buf, size_t* count, - __idle_proc idle_fn); +extern int __write_console(__file_handle file, unsigned char *buf, size_t *count, __idle_proc idle_fn); +extern int __read_console(__file_handle file, unsigned char *buf, size_t *count, __idle_proc idle_fn); unsigned int __flush_all(void); void __close_all(void); diff --git a/include/nw4r/ut/ut_CharWriter.h b/include/nw4r/ut/ut_CharWriter.h index e5801516..0ef0cee4 100644 --- a/include/nw4r/ut/ut_CharWriter.h +++ b/include/nw4r/ut/ut_CharWriter.h @@ -159,6 +159,7 @@ public: void SetupGX(); void SetFontSize(f32 width, f32 height); + void SetFontSize(f32 height); f32 GetFontWidth() const; f32 GetFontHeight() const; f32 GetFontAscent() const; diff --git a/include/nw4r/ut/ut_DvdFileStream.h b/include/nw4r/ut/ut_DvdFileStream.h index 5b000b6e..2f305e6b 100644 --- a/include/nw4r/ut/ut_DvdFileStream.h +++ b/include/nw4r/ut/ut_DvdFileStream.h @@ -24,7 +24,7 @@ public: }; public: - DvdFileStream(s32 entrynum); + DvdFileStream(long entrynum); DvdFileStream(const DVDFileInfo *info, bool close); virtual ~DvdFileStream(); // at 0xC @@ -67,15 +67,15 @@ public: virtual void Close(); // at 0x10 - virtual s32 Read(void *dst, u32 size); // at 0x14 - virtual bool ReadAsync(void *dst, u32 size, AsyncCallback callback, + virtual long Read(void *dst, unsigned long size); // at 0x14 + virtual bool ReadAsync(void *dst, unsigned long size, AsyncCallback callback, void *arg); // at 0x18 - virtual s32 Peek(void *dst, u32 size); // at 0x5C - virtual bool PeekAsync(void *dst, u32 size, AsyncCallback callback, + virtual long Peek(void *dst, unsigned long size); // at 0x5C + virtual bool PeekAsync(void *dst, unsigned long size, AsyncCallback callback, void *arg); // at 0x60 - virtual void Seek(s32 offset, u32 origin); // at 0x44 + virtual void Seek(long offset, unsigned long origin); // at 0x44 virtual void Cancel(); // at 0x48 virtual bool CancelAsync(AsyncCallback callback, void *arg); // at 0x4C @@ -88,11 +88,11 @@ public: bool Open(const DVDFileInfo *info, bool close); private: - static void DvdAsyncCallback_(s32 result, DVDFileInfo *info); - static void DvdCBAsyncCallback_(s32 result, DVDCommandBlock *block); + static void DvdAsyncCallback_(long result, DVDFileInfo *info); + static void DvdCBAsyncCallback_(long result, DVDCommandBlock *block); void Initialize_(); - u32 AdjustReadLength_(u32 len); + unsigned long AdjustReadLength_(unsigned long len); private: FilePosition mFilePosition; // at 0x14 diff --git a/include/nw4r/ut/ut_DvdLockedFileStream.h b/include/nw4r/ut/ut_DvdLockedFileStream.h index 8bbf85af..501bbc18 100644 --- a/include/nw4r/ut/ut_DvdLockedFileStream.h +++ b/include/nw4r/ut/ut_DvdLockedFileStream.h @@ -11,17 +11,19 @@ class DvdLockedFileStream : public DvdFileStream { public: NW4R_UT_RTTI_DECL(DvdLockedFileStream); - DvdLockedFileStream(s32 entrynum); + DvdLockedFileStream(long entrynum); DvdLockedFileStream(const DVDFileInfo *info, bool close); virtual ~DvdLockedFileStream(); // at 0xC - virtual s32 Read(void *dst, u32 size); // at 0x14 - virtual bool ReadAsync(void *dst, u32 size, AsyncCallback callback, void *arg) { + virtual void Close(); // at 0x10 + + virtual long Read(void *dst, unsigned long size); // at 0x14 + virtual bool ReadAsync(void *dst, unsigned long size, AsyncCallback callback, void *arg) { return false; } // at 0x18 - virtual s32 Peek(void *dst, u32 size); // at 0x5C - virtual bool PeekAsync(void *dst, u32 size, AsyncCallback callback, void *arg) { + virtual long Peek(void *dst, unsigned long size); // at 0x5C + virtual bool PeekAsync(void *dst, unsigned long size, AsyncCallback callback, void *arg) { return false; } // at 0x60 @@ -29,11 +31,18 @@ public: return false; } // at 0x28 -private: - static void InitMutex_(); + void Cancel(); private: + static void InitMutex_(); + bool LockMutex(); + static void UnlockMutex(); + void CancelMutex(); + +private: + volatile bool mCancelFlag; // 0x6f static bool sInitialized; + static OSThreadQueue sThreadQueue; static OSMutex sMutex; }; diff --git a/include/nw4r/ut/ut_Font.h b/include/nw4r/ut/ut_Font.h index 0aefe054..4cda439a 100644 --- a/include/nw4r/ut/ut_Font.h +++ b/include/nw4r/ut/ut_Font.h @@ -52,13 +52,12 @@ public: virtual int GetCharWidth(u16 c) const = 0; // at 0x48 virtual CharWidths GetCharWidths(u16 c) const = 0; // at 0x4C virtual void GetGlyph(Glyph *out, u16 c) const = 0; // at 0x50 + virtual bool HasGlyph(u16 c) const = 0; // at 0x50 virtual FontEncoding GetEncoding() const = 0; // at 0x54 void InitReaderFunc(FontEncoding encode); - CharStrmReader GetCharStrmReader() const { - return CharStrmReader(mReadFunc); - } + CharStrmReader GetCharStrmReader() const; private: CharStrmReader::ReadFunc mReadFunc; // at 0x4 diff --git a/include/nw4r/ut/ut_IOStream.h b/include/nw4r/ut/ut_IOStream.h index 33545909..88e7af7a 100644 --- a/include/nw4r/ut/ut_IOStream.h +++ b/include/nw4r/ut/ut_IOStream.h @@ -15,11 +15,11 @@ public: IOStream() : mIsOpen(false), mCallback(NULL), mCallbackArg(NULL) {} virtual ~IOStream() {} // at 0xC - virtual void Close() = 0; // at 0x10 - virtual s32 Read(void *dst, u32 size) = 0; // at 0x14 + virtual void Close() = 0; // at 0x10 + virtual long Read(void *dst, unsigned long size) = 0; // at 0x14 virtual bool ReadAsync(void *dst, unsigned long size, AsyncCallback callback, void *arg); // at 0x18 - virtual bool Write(const void *src, unsigned long size); // at 0x1C + virtual long Write(const void *src, unsigned long size); // at 0x1C virtual bool WriteAsync(const void *src, unsigned long size, AsyncCallback callback, void *arg); // at 0x20 virtual bool IsBusy() const; // at 0x24 diff --git a/include/nw4r/ut/ut_NandFileStream.h b/include/nw4r/ut/ut_NandFileStream.h index 1e1ef805..d672e46b 100644 --- a/include/nw4r/ut/ut_NandFileStream.h +++ b/include/nw4r/ut/ut_NandFileStream.h @@ -25,8 +25,8 @@ public: }; public: - NandFileStream(const char *path, u32 access); - NandFileStream(const NANDFileInfo *info, u32 access, bool close); + NandFileStream(const char *path, unsigned long access); + NandFileStream(const NANDFileInfo *info, unsigned long access, bool close); virtual ~NandFileStream(); // at 0xC virtual bool IsBusy() const { @@ -68,32 +68,32 @@ public: virtual void Close(); // at 0x10 - virtual s32 Read(void *dst, u32 size); // at 0x14 - virtual bool ReadAsync(void *dst, u32 size, AsyncCallback callback, + virtual long Read(void *dst, unsigned long size); // at 0x14 + virtual bool ReadAsync(void *dst, unsigned long size, AsyncCallback callback, void *arg); // at 0x18 - virtual void Write(const void *src, u32 size); // at 0x1C - virtual bool WriteAsync(const void *src, u32 size, AsyncCallback callback, + virtual long Write(const void *src, unsigned long size); // at 0x1C + virtual bool WriteAsync(const void *src, unsigned long size, AsyncCallback callback, void *arg); // at 0x20 - virtual void Seek(s32 offset, u32 origin); // at 0x44 + virtual void Seek(long offset, unsigned long origin); // at 0x44 - bool Open(const char *path, u32 access); - bool Open(const NANDFileInfo *info, u32 access, bool close) DECOMP_DONT_INLINE; + bool Open(const char *path, unsigned long access); + bool Open(const NANDFileInfo *info, unsigned long access, bool close) DECOMP_DONT_INLINE; private: - static void NandAsyncCallback_(s32 result, NANDCommandBlock *block); + static void NandAsyncCallback_(long result, NANDCommandBlock *block); void Initialize_(); private: FilePosition mFilePosition; // at 0x14 AsyncContext mAsyncContext; // at 0x1C - bool mCanRead; // at 0x164 - bool mCanWrite; // at 0x165 - volatile bool mIsBusy; // at 0x166 - bool mCloseOnDestroy; // at 0x167 - bool mAllowClose; // at 0x168 + bool mCanRead; // at 0x168 + bool mCanWrite; // at 0x169 + volatile bool mIsBusy; // at 0x16A + bool mCloseOnDestroy; // at 0x16B + bool mAllowClose; // at 0x16C }; } // namespace ut diff --git a/include/nw4r/ut/ut_ResFont.h b/include/nw4r/ut/ut_ResFont.h index 61e4e778..c1dc3109 100644 --- a/include/nw4r/ut/ut_ResFont.h +++ b/include/nw4r/ut/ut_ResFont.h @@ -8,12 +8,13 @@ namespace ut { class ResFont : public detail::ResFontBase { public: - static FontInformation* Rebuild(BinaryFileHeader* header); + static FontInformation *Rebuild(BinaryFileHeader *header); ResFont(); ~ResFont(); - bool SetResource(void* buffer); + bool SetResource(void *buffer); + void *RemoveResource(); }; } // namespace ut diff --git a/include/nw4r/ut/ut_ResFontBase.h b/include/nw4r/ut/ut_ResFontBase.h index 35870190..6d7bad76 100644 --- a/include/nw4r/ut/ut_ResFontBase.h +++ b/include/nw4r/ut/ut_ResFontBase.h @@ -6,11 +6,7 @@ namespace nw4r { namespace ut { -enum FontMapMethod { - FONT_MAPMETHOD_LINEAR, - FONT_MAPMETHOD_ARRAY, - FONT_MAPMETHOD_SCAN -}; +enum FontMapMethod { FONT_MAPMETHOD_LINEAR, FONT_MAPMETHOD_ARRAY, FONT_MAPMETHOD_SCAN }; struct FontTextureGlyph { u8 cellWidth; // at 0x0 @@ -24,13 +20,13 @@ struct FontTextureGlyph { u16 sheetLine; // at 0xE u16 sheetWidth; // at 0x10 u16 sheetHeight; // at 0x12 - u8* sheetImage; // at 0x14 + u8 *sheetImage; // at 0x14 }; struct FontWidth { u16 firstChar; // at 0x0 u16 lastChar; // at 0x2 - FontWidth* next; // at 0x4 + FontWidth *next; // at 0x4 CharWidths widthTable[]; // at 0x8 }; @@ -39,7 +35,7 @@ struct FontCodeMap { u16 lastChar; // at 0x2 u16 mappingMethod; // at 0x4 u16 reserved; // at 0x6 - FontCodeMap* next; // at 0x8 + FontCodeMap *next; // at 0x8 u16 mapInfo[]; // at 0xc }; @@ -49,9 +45,9 @@ struct FontInformation { u16 alterCharIndex; // at 0x2 CharWidths defaultWidth; // at 0x4 u8 encoding; // at 0x7 - FontTextureGlyph* fontGlyph; // at 0x8 - FontWidth* fontWidth; // at 0xC - FontCodeMap* fontMap; // at 0x10 + FontTextureGlyph *fontGlyph; // at 0x8 + FontWidth *fontWidth; // at 0xC + FontCodeMap *fontMap; // at 0x10 u8 height; // at 0x14 u8 width; // at 0x15 u8 ascent; // at 0x16 @@ -76,34 +72,37 @@ public: virtual GXTexFmt GetTextureFormat() const; // at 0x30 virtual int GetLineFeed() const; // at 0x34 virtual CharWidths GetDefaultCharWidths() const; // at 0x38 - virtual void SetDefaultCharWidths(const CharWidths& widths); // at 0x3C + virtual void SetDefaultCharWidths(const CharWidths &widths); // at 0x3C virtual bool SetAlternateChar(u16 c); // at 0x40 virtual void SetLineFeed(int lf); // at 0x44 virtual int GetCharWidth(u16 c) const; // at 0x48 virtual CharWidths GetCharWidths(u16 c) const; // at 0x4C - virtual void GetGlyph(Glyph* out, u16 c) const; // at 0x50 - virtual FontEncoding GetEncoding() const; // at 0x54 + virtual void GetGlyph(Glyph *out, u16 c) const; // at 0x50 + virtual bool HasGlyph(u16 c) const; // at 0x54 + virtual FontEncoding GetEncoding() const; // at 0x58 - bool IsManaging(const void* buffer) const { return mResource == buffer; } + bool IsManaging(const void *buffer) const { + return mResource == buffer; + } - void SetResourceBuffer(void* buffer, FontInformation* info); + void SetResourceBuffer(void *buffer, FontInformation *info); + void *RemoveResourceBuffer(); u16 GetGlyphIndex(u16 c) const; u16 FindGlyphIndex(u16 c) const; - u16 FindGlyphIndex(const FontCodeMap* map, u16 c) const; + u16 FindGlyphIndex(const FontCodeMap *map, u16 c) const; - const CharWidths& GetCharWidthsFromIndex(u16 index) const; - const CharWidths& GetCharWidthsFromIndex(const FontWidth* width, - u16 index) const; + const CharWidths &GetCharWidthsFromIndex(u16 index) const; + const CharWidths &GetCharWidthsFromIndex(const FontWidth *width, u16 index) const; - void GetGlyphFromIndex(Glyph* out, u16 index) const; + void GetGlyphFromIndex(Glyph *out, u16 index) const; private: - void* mResource; // at 0x10 - FontInformation* mFontInfo; // at 0x14 - u16 mLastCharCode; // at 0x18 - u16 mLastGlyphIndex; // at 0x18 + void *mResource; // at 0x10 + FontInformation *mFontInfo; // at 0x14 + mutable u16 mLastCharCode; // at 0x18 + mutable u16 mLastGlyphIndex; // at 0x1A }; } // namespace detail diff --git a/include/nw4r/ut/ut_RomFont.h b/include/nw4r/ut/ut_RomFont.h index 30fc5425..e444d362 100644 --- a/include/nw4r/ut/ut_RomFont.h +++ b/include/nw4r/ut/ut_RomFont.h @@ -30,7 +30,8 @@ public: virtual int GetCharWidth(u16 c) const; // at 0x48 virtual CharWidths GetCharWidths(u16 c) const; // at 0x4C virtual void GetGlyph(Glyph *out, u16 c) const; // at 0x50 - virtual FontEncoding GetEncoding() const; // at 0x54 + virtual bool HasGlyph(u16 c) const; // at 0x54 + virtual FontEncoding GetEncoding() const; // at 0x58 bool Load(void *buffer); u32 GetRequireBufferSize(); diff --git a/include/nw4r/ut/ut_TextWriterBase.h b/include/nw4r/ut/ut_TextWriterBase.h index 0dd9e271..71291fbe 100644 --- a/include/nw4r/ut/ut_TextWriterBase.h +++ b/include/nw4r/ut/ut_TextWriterBase.h @@ -64,7 +64,7 @@ public: void SetDrawFlag(u32 flag) { mDrawFlag = flag; } - bool IsDrawFlagSet(u32 mask, u32 flag) const { + bool IsDrawFlagSet(unsigned long mask, u32 flag) const { return (mDrawFlag & mask) == flag; } @@ -78,20 +78,39 @@ public: mTagProcessor = &mDefaultTagProcessor; } + void SetLineHeight(f32 height); f32 GetLineHeight() const; - f32 CalcLineWidth(const T *str, int len); - f32 CalcStringWidth(const T *str, int len) const; - void CalcStringRect(Rect *rect, const T *str, int len) const; + f32 CalcFormatStringWidth(const T *str, ...) const; + f32 CalcFormatStringHeight(const T *str, ...) const; + void CalcFormatStringRect(Rect *rect, const T *str, ...) const; + void CalcVStringRect(Rect *rect, const T *str, va_list args) const; - int VSNPrintf(T *buffer, u32 count, const T *fmt, va_list args); + f32 CalcStringWidth(const T *format, int len) const; + f32 CalcStringHeight(const T *format, int len) const; + void CalcStringRect(Rect *rect, const T *format, int len) const; + + f32 Printf(const T *format, ...); f32 VPrintf(const T *str, va_list args); f32 Print(const T *str, int len); + f32 PrintfMutable(const T *format, ...); + f32 VPrintfMutable(const T *format, va_list args); + f32 PrintMutable(const T *str, int n); + // static int VSNPrintf(T *buffer, unsigned long count, const T *fmt, va_list args); + + static int VSNPrintf(char *buffer, unsigned long count, const char *fmt, va_list args) { + return vsnprintf(buffer, count, fmt, args); + } + + static int VSNPrintf(wchar_t *buffer, unsigned long count, const wchar_t *fmt, va_list args) { + return vswprintf(buffer, count, fmt, args); + } + + f32 CalcLineWidth(const T *format, int len); bool CalcLineRectImpl(Rect *rect, const T **str, int len); void CalcStringRectImpl(Rect *rect, const T *str, int len); - - f32 PrintImpl(const T *str, int len); + f32 PrintImpl(const T *str, int len, bool m); f32 AdjustCursor(f32 *x1, f32 *y1, const T *str, int len); private: @@ -103,19 +122,19 @@ private: TagProcessorBase *mTagProcessor; // at 0x60 static T *mFormatBuffer; - static u32 mFormatBufferSize; + static int mFormatBufferSize; static TagProcessorBase mDefaultTagProcessor; }; -template <> -inline int TextWriterBase::VSNPrintf(char *buffer, u32 count, const char *fmt, va_list args) { - return vsnprintf(buffer, count, fmt, args); -} +// template <> +// int TextWriterBase::VSNPrintf(char *buffer, unsigned long count, const char *fmt, va_list args) { +// return vsnprintf(buffer, count, fmt, args); +// } -template <> -inline int TextWriterBase::VSNPrintf(wchar_t *buffer, u32 count, const wchar_t *fmt, va_list args) { - return vswprintf(buffer, count, fmt, args); -} +// template <> +// int TextWriterBase::VSNPrintf(wchar_t *buffer, unsigned long count, const wchar_t *fmt, va_list args) { +// return vswprintf(buffer, count, fmt, args); +// } } // namespace ut } // namespace nw4r diff --git a/include/rvl/DVD.h b/include/rvl/DVD.h index 00b87a44..35fc9f78 100644 --- a/include/rvl/DVD.h +++ b/include/rvl/DVD.h @@ -6,9 +6,12 @@ extern "C" { #include "rvl/DVD/dvd.h" #include "rvl/DVD/dvd_broadway.h" +#include "rvl/DVD/dvderror.h" #include "rvl/DVD/dvdfatal.h" #include "rvl/DVD/dvdfs.h" #include "rvl/DVD/dvdidutils.h" +#include "rvl/DVD/dvdqueue.h" + #ifdef __cplusplus } diff --git a/include/rvl/DVD/dvd.h b/include/rvl/DVD/dvd.h index 254cdf12..ff968863 100644 --- a/include/rvl/DVD/dvd.h +++ b/include/rvl/DVD/dvd.h @@ -5,14 +5,75 @@ extern "C" { #endif +// OS sets MSB to signal that the device code was successfully read +#define DVD_DEVICE_CODE_READ (1 << 15) +#define MAKE_DVD_DEVICE_CODE(x) (DVD_DEVICE_CODE_READ | (x)) + // Forward declarations +typedef struct DVDCommandBlock; +typedef struct DVDFileInfo; typedef struct OSAlarm; -typedef struct DVDDriveBlock { - char UNK_0x0[0xC]; - UNKWORD WORD_0xC; - char UNK_0x10[0x30 - 0x10]; -} DVDDriveBlock; +typedef enum { + DVD_RESULT_COVER_CLOSED = -4, + DVD_RESULT_CANCELED, + DVD_RESULT_M2, + DVD_RESULT_FATAL, + DVD_RESULT_OK, +} DVDResult; + +typedef enum { + DVD_STATE_FATAL = -1, + DVD_STATE_IDLE, + DVD_STATE_BUSY, + DVD_STATE_WAITING, + DVD_STATE_COVER_CLOSED, + DVD_STATE_NO_DISK, + DVD_STATE_COVER_OPENED, + DVD_STATE_WRONG_DISK_ID, + DVD_STATE_7, + DVD_STATE_PAUSED, + DVD_STATE_9, + DVD_STATE_CANCELED, + DVD_STATE_DISK_ERROR, + DVD_STATE_MOTOR_STOPPED, +} DVDAsyncState; + +typedef enum { + DVD_COVER_BUSY, + DVD_COVER_OPENED, + DVD_COVER_CLOSED, +} DVDCoverState; + +typedef void (*DVDAsyncCallback)(long result, struct DVDFileInfo *info); +typedef void (*DVDCommandCallback)(long result, struct DVDCommandBlock *block); + +typedef struct DVDDiskID { + char game[4]; // at 0x0 + char company[2]; // at 0x4 + u8 disk; // at 0x6 + u8 version; // at 0x7 + u8 strmEnable; // at 0x8 + u8 strmBufSize; // at 0x9 + u8 padding[14]; // at 0xA + u32 rvlMagic; // at 0x18 + u32 gcMagic; // at 0x1C +} DVDDiskID; + +typedef struct DVDCommandBlock { + struct DVDCommandBlock *next; // at 0x0 + struct DVDCommandBlock *prev; // at 0x4 + u32 command; // at 0x8 + volatile s32 state; // at 0xC + u32 offset; // at 0x10 + u32 length; // at 0x14 + void *addr; // at 0x18 + u32 transferSize; // at 0x1C + u32 transferTotal; // at 0x20 + DVDDiskID *id; // at 0x24 + DVDCommandCallback callback; // at 0x28 + void *userData; // at 0x2C +} DVDCommandBlock; typedef struct DVDDriveInfo { u16 revision; // at 0x0 @@ -21,16 +82,34 @@ typedef struct DVDDriveInfo { char padding[32 - 0x8]; } DVDDriveInfo; -typedef void (*DVDInquiryCallback)(s32, DVDDriveBlock *); +typedef struct DVDFileInfo { + DVDCommandBlock block; // at 0x0 + u32 offset; // at 0x30 + u32 size; // at 0x34 + DVDAsyncCallback callback; // at 0x38 +} DVDFileInfo; + +extern volatile u32 __DVDLayoutFormat; void DVDInit(void); - -BOOL DVDInquiryAsync(DVDDriveBlock *, DVDDriveInfo *, DVDInquiryCallback); - +BOOL DVDReadAbsAsyncPrio(DVDCommandBlock *block, void *dst, u32 size, u32 offset, DVDCommandCallback callback, + s32 prio); +BOOL DVDInquiryAsync(DVDCommandBlock *block, DVDDriveInfo *info, DVDCommandCallback callback); +s32 DVDGetCommandBlockStatus(const DVDCommandBlock *block); +s32 DVDGetDriveStatus(void); +void DVDPause(void); +void DVDResume(void); +BOOL DVDCancelAsync(DVDCommandBlock *block, DVDCommandCallback callback); +s32 DVDCancel(DVDCommandBlock *block); +BOOL DVDCancelAllAsync(DVDCommandCallback callback); +const DVDDiskID *DVDGetCurrentDiskID(void); u32 __DVDGetCoverStatus(void); - +void __DVDPrepareResetAsync(DVDCommandCallback callback); void __DVDPrepareReset(void); -BOOL __DVDTestAlarm(struct OSAlarm *); +BOOL __DVDTestAlarm(const struct OSAlarm *alarm); +BOOL __DVDLowBreak(void); +BOOL __DVDStopMotorAsync(DVDCommandBlock *block, DVDCommandCallback callback); +void __DVDRestartMotor(void); #ifdef __cplusplus } diff --git a/include/rvl/DVD/dvd_broadway.h b/include/rvl/DVD/dvd_broadway.h index 6329e2f0..01016ade 100644 --- a/include/rvl/DVD/dvd_broadway.h +++ b/include/rvl/DVD/dvd_broadway.h @@ -5,6 +5,9 @@ extern "C" { #endif +#define DVD_LOW_OFFSET(x) ((x) >> 2) +#define DVD_LOW_SPEED(x) (((x) & 3) << 16) + // Forward declarations typedef struct DVDDiskID; typedef struct DVDDriveInfo; @@ -12,21 +15,22 @@ typedef struct ESPTicket; typedef struct ESPTmd; typedef struct OSAlarm; -/** - * https://wiibrew.org/wiki//dev/di - * Names adjusted to be closer to those seen in assertions - */ typedef enum { - DVD_INTTYPE_TC = (1 << 0), //!< Transaction callback? - DVD_INTTYPE_DE = (1 << 1), //!< Drive error - DVD_INTTYPE_CVR = (1 << 2), //!< Something with DVD cover - DVD_INTTYPE_BR = (1 << 3), //!< Break requested - DVD_INTTYPE_TIME = (1 << 4), //!< Time out - DVD_INTTYPE_SERR = (1 << 5), //!< Security error - DVD_INTTYPE_VERR = (1 << 6), //!< Verify error - DVD_INTTYPE_ARGS = (1 << 7), //!< Bad arguments + DVD_INTTYPE_TC = (1 << 0), // Transaction callback? + DVD_INTTYPE_DE = (1 << 1), // Drive error + DVD_INTTYPE_CVR = (1 << 2), // Something with DVD cover + DVD_INTTYPE_BR = (1 << 3), // Break requested + DVD_INTTYPE_TIME = (1 << 4), // Time out + DVD_INTTYPE_SERR = (1 << 5), // Security error + DVD_INTTYPE_VERR = (1 << 6), // Verify error + DVD_INTTYPE_ARGS = (1 << 7), // Bad arguments } DVDLowIntType; +// DICVR - DI Cover Register (via DVDLowGetCoverRegister) +#define DVD_DICVR_CVR (1 << 0) +#define DVD_DICVR_CVRINTMASK (1 << 1) +#define DVD_DICVR_CVRINT (1 << 2) + typedef void (*DVDLowCallback)(u32 intType); BOOL DVDLowInit(void); diff --git a/include/rvl/DVD/dvderror.h b/include/rvl/DVD/dvderror.h new file mode 100644 index 00000000..1b5fc4e1 --- /dev/null +++ b/include/rvl/DVD/dvderror.h @@ -0,0 +1,38 @@ +#ifndef RVL_SDK_DVD_ERROR_H +#define RVL_SDK_DVD_ERROR_H +#include +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*DVDErrorCallback)(s32 result, s32 arg1); + +#define DVD_ERROR_CMD_MAX 5 + +typedef struct DVDErrorInfo { + char game[4]; // at 0x0 + u8 disk; // at 0x4 + u8 version; // at 0x5 + u32 error; // at 0x8 + s32 sec; // at 0xC + u32 disr; // at 0x10 + u32 dicr; // at 0x14 + u32 next; // at 0x18 + + struct { + u32 command; // at 0x1C + u32 param1; // at 0x20 + u32 param2; // at 0x24 + u32 intType; // at 0x28 + u32 tick; // at 0x2C + } info[DVD_ERROR_CMD_MAX]; +} DVDErrorInfo; + +extern DVDErrorInfo __ErrorInfo; + +void __DVDStoreErrorCode(u32 error, DVDErrorCallback callback); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/rvl/DVD/dvdfs.h b/include/rvl/DVD/dvdfs.h index 7458692c..c0747f47 100644 --- a/include/rvl/DVD/dvdfs.h +++ b/include/rvl/DVD/dvdfs.h @@ -1,36 +1,24 @@ #ifndef RVL_SDK_DVD_FS_H #define RVL_SDK_DVD_FS_H +#include +#include #include + #ifdef __cplusplus extern "C" { #endif +extern OSThreadQueue __DVDThreadQueue; extern BOOL __DVDLongFileNameFlag; -typedef void (*DVDCommandCallback)(s32, struct DVDCommandBlock *); -typedef void (*DVDFileCallback)(s32, struct DVDFileInfo *); - -typedef struct DVDCommandBlock { - /* 0x00 */ struct DVDCommandBlock *next; - /* 0x04 */ struct DVDCommandBlock *prev; - /* 0x08 */ u32 command; - /* 0x0c */ s32 state; - /* 0x10 */ u32 offset; - /* 0x14 */ u32 length; - /* 0x18 */ void *addr; - /* 0x1c */ u32 currTransferSize; - /* 0x20 */ u32 transferredSize; - /* 0x24 */ DVDDiskID *id; - /* 0x28 */ DVDCommandCallback callback; - /* 0x2c */ void *userData; -} DVDCommandBlock; - -typedef struct DVDFileInfo { - /* 0x00 */ DVDCommandBlock cb; - /* 0x30 */ u32 startAddr; - /* 0x34 */ u32 length; - /* 0x38 */ DVDFileCallback *callback; -} DVDFileInfo; +void __DVDFSInit(void); +s32 DVDConvertPathToEntrynum(const char *path); +BOOL DVDFastOpen(s32 entrynum, DVDFileInfo *info); +BOOL DVDOpen(const char *path, DVDFileInfo *info); +BOOL DVDClose(DVDFileInfo *info); +BOOL DVDGetCurrentDir(char *buffer, u32 maxlen); +BOOL DVDReadAsyncPrio(DVDFileInfo *info, void *dst, s32 size, s32 offset, DVDAsyncCallback callback, s32 prio); +s32 DVDReadPrio(DVDFileInfo *info, void *dst, s32 size, s32 offset, s32 prio); #ifdef __cplusplus } diff --git a/include/rvl/DVD/dvdidutils.h b/include/rvl/DVD/dvdidutils.h index 2dceb761..23a7d3df 100644 --- a/include/rvl/DVD/dvdidutils.h +++ b/include/rvl/DVD/dvdidutils.h @@ -1,22 +1,12 @@ #ifndef RVL_SDK_DVD_ID_UTILS_H #define RVL_SDK_DVD_ID_UTILS_H +#include #include + #ifdef __cplusplus extern "C" { #endif -typedef struct DVDDiskID { - char game[4]; // at 0x0 - char company[2]; // at 0x4 - u8 disk; // at 0x6 - u8 version; // at 0x7 - u8 strmEnable; // at 0x8 - u8 strmBufSize; // at 0x9 - u8 padding[14]; // at 0xA - u32 rvlMagic; // at 0x18 - u32 gcMagic; // at 0x1C -} DVDDiskID; - BOOL DVDCompareDiskID(const DVDDiskID *id1, const DVDDiskID *id2); #ifdef __cplusplus diff --git a/include/rvl/DVD/dvdqueue.h b/include/rvl/DVD/dvdqueue.h new file mode 100644 index 00000000..0b3a7a3d --- /dev/null +++ b/include/rvl/DVD/dvdqueue.h @@ -0,0 +1,28 @@ +#ifndef RVL_SDK_DVD_QUEUE_H +#define RVL_SDK_DVD_QUEUE_H +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + DVD_PRIO_HIGHEST, + DVD_PRIO_HIGH, + DVD_PRIO_MEDIUM, + DVD_PRIO_LOW, + + DVD_PRIO_MAX, +} DVDQueuePriority; + +void __DVDClearWaitingQueue(void); +BOOL __DVDPushWaitingQueue(s32 prio, DVDCommandBlock *block); +DVDCommandBlock *__DVDPopWaitingQueue(void); +BOOL __DVDCheckWaitingQueue(void); +DVDCommandBlock *__DVDGetNextWaitingQueue(void); +BOOL __DVDDequeueWaitingQueue(const DVDCommandBlock *block); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/rvl/GX/GXInit.h b/include/rvl/GX/GXInit.h index 32369c91..cdae0895 100644 --- a/include/rvl/GX/GXInit.h +++ b/include/rvl/GX/GXInit.h @@ -1,5 +1,6 @@ #ifndef RVL_SDK_GX_INIT_H #define RVL_SDK_GX_INIT_H +#include #include #ifdef __cplusplus extern "C" { @@ -49,11 +50,11 @@ typedef struct _GXData { char UNK_0x230[0x254 - 0x230]; u32 genMode; // at 0x254 char UNK_0x258[0x520 - 0x258]; - GXAttrType normalType; // at 0x520 - GXBool normal; // at 0x524 - GXBool binormal; // at 0x525 - GXProjMtxType projType; // at 0x528 - f32 proj[6]; // at 0x52C + GXAttrType normalType; // at 0x520 + GXBool normal; // at 0x524 + GXBool binormal; // at 0x525 + GXProjectionType projType; // at 0x528 + f32 proj[6]; // at 0x52C union { struct { f32 vpOx; // at 0x544 @@ -80,6 +81,8 @@ extern GXData *const __GXData; // I hate typing this name out #define gxdt __GXData +GXFifoObj *GXInit(void *, u32); + #ifdef __cplusplus } #endif diff --git a/include/rvl/GX/GXPixel.h b/include/rvl/GX/GXPixel.h index 64637b06..cc110d67 100644 --- a/include/rvl/GX/GXPixel.h +++ b/include/rvl/GX/GXPixel.h @@ -19,7 +19,7 @@ void GXSetColorUpdate(GXBool enable); void GXSetAlphaUpdate(GXBool enable); void GXSetZMode(GXBool enableTest, GXCompare func, GXBool enableUpdate); void GXSetZCompLoc(GXBool beforeTex); -void GXSetPixelFmt(GXPixelFmt pixelFmt, GXZFmt zFmt); +void GXSetPixelFmt(GXPixelFmt pixelFmt, GXZFmt16 zFmt); void GXSetDither(GXBool enable); void GXSetDstAlpha(GXBool enable, u8 alpha); void GXSetFieldMask(GXBool enableEven, GXBool enableOdd); diff --git a/include/rvl/GX/GXTransform.h b/include/rvl/GX/GXTransform.h index 2842d634..780af102 100644 --- a/include/rvl/GX/GXTransform.h +++ b/include/rvl/GX/GXTransform.h @@ -7,7 +7,7 @@ extern "C" { #endif -void GXSetProjection(const Mtx44 proj, GXProjMtxType type); +void GXSetProjection(const Mtx44 proj, GXProjectionType type); void GXSetProjectionv(const f32 proj[7]); void GXGetProjectionv(f32 proj[7]); void GXLoadPosMtxImm(const Mtx mtx, u32 id); diff --git a/include/rvl/GX/GXTypes.h b/include/rvl/GX/GXTypes.h index c2c1c424..99094c37 100644 --- a/include/rvl/GX/GXTypes.h +++ b/include/rvl/GX/GXTypes.h @@ -158,7 +158,17 @@ typedef enum _GXChannelID { GX_COLOR_NULL = 255 } GXChannelID; -// TODO: Fabricated names from patent +typedef enum _GXCITexFmt { + GX_TF_C4 = 8, + GX_TF_C8, + GX_TF_C14X2, +} GXCITexFmt; + +typedef enum _GXClearZ { + GX_CLEAR_Z_MIN = 0, + GX_CLEAR_Z_MAX = (1 << 24) - 1, +} GXClearZ; + typedef enum _GXClipMode { // "ClipDisable" in XF mem, so 0 = enable GX_CLIP_ENABLE, @@ -208,6 +218,13 @@ typedef enum _GXCompType { GX_RGBA8 } GXCompType; +typedef enum _GXCopyClamp { + GX_CLAMP_NONE, + GX_CLAMP_TOP, + GX_CLAMP_BOTTOM, + GX_CLAMP_ALL, +} GXCopyClamp; + typedef enum _GXCullMode { GX_CULL_NONE, GX_CULL_FRONT, GX_CULL_BACK, GX_CULL_ALL } GXCullMode; typedef enum _GXDiffuseFn { GX_DF_NONE, GX_DF_SIGN, GX_DF_CLAMP } GXDiffuseFn; @@ -354,16 +371,16 @@ typedef enum _GXIndTexWrap { } GXIndTexWrap; typedef enum _GXLightID { - GX_LIGHT0 = 1, - GX_LIGHT1 = 2, - GX_LIGHT2 = 4, - GX_LIGHT3 = 8, - GX_LIGHT4 = 16, - GX_LIGHT5 = 32, - GX_LIGHT6 = 64, - GX_LIGHT7 = 128, + GX_LIGHT0 = (1 << 0), + GX_LIGHT1 = (1 << 1), + GX_LIGHT2 = (1 << 2), + GX_LIGHT3 = (1 << 3), + GX_LIGHT4 = (1 << 4), + GX_LIGHT5 = (1 << 5), + GX_LIGHT6 = (1 << 6), + GX_LIGHT7 = (1 << 7), - GX_MAX_LIGHT = 256, + GX_MAX_LIGHT = (1 << 8), GX_LIGHT_NULL = 0 } GXLightID; @@ -386,7 +403,6 @@ typedef enum _GXLogicOp { GX_LO_SET } GXLogicOp; -// TODO: Fabricated name typedef enum _GXMtxType { GX_MTX_3x4, GX_MTX_2x4, @@ -432,7 +448,7 @@ typedef enum _GXPrimitive { GX_QUADS = 0x80, } GXPrimitive; -typedef enum _GXProjMtxType { GX_PERSPECTIVE, GX_ORTHOGRAPHIC } GXProjMtxType; +typedef enum _GXProjectionType { GX_PERSPECTIVE, GX_ORTHOGRAPHIC } GXProjectionType; typedef enum _GXSpotFn { GX_SP_OFF, GX_SP_FLAT, GX_SP_COS, GX_SP_COS2, GX_SP_SHARP, GX_SP_RING1, GX_SP_RING2 } GXSpotFn; @@ -509,10 +525,12 @@ typedef enum _GXTevRegID { } GXTevRegID; typedef enum _GXTevScale { - GX_TEV_SCALE_0, - GX_TEV_SCALE_1, - GX_TEV_SCALE_2, - GX_TEV_SCALE_3, + GX_CS_SCALE_1, + GX_CS_SCALE_2, + GX_CS_SCALE_4, + GX_CS_DIVIDE_2, + + GX_MAX_TEVSCALE } GXTevScale; typedef enum _GXTevStageID { @@ -624,6 +642,8 @@ typedef enum _GXTevKColorSel { GX_TEV_KCSEL_K3_A } GXTevKColorSel; +typedef enum _GXTevMode { GX_MODULATE, GX_DECAL, GX_REPLACE, GX_PASSCLR, GX_BLEND } GXTevMode; + typedef enum _GXTexCoordID { GX_TEXCOORD0, GX_TEXCOORD1, @@ -733,9 +753,9 @@ typedef enum _GXTexMapID { GX_TEX_DISABLE } GXTexMapID; -// TODO: Fabricated names typedef enum _GXTexMtx { // Any dimension (in standard XF matrix memory) + // Enum represents base row of matrix GX_TEXMTX0 = 30, GX_TEXMTX1 = 33, GX_TEXMTX2 = 36, @@ -746,18 +766,31 @@ typedef enum _GXTexMtx { GX_TEXMTX7 = 51, GX_TEXMTX8 = 54, GX_TEXMTX9 = 57, + GX_TEXMTX_IDENT = 60, // 3x4 matrices (in dual-tex XF matrix memory) - GX_DTEXMTX0 = 64, - GX_DTEXMTX1 = 67, - GX_DTEXMTX2 = 70, - GX_DTEXMTX3 = 73, - GX_DTEXMTX4 = 76, - GX_DTEXMTX5 = 79, - GX_DTEXMTX6 = 82, - GX_DTEXMTX7 = 85, - GX_DTEXMTX8 = 88, - GX_DTEXMTX9 = 91, + // Enum represents base row of matrix + GX_DUALMTX0 = 64, + GX_DUALMTX1 = 67, + GX_DUALMTX2 = 70, + GX_DUALMTX3 = 73, + GX_DUALMTX4 = 76, + GX_DUALMTX5 = 79, + GX_DUALMTX6 = 82, + GX_DUALMTX7 = 85, + GX_DUALMTX8 = 88, + GX_DUALMTX9 = 91, + GX_DUALMTX10 = 94, + GX_DUALMTX11 = 97, + GX_DUALMTX12 = 100, + GX_DUALMTX13 = 103, + GX_DUALMTX14 = 106, + GX_DUALMTX15 = 109, + GX_DUALMTX16 = 112, + GX_DUALMTX17 = 115, + GX_DUALMTX18 = 118, + GX_DUALMTX19 = 121, + GX_DUALMTX_IDENT = 125, } GXTexMtx; typedef enum _GXTexWrapMode { @@ -776,9 +809,8 @@ typedef enum _GXTlutFmt { GX_MAX_TLUTFMT } GXTlutFmt; -// TODO: Fabricated name typedef enum _GXVtxFmt { - GX_VTXFMT0, // from patent + GX_VTXFMT0, GX_VTXFMT1, GX_VTXFMT2, GX_VTXFMT3, @@ -787,15 +819,24 @@ typedef enum _GXVtxFmt { GX_VTXFMT6, GX_VTXFMT7, - GX_MAX_VTXFMT, + GX_MAX_VTXFMT } GXVtxFmt; -typedef enum _GXZFmt { - GX_ZC_LINEAR, // from patent - GX_ZC_NEAR, // from Dolphin - GX_ZC_MID, // from Dolphin - GX_ZC_FAR, // from Dolphin -} GXZFmt; +typedef enum _GXZFmt16 { + GX_ZC_LINEAR, + GX_ZC_NEAR, + GX_ZC_MID, + GX_ZC_FAR, +} GXZFmt16; + +// From patent +typedef enum _GXZTexOp { + GX_ZT_DISABLE, + GX_ZT_ADD, + GZ_ZT_REPLACE, + + GX_MAX_ZTEXOP +} GXZTexOp; #ifdef __cplusplus } diff --git a/include/rvl/NAND/nand.h b/include/rvl/NAND/nand.h index bae91f37..eb803253 100644 --- a/include/rvl/NAND/nand.h +++ b/include/rvl/NAND/nand.h @@ -66,7 +66,7 @@ typedef enum { NAND_PERM_RWALL = NAND_PERM_RALL | NAND_PERM_WALL } NANDPermission; -typedef void (*NANDAsyncCallback)(s32 result, struct NANDCommandBlock *block); +typedef void (*NANDAsyncCallback)(long result, struct NANDCommandBlock *block); typedef struct NANDStatus { u32 ownerId; // at 0x0 @@ -76,8 +76,8 @@ typedef struct NANDStatus { } NANDStatus; typedef struct NANDFileInfo { - s32 fd; // at 0x0 - s32 tempFd; // at 0x4 + long fd; // at 0x0 + long tempFd; // at 0x4 char openPath[FS_MAX_PATH]; // at 0x8 char tempPath[FS_MAX_PATH]; // at 0x48 u8 access; // at 0x88 @@ -118,6 +118,7 @@ typedef struct NANDCommandBlock { u32 workBlocks; // at 0xAC u32 workInodes; // at 0xB0 const char **dir; // at 0xB4 + int simpleFlag; // } NANDCommandBlock; typedef struct NANDBanner { @@ -157,7 +158,7 @@ NANDResult NANDPrivateCreateDirAsync(const char *path, u8 perm, u8 attr, NANDAsy NANDResult NANDMove(const char *from, const char *to); -NANDResult NANDGetLength(NANDFileInfo *info, u32 *length); +NANDResult NANDGetLength(NANDFileInfo *info, unsigned long *length); NANDResult NANDGetLengthAsync(NANDFileInfo *info, u32 *lengthOut, NANDAsyncCallback callback, NANDCommandBlock *block); NANDResult NANDGetStatus(const char *path, NANDStatus *status); diff --git a/src/egg/core/eggAsyncDisplay.cpp b/src/egg/core/eggAsyncDisplay.cpp index 0901271f..d2b4bf81 100644 --- a/src/egg/core/eggAsyncDisplay.cpp +++ b/src/egg/core/eggAsyncDisplay.cpp @@ -196,9 +196,9 @@ void AsyncDisplay::clearEFB(u16 fbWidth, u16 fbHeight, u16 x, u16 y, u16 width, GXSetTevColor(GX_TEVREG0, color); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0); - GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_TEV_SCALE_0, 1, GX_TEVPREV); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV); GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); - GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_TEV_SCALE_0, 1, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV); GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); GXSetZTexture(2, GX_TF_Z24X8, 0); GXSetZCompLoc(false); diff --git a/src/nw4r/ut/ut_CharWriter.cpp b/src/nw4r/ut/ut_CharWriter.cpp index e69de29b..1281dc01 100644 --- a/src/nw4r/ut/ut_CharWriter.cpp +++ b/src/nw4r/ut/ut_CharWriter.cpp @@ -0,0 +1,260 @@ + +#include + +namespace { + +static void SetupGXCommon() { + static const nw4r::ut::Color fog = 0; + + GXSetFog(GX_FOG_NONE, fog, 0.0f, 0.0f, 0.0f, 0.0f); + GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); + GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0); + GXSetNumChans(1); + GXSetChanCtrl(GX_COLOR0A0, FALSE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetChanCtrl(GX_COLOR1A1, FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetNumTexGens(1); + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX_IDENT, FALSE, GX_DUALMTX_IDENT); + GXSetNumIndStages(0); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET); +} + +} // namespace + +namespace nw4r { +namespace ut { + +CharWriter::CharWriter() : mAlpha(255), mIsWidthFixed(false), mFixedWidth(0.0f), mFont(NULL) { + mLoadingTexture.Reset(); + ResetColorMapping(); + SetGradationMode(GRADMODE_NONE); + SetTextColor(Color(0xFFFFFFFF)); + SetScale(1.0f, 1.0f); + SetCursor(0.0f, 0.0f, 0.0f); + EnableLinearFilter(true, true); +} + +CharWriter::~CharWriter() {} + +void CharWriter::SetupGX() { + ResetTextureCache(); + + if (mColorMapping.min != 0x00000000 || mColorMapping.max != 0xFFFFFFFF) { + SetupGXWithColorMapping(mColorMapping.min, mColorMapping.max); + } else if (mFont != NULL) { + switch (mFont->GetTextureFormat()) { + case GX_TF_I4: + case GX_TF_I8: + SetupGXForI(); + break; + case GX_TF_IA4: + case GX_TF_IA8: + SetupGXDefault(); + break; + case GX_TF_RGB565: + case GX_TF_RGB5A3: + case GX_TF_RGBA8: + SetupGXForRGBA(); + break; + default: + SetupGXDefault(); + break; + } + } else { + SetupGXDefault(); + } +} + +void CharWriter::SetFontSize(f32 width, f32 height) { + SetScale(width / mFont->GetWidth(), height / mFont->GetHeight()); +} + +void CharWriter::SetFontSize(f32 height) { + f32 scale = height / mFont->GetHeight(); + SetScale(scale, scale); +} + +f32 CharWriter::GetFontWidth() const { + return mScale.x * mFont->GetWidth(); +} + +f32 CharWriter::GetFontHeight() const { + return mScale.y * mFont->GetHeight(); +} + +f32 CharWriter::GetFontAscent() const { + return mScale.y * mFont->GetAscent(); +} + +f32 CharWriter::GetFontDescent() const { + return mScale.y * mFont->GetDescent(); +} + +void CharWriter::EnableLinearFilter(bool atSmall, bool atLarge) { + mFilter.atSmall = atSmall ? GX_LINEAR : GX_NEAR; + mFilter.atLarge = atLarge ? GX_LINEAR : GX_NEAR; +} + +f32 CharWriter::Print(u16 ch) { + f32 width; + f32 left; + + Glyph glyph; + mFont->GetGlyph(&glyph, ch); + + if (mIsWidthFixed) { + width = mFixedWidth; + left = (width - glyph.widths.charWidth * mScale.x) / 2 + (glyph.widths.leftSpacing * mScale.x); + } else { + width = glyph.widths.charWidth * mScale.x; + left = glyph.widths.leftSpacing * mScale.x; + } + + PrintGlyph(mCursorPos.x + left, mCursorPos.y, mCursorPos.z, glyph); + mCursorPos.x += width; + + return width; +} + +void CharWriter::PrintGlyph(f32 x, f32 y, f32 z, const Glyph &glyph) { + f32 x2 = x + (glyph.widths.glyphWidth * mScale.x); + f32 y2 = y + (glyph.height * mScale.y); + + u32 posLeft = glyph.cellX; + u16 texLeft = 0x8000 * posLeft / glyph.texWidth; + + u32 posTop = glyph.cellY; + u16 texTop = 0x8000 * posTop / glyph.texHeight; + + u32 posRight = posLeft + glyph.widths.glyphWidth; + u16 texRight = 0x8000 * posRight / glyph.texWidth; + + u32 posBottom = posTop + glyph.height; + u16 texBottom = 0x8000 * posBottom / glyph.texHeight; + + LoadTexture(glyph, GX_TEXMAP0); + + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + { + GXPosition3f32(x, y, z); + GXColor1u32(mVertexColor.tl); + GXTexCoord2s16(texLeft, texTop); + + GXPosition3f32(x2, y, z); + GXColor1u32(mVertexColor.tr); + GXTexCoord2s16(texRight, texTop); + + GXPosition3f32(x2, y2, z); + GXColor1u32(mVertexColor.br); + GXTexCoord2s16(texRight, texBottom); + + GXPosition3f32(x, y2, z); + GXColor1u32(mVertexColor.bl); + GXTexCoord2s16(texLeft, texBottom); + } + // GXEnd(); +} + +void CharWriter::LoadTexture(const Glyph &glyph, GXTexMapID slot) { + LoadingTexture loadingTexture; + + loadingTexture.slot = slot; + loadingTexture.texture = glyph.texture; + loadingTexture.filter = mFilter; + + if (loadingTexture != mLoadingTexture) { + GXTexObj texObj; + GXInitTexObj(&texObj, glyph.texture, glyph.texWidth, glyph.texHeight, glyph.format, GX_CLAMP, GX_CLAMP, FALSE); + GXInitTexObjLOD(&texObj, mFilter.atSmall, mFilter.atLarge, 0.0f, 0.0f, 0.0f, FALSE, FALSE, GX_ANISO_1); + GXLoadTexObj(&texObj, slot); + + mLoadingTexture = loadingTexture; + } +} + +void CharWriter::UpdateVertexColor() { + // clang-format off + mVertexColor.tl = mTextColor.start; + mVertexColor.tr = mTextColor.gradMode != GRADMODE_H ? mTextColor.start : mTextColor.end; + mVertexColor.bl = mTextColor.gradMode != GRADMODE_V ? mTextColor.start : mTextColor.end; + mVertexColor.br = mTextColor.gradMode == GRADMODE_NONE ? mTextColor.start : mTextColor.end; + // clang-format on + + mVertexColor.tl.a = (mVertexColor.tl.a * mAlpha) / 255, mVertexColor.tr.a = (mVertexColor.tr.a * mAlpha) / 255; + mVertexColor.bl.a = (mVertexColor.bl.a * mAlpha) / 255; + mVertexColor.br.a = (mVertexColor.br.a * mAlpha) / 255; +} + +void CharWriter::SetupVertexFormat() { + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U16, 15); + + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); +} + +void CharWriter::SetupGXDefault() { + SetupGXCommon(); + + GXSetNumTevStages(1); + GXSetTevDirect(GX_TEVSTAGE0); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); + + SetupVertexFormat(); +} + +void CharWriter::SetupGXWithColorMapping(Color min, Color max) { + SetupGXCommon(); + + GXSetNumTevStages(2); + GXSetTevDirect(GX_TEVSTAGE0); + GXSetTevDirect(GX_TEVSTAGE1); + + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + + GXSetTevColor(GX_TEVREG0, min); + GXSetTevColor(GX_TEVREG1, max); + + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C0, GX_CC_C1, GX_CC_TEXC, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_A0, GX_CA_A1, GX_CA_TEXA, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV); + + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_CPREV, GX_CC_RASC, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_APREV, GX_CA_RASA, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV); + + SetupVertexFormat(); +} + +void CharWriter::SetupGXForI() { + SetupGXCommon(); + + GXSetNumTevStages(1); + GXSetTevDirect(GX_TEVSTAGE0); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV); + + SetupVertexFormat(); +} + +void CharWriter::SetupGXForRGBA() { + SetupGXDefault(); +} + +CharWriter::LoadingTexture CharWriter::mLoadingTexture; + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_DvdFileStream.cpp b/src/nw4r/ut/ut_DvdFileStream.cpp index e69de29b..317bbc40 100644 --- a/src/nw4r/ut/ut_DvdFileStream.cpp +++ b/src/nw4r/ut/ut_DvdFileStream.cpp @@ -0,0 +1,180 @@ +#include + +namespace nw4r { +namespace ut { + +NW4R_UT_RTTI_DEF_DERIVED(DvdFileStream, FileStream); + +void DvdFileStream::DvdAsyncCallback_(long result, DVDFileInfo *info) { + DvdFileStream *self = reinterpret_cast(info)->stream; + + self->mIsBusy = false; + self->mResult = result; + + if (self->mCallback != NULL) { + self->mCallback(result, self, self->mCallbackArg); + } +} + +void DvdFileStream::DvdCBAsyncCallback_(long result, DVDCommandBlock *block) { + DvdFileStream *self = reinterpret_cast(block)->stream; + + self->mIsCancelling = false; + + if (self->mCancelCallback != NULL) { + self->mCancelCallback(result, self, self->mCancelCallbackArg); + } +} + +void DvdFileStream::Initialize_() { + mCloseOnDestroy = false; + mAllowClose = false; + mIsOpen = false; + mPriority = DVD_PRIO_MEDIUM; + mIsBusy = false; + mCallback = NULL; + mCallbackArg = NULL; + mResult = DVD_RESULT_OK; + mCancelCallback = NULL; + mIsCancelling = false; + mCancelCallbackArg = NULL; + mAsyncContext.stream = this; +} + +DvdFileStream::DvdFileStream(long entrynum) { + Initialize_(); + Open(entrynum); +} + +DvdFileStream::DvdFileStream(const DVDFileInfo *info, bool close) { + Initialize_(); + Open(info, close); +} + +DvdFileStream::~DvdFileStream() { + if (mCloseOnDestroy) { + Close(); + } +} + +bool DvdFileStream::Open(s32 entrynum) { + if (mCloseOnDestroy) { + Close(); + } + + if (DVDFastOpen(entrynum, &mAsyncContext.info)) { + mFilePosition.SetFileSize(mAsyncContext.info.size); + mFilePosition.Seek(0, SEEK_BEG); + + mCloseOnDestroy = true; + mAllowClose = true; + mIsOpen = true; + + return true; + } + + return false; +} + +bool DvdFileStream::Open(const DVDFileInfo *info, bool close) { + if (mCloseOnDestroy) { + Close(); + } + + mAsyncContext.info = *info; + mFilePosition.SetFileSize(mAsyncContext.info.size); + mFilePosition.Seek(0, SEEK_BEG); + + mCloseOnDestroy = false; + mAllowClose = close; + mIsOpen = true; + + return true; +} + +void DvdFileStream::Close() { + if (mAllowClose && mIsOpen) { + DVDClose(&mAsyncContext.info); + mIsOpen = false; + } +} + +long DvdFileStream::Read(void *dst, unsigned long size) { + size = AdjustReadLength_(size); + + long result = DVDReadPrio(&mAsyncContext.info, dst, size, mFilePosition.Tell(), mPriority); + + if (result > 0) { + mFilePosition.Skip(result); + } + + return result; +} + +bool DvdFileStream::ReadAsync(void *dst, unsigned long size, AsyncCallback callback, void *arg) { + size = AdjustReadLength_(size); + + bool success = DvdFileStream::PeekAsync(dst, size, callback, arg); + + if (success) { + mFilePosition.Skip(size); + } else { + mIsBusy = false; + } + + return success; +} + +long DvdFileStream::Peek(void *dst, unsigned long size) { + size = AdjustReadLength_(size); + + return DVDReadPrio(&mAsyncContext.info, dst, size, mFilePosition.Tell(), mPriority); +} + +bool DvdFileStream::PeekAsync(void *dst, unsigned long size, AsyncCallback callback, void *arg) { + mCallback = callback; + mCallbackArg = arg; + mIsBusy = true; + + size = AdjustReadLength_(size); + + return DVDReadAsyncPrio(&mAsyncContext.info, dst, size, mFilePosition.Tell(), DvdAsyncCallback_, mPriority); +} + +void DvdFileStream::Seek(long offset, unsigned long origin) { + mFilePosition.Seek(offset, origin); +} + +void DvdFileStream::Cancel() { + DVDCancel(&mAsyncContext.info.block); +} + +bool DvdFileStream::CancelAsync(AsyncCallback callback, void *arg) { + mCancelCallback = callback; + mCancelCallbackArg = arg; + + BOOL success = DVDCancelAsync(&mAsyncContext.info.block, DvdCBAsyncCallback_); + + if (success) { + mIsCancelling = true; + } + + return success; +} + +unsigned long DvdFileStream::AdjustReadLength_(unsigned long len) { + u32 fileOffset = mFilePosition.Tell(); + u32 fileSize = mFilePosition.GetFileSize(); + + u32 alignSize = RoundUp(fileSize, 32); + u32 alignPos = RoundUp(fileOffset + len, 32); + + if (alignPos > alignSize) { + len = RoundUp(fileSize - fileOffset, 32); + } + + return len; +} + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_DvdLockedFileStream.cpp b/src/nw4r/ut/ut_DvdLockedFileStream.cpp index e69de29b..eb18ac54 100644 --- a/src/nw4r/ut/ut_DvdLockedFileStream.cpp +++ b/src/nw4r/ut/ut_DvdLockedFileStream.cpp @@ -0,0 +1,93 @@ +#include +#include + +namespace nw4r { +namespace ut { + +NW4R_UT_RTTI_DEF_DERIVED(DvdLockedFileStream, DvdFileStream); + +OSThreadQueue DvdLockedFileStream::sThreadQueue; +OSMutex DvdLockedFileStream::sMutex; +bool DvdLockedFileStream::sInitialized = false; + +void DvdLockedFileStream::InitMutex_() { + BOOL enabled = OSDisableInterrupts(); + + if (!sInitialized) { + OSInitMutex(&sMutex); + OSInitThreadQueue(&sThreadQueue); + sInitialized = true; + } + + OSRestoreInterrupts(enabled); +} + +DvdLockedFileStream::DvdLockedFileStream(long entrynum) : DvdFileStream(entrynum) { + mCancelFlag = false; + InitMutex_(); +} + +DvdLockedFileStream::DvdLockedFileStream(const DVDFileInfo *info, bool close) : DvdFileStream(info, close) { + mCancelFlag = false; + InitMutex_(); +} + +DvdLockedFileStream::~DvdLockedFileStream() {} + +void DvdLockedFileStream::Close() { + DvdFileStream::Close(); + mCancelFlag = false; +} + +long DvdLockedFileStream::Read(void *dst, unsigned long size) { + if (!LockMutex()) { + return DVD_RESULT_CANCELED; + } + long ret = DvdFileStream::Read(dst, size); + UnlockMutex(); + return ret; +} + +long DvdLockedFileStream::Peek(void *dst, unsigned long size) { + if (!LockMutex()) { + return DVD_RESULT_CANCELED; + } + long ret = DvdFileStream::Peek(dst, size); + UnlockMutex(); + return ret; +} + +void DvdLockedFileStream::Cancel() { + CancelMutex(); + DvdFileStream::Cancel(); +} + +bool DvdLockedFileStream::LockMutex() { + BOOL enabled = OSDisableInterrupts(); + while (!OSTryLockMutex(&sMutex)) { + OSSleepThread(&sThreadQueue); + if (mCancelFlag) { + OSRestoreInterrupts(enabled); + return false; + } + }; + OSRestoreInterrupts(enabled); + return true; +} + +void DvdLockedFileStream::UnlockMutex() { + BOOL enabled = OSDisableInterrupts(); + OSUnlockMutex(&sMutex); + OSWakeupThread(&sThreadQueue); + OSRestoreInterrupts(enabled); +} + +void DvdLockedFileStream::CancelMutex() { + BOOL enabled = OSDisableInterrupts(); + mCancelFlag = true; + OSWakeupThread(&sThreadQueue); + OSRestoreInterrupts(enabled); +} + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_Font.cpp b/src/nw4r/ut/ut_Font.cpp index e69de29b..0032e911 100644 --- a/src/nw4r/ut/ut_Font.cpp +++ b/src/nw4r/ut/ut_Font.cpp @@ -0,0 +1,25 @@ +#include + +namespace nw4r { +namespace ut { + +void Font::InitReaderFunc(FontEncoding encode) { + switch (encode) { + case FONT_ENCODE_UTF8: + mReadFunc = &CharStrmReader::ReadNextCharUTF8; + break; + case FONT_ENCODE_UTF16: + mReadFunc = &CharStrmReader::ReadNextCharUTF16; + break; + case FONT_ENCODE_SJIS: + mReadFunc = &CharStrmReader::ReadNextCharSJIS; + break; + case FONT_ENCODE_CP1252: + default: + mReadFunc = &CharStrmReader::ReadNextCharCP1252; + break; + } +} + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_IOStream.cpp b/src/nw4r/ut/ut_IOStream.cpp index dec6c090..01c7fed0 100644 --- a/src/nw4r/ut/ut_IOStream.cpp +++ b/src/nw4r/ut/ut_IOStream.cpp @@ -9,7 +9,7 @@ bool IOStream::ReadAsync(void *dst, unsigned long size, AsyncCallback callback, return false; } -bool IOStream::Write(const void *src, unsigned long size) { +long IOStream::Write(const void *src, unsigned long size) { return false; } diff --git a/src/nw4r/ut/ut_LockedCache.cpp b/src/nw4r/ut/ut_LockedCache.cpp index e69de29b..3972e471 100644 --- a/src/nw4r/ut/ut_LockedCache.cpp +++ b/src/nw4r/ut/ut_LockedCache.cpp @@ -0,0 +1,104 @@ +#include + +namespace nw4r { +namespace ut { +namespace { + +class LCImpl { +public: + class Lock_ { + public: + Lock_(LCImpl &lc) : mMutex(lc.mMutex) { + OSLockMutex(&mMutex); + } + ~Lock_() { + OSUnlockMutex(&mMutex); + } + + private: + OSMutex &mMutex; // at 0x0 + }; + +public: + LCImpl() : mIsEnabled(false) { + OSInitMutex(&mMutex); + } + + void Enable() { + Lock_ lock(*this); + + if (!mIsEnabled) { + LCEnable(); + mIsEnabled = true; + } + } + + void Disable() { + Lock_ lock(*this); + + if (mIsEnabled) { + LC::QueueWaitEx(0); + LCDisable(); + mIsEnabled = false; + } + } + + bool Lock() { + OSLockMutex(&mMutex); + + if (mIsEnabled) { + LC::QueueWaitEx(0); + return true; + } + + OSUnlockMutex(&mMutex); + return false; + } + + void Unlock() { + LC::QueueWaitEx(0); + OSUnlockMutex(&mMutex); + } + +private: + bool mIsEnabled; // at 0x0 + OSMutex mMutex; // at 0x4 +}; + +static LCImpl sLCImpl; + +} // namespace + +namespace LC { + +void Enable() { + sLCImpl.Enable(); +} + +void Disable() { + sLCImpl.Disable(); +} + +bool Lock() { + return sLCImpl.Lock(); +} + +void Unlock() { + sLCImpl.Unlock(); +} + +void LoadBlocks(void *dst, void *src, unsigned long size) { + LCLoadBlocks(dst, src, size); +} + +void StoreBlocks(void *dst, void *src, unsigned long size) { + LCStoreBlocks(dst, src, size); +} + +void StoreData(void *dst, void *src, unsigned long size) { + LCStoreData(dst, src, size); +} + +} // namespace LC +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_NandFileStream.cpp b/src/nw4r/ut/ut_NandFileStream.cpp index e69de29b..29c7a0b8 100644 --- a/src/nw4r/ut/ut_NandFileStream.cpp +++ b/src/nw4r/ut/ut_NandFileStream.cpp @@ -0,0 +1,178 @@ + +#include + +namespace nw4r { +namespace ut { + +NW4R_UT_RTTI_DEF_DERIVED(NandFileStream, FileStream); + +void NandFileStream::NandAsyncCallback_(long result, NANDCommandBlock *block) { + NandFileStream *self = reinterpret_cast(block)->stream; + + self->mIsBusy = false; + self->mResult = result; + + if (self->mCallback != NULL) { + self->mCallback(result, self, self->mCallbackArg); + } +} + +void NandFileStream::Initialize_() { + mCanRead = false; + mCanWrite = false; + mCloseOnDestroy = false; + mAllowClose = false; + mIsOpen = false; + mIsBusy = false; + mCallback = NULL; + mCallbackArg = NULL; + mResult = NAND_RESULT_OK; + mAsyncContext.stream = this; +} + +NandFileStream::NandFileStream(const char *path, unsigned long access) { + Initialize_(); + Open(path, access); +} + +NandFileStream::NandFileStream(const NANDFileInfo *info, unsigned long access, bool close) { + Initialize_(); + Open(info, access, close); +} + +NandFileStream::~NandFileStream() { + if (mCloseOnDestroy) { + Close(); + } +} + +bool NandFileStream::Open(const char *path, unsigned long access) { + if (mCloseOnDestroy) { + Close(); + } + + mCanRead = access & NAND_ACCESS_READ; + mCanWrite = access & NAND_ACCESS_WRITE; + + if (NANDOpen(path, &mAsyncContext.info, access) != NAND_RESULT_OK) { + return false; + } + + if (mCanRead) { + unsigned long fileSize; + + if (NANDGetLength(&mAsyncContext.info, &fileSize) != NAND_RESULT_OK) { + NANDClose(&mAsyncContext.info); + return false; + } + + mFilePosition.SetFileSize(fileSize); + } + + mFilePosition.Seek(0, SEEK_BEG); + + mCloseOnDestroy = true; + mAllowClose = true; + mIsOpen = true; + + return true; +} + +bool NandFileStream::Open(const NANDFileInfo *info, unsigned long access, bool close) { + if (mCloseOnDestroy) { + Close(); + } + + mCanRead = access & NAND_ACCESS_READ; + mCanWrite = access & NAND_ACCESS_WRITE; + + mAsyncContext.info = *info; + + unsigned long fileSize; + if (mCanRead) { + if (NANDGetLength(&mAsyncContext.info, &fileSize) != NAND_RESULT_OK) { + if (close) { + NANDClose(&mAsyncContext.info); + } + return false; + } + mFilePosition.SetFileSize(fileSize); + } + mFilePosition.Seek(0, SEEK_BEG); + + mCloseOnDestroy = false; + mAllowClose = close; + mIsOpen = true; + return true; +} + +void NandFileStream::Close() { + if (mAllowClose && mIsOpen) { + NANDClose(&mAsyncContext.info); + mIsOpen = false; + } +} + +long NandFileStream::Read(void *dst, unsigned long size) { + NANDSeek(&mAsyncContext.info, mFilePosition.Tell(), NAND_SEEK_BEG); + + long result = NANDRead(&mAsyncContext.info, dst, size); + if (result > 0) { + mFilePosition.Skip(result); + } + + return result; +} + +bool NandFileStream::ReadAsync(void *dst, unsigned long size, AsyncCallback callback, void *arg) { + mCallback = callback; + mCallbackArg = arg; + mIsBusy = true; + + NANDSeek(&mAsyncContext.info, mFilePosition.Tell(), NAND_SEEK_BEG); + + bool success = + NANDReadAsync(&mAsyncContext.info, dst, size, NandAsyncCallback_, &mAsyncContext.block) == NAND_RESULT_OK; + + if (success) { + mFilePosition.Skip(size); + } else { + mIsBusy = false; + } + + return success; +} + +long NandFileStream::Write(const void *src, unsigned long size) { + NANDSeek(&mAsyncContext.info, mFilePosition.Tell(), NAND_SEEK_BEG); + long result = NANDWrite(&mAsyncContext.info, src, size); + if (result > 0) { + mFilePosition.Append(result); + } + return result; +} + +bool NandFileStream::WriteAsync(const void *src, unsigned long size, AsyncCallback callback, void *arg) { + mCallback = callback; + mCallbackArg = arg; + mIsBusy = true; + + NANDSeek(&mAsyncContext.info, mFilePosition.Tell(), NAND_SEEK_BEG); + + long result = NANDWriteAsync(&mAsyncContext.info, src, size, NandAsyncCallback_, &mAsyncContext.block); + + if (result == NAND_RESULT_OK) { + mFilePosition.Append(size); + } else { + mIsBusy = false; + } + + return result == NAND_RESULT_OK; +} + +void NandFileStream::Seek(long offset, unsigned long origin) { + mFilePosition.Seek(offset, origin); +} + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_ResFont.cpp b/src/nw4r/ut/ut_ResFont.cpp index e69de29b..1dfc9f3b 100644 --- a/src/nw4r/ut/ut_ResFont.cpp +++ b/src/nw4r/ut/ut_ResFont.cpp @@ -0,0 +1,121 @@ +#include + +const u32 MAGIC_RESFONT = 'RFNT'; +const u32 MAGIC_UNPACKED = 'RFNU'; + +const u32 MAGIC_FONTINFO = 'FINF'; +const u32 MAGIC_TEXGLYPH = 'TGLP'; +const u32 MAGIC_CHARWIDTH = 'CWDH'; +const u32 MAGIC_CHARMAP = 'CMAP'; +const u32 MAGIC_GLGR = 'GLGR'; + +namespace nw4r { +namespace ut { +namespace { + +template +void ResolveOffset(T *&ptr, void *base) { + ptr = reinterpret_cast(static_cast(base) + reinterpret_cast(ptr)); +} + +} // namespace + +ResFont::ResFont() {} + +ResFont::~ResFont() {} + +bool ResFont::SetResource(void *buffer) { + BinaryFileHeader *header = static_cast(buffer); + FontInformation *info = NULL; + + if (!IsManaging(NULL)) { + return false; + } + + if (header->magic == MAGIC_UNPACKED) { + BinaryBlockHeader *block = + reinterpret_cast(reinterpret_cast(header) + header->headerSize); + + for (int i = 0; i < header->numBlocks; i++) { + if (block->magic == MAGIC_FONTINFO) { + info = reinterpret_cast(block + 1); + break; + } + + block = reinterpret_cast(reinterpret_cast(block) + block->length); + } + } else { + if (header->version == NW4R_VERSION(1, 04)) { + if (!IsValidBinaryFile(header, MAGIC_RESFONT, NW4R_VERSION(1, 04), 2)) { + return false; + } + } else if (!IsValidBinaryFile(header, MAGIC_RESFONT, NW4R_VERSION(1, 02), 2)) { + return false; + } + + info = Rebuild(header); + } + + if (info == NULL) { + return false; + } + + SetResourceBuffer(header, info); + InitReaderFunc(GetEncoding()); + + return true; +} + +void *ResFont::RemoveResource() { + return ResFontBase::RemoveResourceBuffer(); +} + +FontInformation *ResFont::Rebuild(BinaryFileHeader *header) { + BinaryBlockHeader *block = + reinterpret_cast(reinterpret_cast(header) + header->headerSize); + FontInformation *info = NULL; + + for (int i = 0; i < header->numBlocks; i++) { + switch (block->magic) { + case MAGIC_FONTINFO: + info = reinterpret_cast(block + 1); + ResolveOffset(info->fontGlyph, header); + + if (info->fontWidth != 0) { + ResolveOffset(info->fontWidth, header); + } + + if (info->fontMap != 0) { + ResolveOffset(info->fontMap, header); + } + break; + case MAGIC_TEXGLYPH: + ResolveOffset(reinterpret_cast(block + 1)->sheetImage, header); + break; + case MAGIC_CHARWIDTH: + FontWidth *width = reinterpret_cast(block + 1); + if (width->next != 0) { + ResolveOffset(width->next, header); + } + break; + case MAGIC_CHARMAP: + FontCodeMap *map = reinterpret_cast(block + 1); + if (map->next != 0) { + ResolveOffset(map->next, header); + } + break; + case MAGIC_GLGR: + break; + default: + return NULL; + } + + block = reinterpret_cast(reinterpret_cast(block) + block->length); + } + + header->magic = MAGIC_UNPACKED; + return info; +} + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_ResFontBase.cpp b/src/nw4r/ut/ut_ResFontBase.cpp index e69de29b..40068a17 100644 --- a/src/nw4r/ut/ut_ResFontBase.cpp +++ b/src/nw4r/ut/ut_ResFontBase.cpp @@ -0,0 +1,221 @@ +#include + +namespace nw4r { +namespace ut { +namespace detail { + +ResFontBase::ResFontBase() : mResource(NULL), mFontInfo(NULL), mLastCharCode(0), mLastGlyphIndex(-1) {} + +ResFontBase::~ResFontBase() {} + +void ResFontBase::SetResourceBuffer(void *buffer, FontInformation *info) { + mResource = buffer; + mFontInfo = info; +} + +void *ResFontBase::RemoveResourceBuffer() { + void *pUserData = mResource; + mFontInfo = NULL; + mResource = NULL; + return pUserData; +} + +int ResFontBase::GetWidth() const { + return mFontInfo->width; +} + +int ResFontBase::GetHeight() const { + return mFontInfo->height; +} + +int ResFontBase::GetAscent() const { + return mFontInfo->ascent; +} + +int ResFontBase::GetDescent() const { + return mFontInfo->height - mFontInfo->ascent; +} + +int ResFontBase::GetBaselinePos() const { + return mFontInfo->fontGlyph->baselinePos; +} + +int ResFontBase::GetCellHeight() const { + return mFontInfo->fontGlyph->cellHeight; +} + +int ResFontBase::GetCellWidth() const { + return mFontInfo->fontGlyph->cellWidth; +} + +int ResFontBase::GetMaxCharWidth() const { + return mFontInfo->fontGlyph->maxCharWidth; +} + +Font::Type ResFontBase::GetType() const { + return TYPE_RESOURCE; +} + +GXTexFmt ResFontBase::GetTextureFormat() const { + return static_cast(mFontInfo->fontGlyph->sheetFormat); +} + +int ResFontBase::GetLineFeed() const { + return mFontInfo->lineFeed; +} + +CharWidths ResFontBase::GetDefaultCharWidths() const { + return mFontInfo->defaultWidth; +} + +void ResFontBase::SetDefaultCharWidths(const CharWidths &widths) { + mFontInfo->defaultWidth = widths; +} + +bool ResFontBase::SetAlternateChar(u16 ch) { + u32 index = FindGlyphIndex(ch); + if (index != 0xFFFF) { + mFontInfo->alterCharIndex = index; + return true; + } + + return false; +} + +void ResFontBase::SetLineFeed(int lf) { + mFontInfo->lineFeed = lf; +} + +int ResFontBase::GetCharWidth(u16 ch) const { + return GetCharWidths(ch).charWidth; +} + +CharWidths ResFontBase::GetCharWidths(u16 ch) const { + u16 index = GetGlyphIndex(ch); + return GetCharWidthsFromIndex(index); +} + +void ResFontBase::GetGlyph(Glyph *out, u16 ch) const { + u16 index = GetGlyphIndex(ch); + GetGlyphFromIndex(out, index); +} + +bool ResFontBase::HasGlyph(u16 c) const { + return FindGlyphIndex(c) != 0xFFFF; +} + +FontEncoding ResFontBase::GetEncoding() const { + return static_cast(mFontInfo->encoding); +} + +u16 ResFontBase::GetGlyphIndex(u16 c) const { + u16 index = FindGlyphIndex(c); + return (index != 0xFFFF) ? index : mFontInfo->alterCharIndex; +} + +u16 ResFontBase::FindGlyphIndex(u16 c) const { + if (c == mLastCharCode) { + return mLastGlyphIndex; + } + mLastCharCode = c; + + for (FontCodeMap *it = mFontInfo->fontMap; it != NULL; it = it->next) { + if (it->firstChar <= c && c <= it->lastChar) { + mLastGlyphIndex = FindGlyphIndex(it, c); + return mLastGlyphIndex; + } + } + + mLastGlyphIndex = 0xFFFF; + return mLastGlyphIndex; +} + +u16 ResFontBase::FindGlyphIndex(const FontCodeMap *map, u16 c) const { + struct CMapScanEntry { + u16 code; // at 0x0 + u16 index; // at 0x2 + }; + + struct CMapInfoScan { + u16 num; // at 0x0 + CMapScanEntry entries[]; // at 0x2 + }; + + u16 index = 0xFFFF; + + switch (map->mappingMethod) { + case FONT_MAPMETHOD_LINEAR: + index = map->mapInfo[0] + (c - map->firstChar); + break; + case FONT_MAPMETHOD_ARRAY: + index = map->mapInfo[c - map->firstChar]; + break; + case FONT_MAPMETHOD_SCAN: + const CMapInfoScan *info = reinterpret_cast(map->mapInfo); + + const CMapScanEntry *s = info->entries; + const CMapScanEntry *e = &info->entries[info->num - 1]; + + while (s <= e) { + const CMapScanEntry *m = s + (e - s) / 2; + + if (m->code < c) { + s = m + 1; + } else if (c < m->code) { + e = m - 1; + } else { + return m->index; + } + } + + break; + } + + return index; +} + +const CharWidths &ResFontBase::GetCharWidthsFromIndex(u16 index) const { + for (const FontWidth *it = mFontInfo->fontWidth; it != NULL; it = it->next) { + if (it->firstChar <= index && index <= it->lastChar) { + return GetCharWidthsFromIndex(it, index); + } + } + + return mFontInfo->defaultWidth; +} + +const CharWidths &ResFontBase::GetCharWidthsFromIndex(const FontWidth *width, u16 index) const { + return width->widthTable[index - width->firstChar]; +} + +void ResFontBase::GetGlyphFromIndex(Glyph *out, u16 index) const { + const FontTextureGlyph *texGlyph = mFontInfo->fontGlyph; + + u32 cellsInASheet = texGlyph->sheetRow * texGlyph->sheetLine; + + u32 glyphCell = index % cellsInASheet; + u32 glyphSheet = index / cellsInASheet; + + u32 unitX = glyphCell % texGlyph->sheetRow; + u32 unitY = glyphCell / texGlyph->sheetRow; + + u32 pixelX = unitX * (texGlyph->cellWidth + 1); + u32 pixelY = unitY * (texGlyph->cellHeight + 1); + + out->texture = texGlyph->sheetImage + (glyphSheet * texGlyph->sheetSize); + + out->widths = GetCharWidthsFromIndex(index); + out->height = texGlyph->cellHeight; + + out->format = static_cast(texGlyph->sheetFormat); + + out->texWidth = texGlyph->sheetWidth; + out->texHeight = texGlyph->sheetHeight; + + out->cellX = pixelX + 1; + out->cellY = pixelY + 1; +} + +} // namespace detail +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_RomFont.cpp b/src/nw4r/ut/ut_RomFont.cpp new file mode 100644 index 00000000..f3cb29f6 --- /dev/null +++ b/src/nw4r/ut/ut_RomFont.cpp @@ -0,0 +1,226 @@ +#include + +namespace nw4r { +namespace ut { + +u16 RomFont::mFontEncode = 0xFFFF; + +namespace { + +bool IsCP1252Char(u16 c) { + return c >= 0x20 && c <= 0xFF; +} + +bool IsSJISHalfWidthChar(u16 c) { + if (c > 0xFF) { + return false; + } + + return (c >= 0x20 && c <= 0x7E) || (c >= 0xA1 && c <= 0xDF); +} + +bool IsSJISFullWidthChar(u16 c) { + u8 hi = BitExtract(c, 8, 8); + u8 lo = BitExtract(c, 0, 8); + + return hi >= 0x81 && hi <= 0x98 && lo >= 0x40 && lo <= 0xFC; +} + +} // namespace + +RomFont::RomFont() : mFontHeader(NULL), mAlternateChar('?') { + mDefaultWidths.leftSpacing = 0; + mDefaultWidths.glyphWidth = 0; + mDefaultWidths.charWidth = 0; +} + +RomFont::~RomFont() {} + +bool RomFont::Load(void *buffer) { + if (mFontHeader != NULL) { + return false; + } + + BOOL success = OSInitFont(static_cast(buffer)); + + if (success) { + mFontEncode = OSGetFontEncode(); + mFontHeader = static_cast(buffer); + + mDefaultWidths.leftSpacing = 0; + mDefaultWidths.glyphWidth = GetCellWidth(); + mDefaultWidths.charWidth = GetMaxCharWidth(); + + InitReaderFunc(GetEncoding()); + } + + return success; +} + +u32 RomFont::GetRequireBufferSize() { + switch (OSGetFontEncode()) { + case OS_FONT_ENCODE_ANSI: + return 0x00020120; + case OS_FONT_ENCODE_SJIS: + return 0x00120F00; + } + + return 0; +} + +int RomFont::GetWidth() const { + return mFontHeader->width; +} + +int RomFont::GetHeight() const { + return GetAscent() + GetDescent(); +} + +int RomFont::GetAscent() const { + return mFontHeader->ascent; +} + +int RomFont::GetDescent() const { + return mFontHeader->descent; +} + +int RomFont::GetBaselinePos() const { + return mFontHeader->ascent; +} + +int RomFont::GetCellHeight() const { + return mFontHeader->cellHeight; +} + +int RomFont::GetCellWidth() const { + return mFontHeader->cellWidth; +} + +int RomFont::GetMaxCharWidth() const { + return mFontHeader->width; +} + +Font::Type RomFont::GetType() const { + return TYPE_ROM; +} + +GXTexFmt RomFont::GetTextureFormat() const { + return GX_TF_I4; +} + +int RomFont::GetLineFeed() const { + return mFontHeader->leading; +} + +CharWidths RomFont::GetDefaultCharWidths() const { + return mDefaultWidths; +} + +void RomFont::SetDefaultCharWidths(const CharWidths &widths) { + mDefaultWidths = widths; +} + +bool RomFont::SetAlternateChar(u16 c) { + const u16 prev = mAlternateChar; + mAlternateChar = 0xFFFF; + + u16 undef = HandleUndefinedChar(c); + if (undef != 0xFFFF) { + mAlternateChar = c; + return true; + } else { + mAlternateChar = prev; + return false; + } +} + +void RomFont::SetLineFeed(int lf) { + mFontHeader->leading = lf; +} + +int RomFont::GetCharWidth(u16 c) const { + u32 width; + char buffer[4]; + + MakeCharPtr(buffer, c); + OSGetFontWidth(buffer, &width); + + return width; +} + +CharWidths RomFont::GetCharWidths(u16 c) const { + int width = GetCharWidth(c); + + CharWidths widths; + widths.leftSpacing = 0; + widths.glyphWidth = width; + widths.charWidth = width; + + return widths; +} + +void RomFont::GetGlyph(Glyph *out, u16 c) const { + void *texture; + u32 x, y, width; + char buffer[4]; + + MakeCharPtr(buffer, c); + OSGetFontTexture(buffer, &texture, &x, &y, &width); + + out->texture = texture; + + out->widths.leftSpacing = 0; + out->widths.glyphWidth = width; + out->widths.charWidth = width; + + out->height = mFontHeader->cellHeight; + out->format = GX_TF_I4; + + out->texWidth = mFontHeader->sheetWidth; + out->texHeight = mFontHeader->sheetHeight; + + out->cellX = x; + out->cellY = y; +} + +FontEncoding RomFont::GetEncoding() const { + switch (mFontEncode) { + case OS_FONT_ENCODE_ANSI: + return FONT_ENCODE_CP1252; + case OS_FONT_ENCODE_SJIS: + return FONT_ENCODE_SJIS; + } + + return FONT_ENCODE_CP1252; +} + +void RomFont::MakeCharPtr(char *buffer, u16 c) const { + c = HandleUndefinedChar(c); + + if (BitExtract(c, 8, 8) == 0) { + buffer[0] = c & 0x00FF; + buffer[1] = '\0'; + } else { + buffer[0] = BitExtract(c, 8, 8); + buffer[1] = c & 0x00FF; + buffer[2] = '\0'; + } +} + +u16 RomFont::HandleUndefinedChar(u16 c) const { + bool valid; + + switch (mFontEncode) { + case OS_FONT_ENCODE_ANSI: + valid = IsCP1252Char(c); + break; + case OS_FONT_ENCODE_SJIS: + valid = IsSJISHalfWidthChar(c) || IsSJISFullWidthChar(c); + break; + } + + return valid ? c : mAlternateChar; +} + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_TextWriterBase.cpp b/src/nw4r/ut/ut_TextWriterBase.cpp index e69de29b..c3fc3032 100644 --- a/src/nw4r/ut/ut_TextWriterBase.cpp +++ b/src/nw4r/ut/ut_TextWriterBase.cpp @@ -0,0 +1,494 @@ + +#include +#include + +namespace nw4r { +namespace ut { + +template +T *TextWriterBase::mFormatBuffer; +template +int TextWriterBase::mFormatBufferSize = 0x100; + +template +TagProcessorBase TextWriterBase::mDefaultTagProcessor; + +template +TextWriterBase::TextWriterBase() + : mCharSpace(0.0f), mWidthLimit(NW4R_MATH_FLT_MAX), mLineSpace(0.0f), mTabWidth(4), mDrawFlag(0), + mTagProcessor(&mDefaultTagProcessor) {} + +template +TextWriterBase::~TextWriterBase() {} + +template +void TextWriterBase::SetLineHeight(f32 height) { + const Font *font = GetFont(); + int lf = font != NULL ? font->GetLineFeed() : 0; + mLineSpace = height - lf * GetScaleV(); +} + +template +f32 TextWriterBase::GetLineHeight() const { + const Font *font = GetFont(); + int lf = font != NULL ? font->GetLineFeed() : 0; + return mLineSpace + GetScaleV() * lf; +} + +template +f32 TextWriterBase::CalcFormatStringWidth(const T *format, ...) const { + Rect rect; + _va_list_struct args; + + va_start(args, format); + CalcVStringRect(&rect, format, &args); + va_end(args); + + return rect.GetWidth(); +} + +template +f32 TextWriterBase::CalcFormatStringHeight(const T *format, ...) const { + Rect rect; + _va_list_struct args; + + va_start(args, format); + CalcVStringRect(&rect, format, &args); + va_end(args); + + return rect.GetHeight(); +} + +template +void TextWriterBase::CalcFormatStringRect(Rect *rect, const T *format, ...) const { + _va_list_struct args; + + va_start(args, format); + CalcVStringRect(rect, format, &args); + va_end(args); +} + +template +void TextWriterBase::CalcVStringRect(Rect *rect, const T *format, va_list args) const { + T *pBuffer; + + if (mFormatBuffer != NULL) { + pBuffer = mFormatBuffer; + } else { + pBuffer = static_cast(__alloca(mFormatBufferSize)); + } + + int len = VSNPrintf(pBuffer, mFormatBufferSize, format, args); + len = Min(len, mFormatBufferSize - 1); + + CalcStringRect(rect, pBuffer, len); +} + +template +f32 TextWriterBase::CalcStringWidth(const T *str, int len) const { + Rect rect; + CalcStringRect(&rect, str, len); + return rect.GetWidth(); +} + +template +f32 TextWriterBase::CalcStringHeight(const T *str, int len) const { + Rect rect; + CalcStringRect(&rect, str, len); + return rect.GetHeight(); +} + +template +void TextWriterBase::CalcStringRect(Rect *rect, const T *str, int len) const { + TextWriterBase clone(*this); + clone.CalcStringRectImpl(rect, str, len); +} + +template +f32 TextWriterBase::Printf(const T *format, ...) { + va_list args; + va_start(args[0], format); + f32 width = VPrintf(format, args); + va_end(args[0]); + return width; +} + +template +f32 TextWriterBase::VPrintf(const T *str, va_list args) { + T *pBuffer; + + if (mFormatBuffer != NULL) { + pBuffer = mFormatBuffer; + } else { + pBuffer = static_cast(__alloca(mFormatBufferSize)); + } + + int len = VSNPrintf(pBuffer, mFormatBufferSize, str, args); + len = Min(len, mFormatBufferSize - 1); + return Print(pBuffer, len); +} + +template +f32 TextWriterBase::Print(const T *str, int len) { + TextWriterBase clone(*this); + + f32 width = clone.PrintImpl(str, len, false); + SetCursor(clone.GetCursorX(), clone.GetCursorY()); + + return width; +} + +template +f32 TextWriterBase::PrintfMutable(const T *format, ...) { + va_list args; + va_start(args[0], format); + f32 width = VPrintfMutable(format, args); + va_end(args[0]); + return width; +} + +template +f32 TextWriterBase::VPrintfMutable(const T *format, va_list args) { + T *pBuffer; + + if (mFormatBuffer != NULL) { + pBuffer = mFormatBuffer; + } else { + pBuffer = static_cast(__alloca(mFormatBufferSize)); + } + + int len = VSNPrintf(pBuffer, mFormatBufferSize, format, args); + len = Min(len, mFormatBufferSize - 1); + return PrintMutable(pBuffer, len); +} + +template +f32 TextWriterBase::PrintMutable(const T *str, int len) { + return PrintImpl(str, len, true); +} + +template +f32 TextWriterBase::CalcLineWidth(const T *str, int len) { + Rect rect; + TextWriterBase clone(*this); + + clone.SetCursor(0.0f, 0.0f); + clone.CalcLineRectImpl(&rect, &str, len); + + return rect.GetWidth(); +} + +template +bool TextWriterBase::CalcLineRectImpl(Rect *rect, const T **str, int len) { + const T *strBegin = *str; + const T *strEnd = strBegin + len; + const bool useLimit = mWidthLimit < NW4R_MATH_FLT_MAX; + + PrintContext context = {this, strBegin}; + + f32 x = 0.0f; + bool charSpace = false; + bool overLimit = false; + + const T *prevStream = NULL; + Rect prevRect; + + CharStrmReader reader = GetFont()->GetCharStrmReader(); + + rect->left = 0.0f; + rect->right = 0.0f; + rect->top = Min(0.0f, GetLineHeight()); + rect->bottom = Max(0.0f, GetLineHeight()); + prevRect = *rect; + + reader.Set(strBegin); + prevStream = NULL; + + u16 ch = reader.Next(); + + while (static_cast(reader.GetCurrentPos()) <= strEnd) { + if (ch < ' ') { + Rect r(x, 0.0f, 0.0f, 0.0f); + context.str = static_cast(reader.GetCurrentPos()); + context.flags = charSpace ? 0 : PRINTFLAGS_CHARSPACE; + SetCursorX(x); + + if (useLimit && ch != '\n' && prevStream != NULL) { + PrintContext context2 = context; + TextWriterBase clone(*this); + + Rect r; + context2.writer = &clone; + mTagProcessor->CalcRect(&r, ch, &context2); + + if (r.GetWidth() > 0.0f && clone.GetCursorX() - context.x > mWidthLimit) { + overLimit = true; + ch = '\n'; + reader.Set(prevStream); + continue; + } + } + + Operation oper = mTagProcessor->CalcRect(&r, ch, &context); + reader.Set(context.str); + + rect->left = Min(rect->left, r.left); + rect->top = Min(rect->top, r.top); + rect->right = Max(rect->right, r.right); + rect->bottom = Max(rect->bottom, r.bottom); + + x = GetCursorX(); + + if (oper == OPERATION_END_DRAW) { + *str += len; + return false; + } + + if (oper == OPERATION_NO_CHAR_SPACE) { + charSpace = false; + } else if (oper == OPERATION_CHAR_SPACE) { + charSpace = true; + } else if (oper == OPERATION_NEXT_LINE) { + break; + } + } else { + f32 dx = 0.0f; + + if (charSpace) { + dx += GetCharSpace(); + } + + if (IsWidthFixed()) { + dx += GetFixedWidth(); + } else { + dx += GetFont()->GetCharWidth(ch) * GetScaleH(); + } + + if (useLimit && prevStream != NULL && x + dx > mWidthLimit) { + overLimit = true; + ch = '\n'; + reader.Set(prevStream); + continue; + } + + x += dx; + rect->left = Min(rect->left, x); + rect->right = Max(rect->right, x); + + charSpace = true; + } + + if (useLimit) { + prevStream = static_cast(reader.GetCurrentPos()); + } + + ch = reader.Next(); + } + + *str = static_cast(reader.GetCurrentPos()); + return overLimit; +} + +template +void TextWriterBase::CalcStringRectImpl(Rect *rect, const T *str, int len) { + const T *end = str + len; + int remain = len; + + rect->left = 0.0f; + rect->right = 0.0f; + rect->top = 0.0f; + rect->bottom = 0.0f; + + SetCursor(0.0f, 0.0f); + + do { + Rect r; + CalcLineRectImpl(&r, &str, remain); + remain = end - str; + + rect->left = Min(rect->left, r.left); + rect->top = Min(rect->top, r.top); + rect->right = Max(rect->right, r.right); + rect->bottom = Max(rect->bottom, r.bottom); + } while (remain > 0); +} + +template +f32 TextWriterBase::PrintImpl(const T *str, int len, bool m) { + f32 cursorX = GetCursorX(); + f32 cursorY = GetCursorY(); + + bool useLimit = mWidthLimit < NW4R_MATH_FLT_MAX; + + f32 orgCursorX = cursorX; + f32 orgCursorY = cursorY; + + f32 cursorXAdj = 0.0f; + f32 cursorYAdj = 0.0f; + + bool charSpace = false; + + const T *prevStream = str; + const T *prevNewline = str; + + f32 textWidth = AdjustCursor(&cursorX, &cursorY, str, len); + + cursorXAdj = orgCursorX - GetCursorX(); + cursorYAdj = orgCursorY - GetCursorY(); + + PrintContext context = {this, str, cursorX, cursorY}; + + CharStrmReader reader = GetFont()->GetCharStrmReader(); + reader.Set(str); + + Operation oper; + u16 ch = reader.Next(); + + while (static_cast(reader.GetCurrentPos()) - str <= len) { + if (ch < ' ') { + context.str = static_cast(reader.GetCurrentPos()); + context.flags = charSpace ? 0 : PRINTFLAGS_CHARSPACE; + + if (useLimit && ch != '\n' && prevStream != prevNewline) { + PrintContext context2 = context; + TextWriterBase clone(*this); + Rect rect; + + context2.writer = &clone; + oper = mTagProcessor->CalcRect(&rect, ch, &context2); + + if (rect.GetWidth() > 0.0f && clone.GetCursorX() - context.x > mWidthLimit) { + ch = '\n'; + reader.Set(prevStream); + continue; + } + } + + oper = mTagProcessor->Process(ch, &context); + if (oper == OPERATION_NEXT_LINE) { + if (IsDrawFlagSet(0x3, 0x1)) { + int remain = len - (context.str - str); + f32 width = CalcLineWidth(context.str, remain); + f32 offset = (textWidth - width) / 2.0f; + SetCursorX(context.x + offset); + } else if (IsDrawFlagSet(0x3, 0x2)) { + int remain = len - (context.str - str); + f32 width = CalcLineWidth(context.str, remain); + f32 offset = textWidth - width; + SetCursorX(context.x + offset); + } else { + f32 width = GetCursorX() - context.x; + textWidth = Max(textWidth, width); + SetCursorX(context.x); + } + + if (useLimit) { + prevNewline = static_cast(reader.GetCurrentPos()); + } + + charSpace = false; + } else if (oper == OPERATION_NO_CHAR_SPACE) { + charSpace = false; + } else if (oper == OPERATION_CHAR_SPACE) { + charSpace = true; + } else if (oper == OPERATION_END_DRAW) { + break; + } + + reader.Set(context.str); + } else { + f32 baseY = GetCursorY(); + if (useLimit && prevStream != prevNewline) { + f32 baseX = GetCursorX(); + f32 space = charSpace ? GetCharSpace() : 0.0f; + f32 width = IsWidthFixed() ? GetFixedWidth() : GetFont()->GetCharWidth(ch) * GetScaleH(); + if (baseX - cursorX + space + width > mWidthLimit) { + ch = '\n'; + reader.Set(prevStream); + continue; + } + } + + if (charSpace) { + MoveCursorX(GetCharSpace()); + } + + charSpace = true; + + const Font *font = GetFont(); + f32 adj = -font->GetBaselinePos() * GetScaleV(); + MoveCursorY(adj); + CharWriter::Print(ch); + SetCursorY(baseY); + } + + if (useLimit) { + prevStream = static_cast(reader.GetCurrentPos()); + } + + ch = reader.Next(); + } + + f32 width = GetCursorX() - context.x; + textWidth = Max(textWidth, width); + + if (IsDrawFlagSet(0x300, 0x100) || IsDrawFlagSet(0x300, 0x200)) { + SetCursorY(orgCursorY); + } else { + MoveCursorY(cursorYAdj); + } + + return textWidth; +} + +template +f32 TextWriterBase::AdjustCursor(f32 *x1, f32 *y1, const T *str, int len) { + f32 textWidth = 0.0f; + f32 textHeight = 0.0f; + + if (!IsDrawFlagSet(0x333, 0x300) && !IsDrawFlagSet(0x333, 0)) { + Rect rect; + CalcStringRect(&rect, str, len); + + textWidth = rect.left + rect.right; + textHeight = rect.top + rect.bottom; + + if (textWidth > mWidthLimit) { + textWidth = mWidthLimit; + } + } + + if (IsDrawFlagSet(0x30, 0x10)) { + *x1 -= textWidth / 2; + } else if (IsDrawFlagSet(0x30, 0x20)) { + *x1 -= textWidth; + } + + if (IsDrawFlagSet(0x300, 0x100)) { + *y1 -= textHeight / 2; + } else if (IsDrawFlagSet(0x300, 0x200)) { + *y1 -= textHeight; + } + + if (IsDrawFlagSet(0x3, 0x1)) { + SetCursorX(*x1 + (textWidth - CalcLineWidth(str, len)) / 2); + } else if (IsDrawFlagSet(0x3, 0x2)) { + SetCursorX(*x1 + (textWidth - CalcLineWidth(str, len))); + } else { + SetCursorX(*x1); + } + + if (IsDrawFlagSet(0x300, 0x300)) { + SetCursorY(*y1); + } else { + SetCursorY(*y1 + GetFontAscent()); + } + + return textWidth; +} + +template struct TextWriterBase; +template struct TextWriterBase; + +} // namespace ut +} // namespace nw4r