diff --git a/.clang-format b/.clang-format index f2233bb..8b346af 100644 --- a/.clang-format +++ b/.clang-format @@ -12,59 +12,52 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true FixNamespaceComments: true AccessModifierOffset: -4 AllowShortFunctionsOnASingleLine: Empty -WhitespaceSensitiveMacros: [ - NW4R_UT_LINKLIST_FOREACH, - NW4R_UT_LINKLIST_FOREACH_SAFE, - NW4R_UT_LIST_FOREACH, - NW4R_UT_LIST_FOREACH_SAFE, - NW4R_EF_LIST_FOREACH, - NW4R_EF_LIST_FOREACH_SAFE, - EGG_ASSERT, - EGG_ASSERT_MSG, - K_ASM, - KOKESHI_BY_PACK, - KM_BRANCH_MF, - KM_BRANCH, - KM_CALL_MF, - KM_CALL, - ASM, - TRAMPOLINE, - TRAMPOLINE_EX, -] -AttributeMacros: [DECOMP_INLINE, DECOMP_DONT_INLINE] -InsertNewlineAtEOF: true ForEachMacros: [K_FOREACH] +AttributeMacros: [DECOMP_INLINE, DECOMP_DONT_INLINE] +WhitespaceSensitiveMacros: + [ + DECOMP_FORCEACTIVE, + DECOMP_FORCELITERAL, + DECOMP_FORCEACTIVE_DTOR, + NW4R_UT_LINKLIST_FOREACH, + NW4R_UT_LINKLIST_FOREACH_SAFE, + NW4R_UT_LIST_FOREACH, + NW4R_UT_LIST_FOREACH_SAFE, + NW4R_EF_LIST_FOREACH, + NW4R_EF_LIST_FOREACH_SAFE, + EGG_ASSERT, + EGG_ASSERT_MSG, + KOKESHI_BY_PACK, + KM_BRANCH, + KM_CALL, + KM_BRANCH_MF, + KM_CALL_MF, + ] IncludeCategories: - - Regex: '' - Priority: -1 - - - Regex: '"' - Priority: 1 - - - Regex: '^<(nw4r|egg|Pack)?(\/)?types' # "Types" headers - Priority: 2 - CaseSensitive: true + - Regex: '^<(nw4r|egg|Pack)?(\/)?types' # "Types" headers + Priority: 0 + CaseSensitive: true - - Regex: '' # libkiwi public headers - Priority: 4 - CaseSensitive: true + - Regex: "" # libkiwi public headers + Priority: 2 + CaseSensitive: true - - Regex: '' # EGG public headers - Priority: 5 - CaseSensitive: true + - Regex: '' # EGG public headers + Priority: 3 + CaseSensitive: true - - Regex: '' # NW4R public headers - Priority: 6 - CaseSensitive: true + - Regex: '' # NW4R public headers + Priority: 4 + CaseSensitive: true - - Regex: '^' # RVL SDK public headers - Priority: 7 - CaseSensitive: true + - Regex: '^' # RVL SDK public headers + Priority: 5 + CaseSensitive: true - - Regex: '<[[:alnum:].]+>' # STL headers - Priority: 8 # Priority 0 is header mapped to src file - CaseSensitive: true + - Regex: "<[[:alnum:].]+>" # STL headers + Priority: 6 # Priority 0 is header mapped to src file + CaseSensitive: true - - Regex: '.*' # All other headers - Priority: 3 + - Regex: ".*" # All other headers + Priority: 1 diff --git a/.gitignore b/.gitignore index a54f3eb..18e1fa3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ +#=========================================================# +# OS Files +#=========================================================# +.DS_Store + #=========================================================# # IDE Configuration #=========================================================# @@ -10,19 +15,17 @@ # Base ROM filesystem romfs/** # Base ROM executable(s) -baserom*.dol +base/**.dol #=========================================================# # Tools #=========================================================# -# Kamek -tools/Kamek/* -tools/Kamek*.* +# Executables +tools/kamek/* +!tools/kamek/.gitkeep # CodeWarrior -tools/mwasmeppc.exe -tools/mwcceppc.exe -tools/mwldeppc.exe -tools/*.dll +tools/codewarrior/* +!tools/codewarrior/.gitkeep # Compiled Python tools/**/*.pyc @@ -33,3 +36,7 @@ tools/**/*.pyc build/** # Symbol maps *.MAP +# Ninja artifacts +.ninja_deps +.ninja_log +build.ninja diff --git a/Makefile b/Makefile deleted file mode 100644 index b733f06..0000000 --- a/Makefile +++ /dev/null @@ -1,93 +0,0 @@ -#=============================================================================# -# # -# Kokeshi makefile # -# # -#=============================================================================# - - - -#=============================================================================# -# Configuration # -#=============================================================================# - -# Game(s) that your mod should build for. -# By default, we try building for Wii Sports. -# -# You can build for multiple games by writing multiple pack names, separated -# by spaces. -# -# To handle this in your code, expect preprocessor definitions of the format -# PACK_{NAME}, (i.e. PACK_SPORTS, PACK_RESORT). -PACK ?= resort - -# Pass NDEBUG=1 when running make to disable debug features. -# -# By default, we build for debug. There is not much benefit to building for -# release except maybe security, or if you have something REALLY slowing down -# debug builds. -# -# NOTE: This will disable some features in libkiwi such as the mapfile and -# exception handler. -# -# (This also will define "NDEBUG" when compiling your code too.) -NDEBUG ?= 0 - -# Extra compiler flags to apply across all code. -# NOTE: See 'compile.py' (CFLAGS_COMMON) to see what is already being applied. -CFLAGS := -maxerrors 1 - -# Pass CI=1 when running through GitHub CI to perform only code compilation. -CI ?= 0 - -#=============================================================================# -# Variables # -#=============================================================================# -# Default to debug target unless NDEBUG is set -TARGET := debug -ifeq ($(NDEBUG), 1) - TARGET := release -endif - -# Verbose output for debugging (optional) -VERBOSE ?= 0 -ifeq ($(VERBOSE), 0) - QUIET = @ -endif - - -#==============================================================================# -# Tools # -#==============================================================================# -PYTHON := python - -ASSETSCRIPT := tools/asset.py -BUILDSCRIPT := tools/compile.py -CLEANSCRIPT := tools/clean.py - -#==============================================================================# -# Default Targets # -#==============================================================================# -default: all -all: build - - -#==============================================================================# -# Build # -#==============================================================================# -.PHONY: build -build: -# Build the mod for each game -# -# NOTE: If you want to add custom preprocessor definitions, supply each using -# the following format: --define=KEY VALUE - $(QUIET) $(foreach game, $(PACK), \ - $(PYTHON) $(ASSETSCRIPT) --game=$(game) --ci=$(CI); \ - $(PYTHON) $(BUILDSCRIPT) --game=$(game) --target=$(TARGET) --cflags="$(CFLAGS)" --define="" --ci=$(CI); \ - ) - -#==============================================================================# -# Clean # -#==============================================================================# -.PHONY: clean -clean: - $(QUIET) $(PYTHON) $(CLEANSCRIPT) diff --git a/README.md b/README.md index 484af74..e238e79 100644 --- a/README.md +++ b/README.md @@ -35,9 +35,9 @@ Kokeshi supports the following games: #### Tools 1. Install GNU `make`. If you have DevKitPRO or Windows Subsystem for Linux you may already have the tool installed. 2. Download the latest release of [the PackProject fork of Kamek](https://github.com/PackProject/Kamek/releases/latest). - 1. Install the contents of the zip file to the `tools/` directory. + 1. Install the contents of the zip file to the `tools/kamek` directory. 3. Download the Wii v1.7 version of [the CodeWarrior compiler](https://files.decomp.dev/compilers_20230715.zip). - 1. Install the contents of the `Wii/1.7/` folder to the `tools/` directory. + 1. Install the contents of the `Wii/1.7/` folder to the `tools/codewarrior` directory. #### Filesystem 1. For each game that you want to build for, extract its filesystem using Dolphin Emulator. diff --git a/base/symbols_play.txt b/base/SymbolsPlay.txt similarity index 85% rename from base/symbols_play.txt rename to base/SymbolsPlay.txt index 705ac2f..259f581 100644 --- a/base/symbols_play.txt +++ b/base/SymbolsPlay.txt @@ -2757,9 +2757,16 @@ PPCMfmsr=0x8010a400 PPCMtmsr=0x8010a408 VISetPreRetraceCallback=0x800fa3f0 _current_locale=0x8032e650 +__ct__Q34nw4r3lyt19ArcResourceAccessorFv=0x80082848 +__dt__Q34nw4r3lyt16ResourceAccessorFv=0x800825e4 +__dt__Q44nw4r2ut6detail12LinkListImplFv=0x80007a9c +PlayPolicy_Onetime__Q24nw4r3g3dFfff=0x80063320 +PlayPolicy_Loop__Q24nw4r3g3dFfff=0x80063328 +ResWriteBPCmd__Q34nw4r3g3d6detailFPUcUlUl=0x800507e8 FLog__Q34nw4r4math6detailFf=0x8002f920 alloc__Q23EGG4HeapFUliPQ23EGG4Heap=0x800a35ec free__Q23EGG4HeapFPvPQ23EGG4Heap=0x800a3854 +request__Q23EGG10TaskThreadFPFPv_vPvPv=0x800a47c4 __dt__Q23EGG5SceneFv=0x800ab4f8 mainLoop__11RPSysSystemFv=0x80183514 getCurrentScene__13RPSysSceneMgrCFv=0x801859a0 @@ -2769,11 +2776,22 @@ spCurrent__13RPGrpRenderer=0x8043c5a0 sDrawPass__13RPGrpRenderer=0x8043b354 sCurrentViewID__13RPGrpRenderer=0x8043c5a5 sActiveScreen__13RPGrpRenderer=0x8043c5ac +__dt__Q23EGG7ArchiveFv=0x800ac594 +__ct__Q23EGG8DisposerFv=0x800ac4cc +__vt__Q23EGG7Archive=0x80358a88 +sIsArchiveListInitialized__Q23EGG7Archive=0x8043bc88 +sArchiveList__Q23EGG7Archive=0x803a0390 +List_Init__Q24nw4r2utFPQ34nw4r2ut4ListUs=0x80007800 +List_Append__Q24nw4r2utFPQ34nw4r2ut4ListPv=0x80007818 +mount__Q23EGG7ArchiveFPvPQ23EGG4Heapi=0x800ac60c +getFile__Q23EGG7ArchiveFPCcPQ33EGG7Archive8FileInfo=0x800ac7ec +appendLocalDirectory__17RPSysProjectLocalFPcPCc=0x80185ae4 +spInstance__17RPSysProjectLocal=0x8043c470 AppendDrawObject__13RPGrpRendererFP16IRPGrpDrawObject=0x801acdf8 create__Q23EGG7ExpHeapFUlPQ23EGG4HeapUs=0x800a2ef4 loadToMainRAM__Q23EGG9DvdRipperFPCcPUcPQ23EGG4HeapQ33EGG9DvdRipper15EAllocDirectionUlPUlPUl=0x800aae3c changeSceneAfterFade__17RPSysSceneCreatorFlb=0x8018459c -getCoreStatus__Q23EGG14CoreControllerCFi=0x800a675c +getCoreStatus__Q23EGG14CoreControllerFi=0x800a675c getNthController__Q23EGG17CoreControllerMgrFi=0x800a6eb4 sInstance__Q23EGG17CoreControllerMgr=0x8043bc70 updateState__13RPSysSceneMgrFv=0x80185058 @@ -2797,6 +2815,7 @@ TurnY__9RPBilCtrlFf=0x802bc000 TurnX__9RPBilCtrlFf=0x802bc238 isSceneChangeEnable__10RPSysSceneCFv=0x80184f04 initialize__11RPUtlRandomFv=0x801b882c +isNandAccessEnable__10RPSysSceneCFv=0x80184eb4 setEnterFast__10RPSysSceneFv=0x80184878 setCreatorSceneID__10RPSysSceneFl=0x80184890 createPartyScene__17RPSysSceneCreatorFl=0x80183c38 @@ -2829,7 +2848,9 @@ __ml__3EGGFRCQ23EGG5QuatfRCQ23EGG5Quatf=0x800a29bc rotateVector__Q23EGG5QuatfFRCQ23EGG8Vector3f=0x800a2840 slerpTo__Q23EGG5QuatfCFRCQ23EGG5QuatffRQ23EGG5Quatf=0x800a2a80 __ct__Q23EGG9Matrix34fFffffffffffff=0x800a1d6c +makeIdentity__Q23EGG9Matrix34fFv=0x800a1c44 DrawDL__Q23EGG6DrawGXFQ33EGG6DrawGX2DLRCQ34nw4r4math5MTX34=0x80089640 +BeginDrawQuad__Q23EGG6DrawGXFQ33EGG6DrawGX12ColorChannelQ33EGG6DrawGX5ZModeQ33EGG6DrawGX5Blendbb=0x800876a4 spInstance__13RPSysSceneMgr=0x8043c468 spInstance__11RPSysSystem=0x8043c440 spInstance__17RPSysSceneCreator=0x8043c458 @@ -2851,10 +2872,10 @@ pauseCallBack__10RPSysSceneFb=0x80184f1c isTaskAsyncFinish__10RPSysSceneCFv=0x8018659c startSound__13RPSndAudioMgrFPQ34nw4r3snd11SoundHandleUl=0x801b38f8 startSound__13RPSndAudioMgrFPQ34nw4r3snd11SoundHandlePCc=0x801b384c -spInstance__20RPGrpModelResManager=0x8043c590 +spCurrent__20RPGrpModelResManager=0x8043c590 CreateResourceList__20RPGrpModelResManagerFUs=0x801ac978 -spInstance__17RPGrpModelManager=0x8043c588 -CreateModelScene__17RPGrpModelManagerFUlUcUlP17RPGrpLightManagerP15RPGrpFogManager=0x801ac978 +spCurrent__17RPGrpModelManager=0x8043c588 +CreateModelScene__17RPGrpModelManagerFUlUcUlP17RPGrpLightManagerP15RPGrpFogManager=0x801abf2c CreateView2D__13RPGrpRendererFUcP11RPGrpScreen=0x801acf54 CorrectView__13RPGrpRendererFv=0x801ace1c __ct__Q23EGG6ScreenFv=0x80099008 @@ -2882,7 +2903,7 @@ setPlayerNum__14RPSysPlayerMgrFi=0x8018c9a0 setControllerNum__14RPSysPlayerMgrFi=0x8018c948 CreateInstance__14RPPartyGameMgrFv=0x801e4b18 spInstance__20RPSysResourceManager=0x8043c480 -LoadCacheArchives__20RPSysResourceManagerFv=0x80186fa4 +LoadCacheArchives__20RPSysResourceManagerFv=0x80186d54 LoadSharedCommonArchive__20RPSysResourceManagerFv=0x80186d54 spInstance__17RPSysSystemWinMgr=0x8043c530 createSystemWindow__17RPSysSystemWinMgrFv=0x801a14c8 @@ -2894,11 +2915,19 @@ spInstance__16RPSysHomeMenuMgr=0x8043c538 LoadResource__16RPSysHomeMenuMgrFv=0x801a29a8 spInstance__19RPSysKokeshiManager=0x8043c4d0 LoadStaticResource__19RPSysKokeshiManagerFv=0x80190660 +__ct__11RPSysEffectFPCcUlUl=0x80193d1c spInstance__14RPSysEffectMgr=0x8043c4d8 LoadResource__14RPSysEffectMgrFv=0x80190d40 initBanner__16RPSysSaveDataMgrFv=0x80188490 createBannerFile__16RPSysSaveDataMgrFv=0x80188218 +loadSync__16RPSysSaveDataMgrFv=0x80188038 +saveSync__16RPSysSaveDataMgrFv=0x80188124 +saveBannerFile__16RPSysSaveDataMgrFQ216RPSysSaveDataMgr11EBannerType=0x80187f68 +setPartySystemData__16RPSysSaveDataMgrFRC17RPPartySystemData=0x80188d74 +getPartySystemData__16RPSysSaveDataMgrCFv=0x80188e6c createTimeStamp__11RPSysSystemFv=0x80182fa0 +getNandEndMessage__11RPSysSystemCFv=0x80182ea0 +getNandThread__11RPSysSystemFv=0x80182eb8 spInstance__14RPPartyGameMgr=0x8043c6c8 Reset__14RPPartyGameMgrFv=0x801e4a90 DestroyInstance__14RPPartyGameMgrFv=0x801e4ad4 @@ -2906,6 +2935,11 @@ SetEfbClearColor__13RPGrpRendererFUcUcUc=0x801ad9cc spInstance__16RPSysFontManager=0x8043c4a0 GetResFontData__16RPSysFontManagerCFPCc=0x8018a11c GetInstance__Q44nw4r3snd6detail9AxManagerFv=0x800312e0 +List_GetNext__Q24nw4r2utFPCQ34nw4r2ut4ListPCv=0x80007a14 +IsValid__Q34nw4r2ef10HandleBaseCFv=0x8001cc50 +GetPtr__Q34nw4r2ef10HandleBaseCFv=0x8001cc7c +ForeachParticleManager__Q34nw4r2ef6EffectFPFPvUl_vUlb=0x80011398 +create__11RPSysEffectFv=0x80193b84 __ct__Q34nw4r2ut7ResFontFv=0x8000aaa4 SetResource__Q34nw4r2ut7ResFontFPv=0x8000ab38 SetupGX__Q34nw4r2ut10CharWriterFv=0x8000b1ec @@ -2931,3 +2965,307 @@ __ct__Q34nw4r2ut17TextWriterBaseFv=0x8000e65c Print__Q34nw4r2ut17TextWriterBaseFPCwi=0x8000ecb8 __dt__Q34nw4r2ut10CharWriterFv=0x8000b1ac __dt__Q34nw4r2ut17TextWriterBaseFv=0x8000e6b8 +spInstance__14RPDucCursorMgr=0x8043c878 +PlayCursorOnSfx__14RPDucCursorMgrFl=0x80244648 +EnableCursor__14RPDucCursorMgrFbl=0x8024476c +CreateCursors__14RPDucCursorMgrFUl=0x80244a44 +SetEffectState__14RPDucCursorMgrFlQ211RPDucCursor12EEffectState=0x8024476c +spInstance__13RPDucSequence=0x8043c890 +__vt__14RPDucCursorMgr=0x8035a488 +__dt__14RPDucCursorMgrFv=0x80244ad0 +FUN_80244790__14RPDucCursorMgrFv=0x80244790 +Exit__14RPDucCursorMgrFv=0x802447f8 +FUN_801b6b74__14RPDucCursorMgrFv=0x801b6b74 +FUN_80244a40__14RPDucCursorMgrFv=0x80244a40 +CreateInstance__14RPDucCursorMgrFv=0x80244b6c +DestroyInstance__14RPDucCursorMgrFv=0x80244b28 +__ct__11RPDucCursorFv=0x8024452c +__dt__11RPDucCursorFv=0x802444d4 +Configure__11RPDucCursorFv=0x80243aa4 +LoadResource__11RPDucCursorFv=0x801b6b70 +Reset__11RPDucCursorFv=0x802439cc +Calculate__11RPDucCursorFv=0x80243424 +VF_1C__11RPDucCursorFv=0x801b6b64 +VF_20__11RPDucCursorFv=0x80243420 +VF_34__11RPDucCursorFv=0x80243418 +StartAnimOut__16RPBilBallDisplayFv=0x802d04ac +CalcDisplay__16RPBilBallDisplayFUlfUlUl=0x802d04d0 +spInstance__21RPBilPocketCamManager=0x8043ca20 +HurryUp__21RPBilPocketCamManagerFv=0x802cb77c +StartCamera__21RPBilPocketCamManagerFl=0x802cb7b0 +ResetRack__9RPBilBallFv=0x802c20d0 +PreCalculate__9RPBilBallFv=0x802c24b4 +PostCalculate__9RPBilBallFv=0x802c2140 +GetClosePocketIndex__9RPBilBallCFv=0x802c18f8 +CalcBallCollision__16RPBilBallManagerFv=0x802c4338 +CalcTableCollision__16RPBilBallManagerFv=0x802c3a94 +spInstance__10RPBilTable=0x8043c9b8 +IsValidPlaceFoul__10RPBilTableCFRCQ23EGG8Vector3ff=0x802bb008 +CheckRayIntersect__9RPBilBallFRCQ23EGG5Ray3ffRQ23EGG8Vector3fRf=0x802c19c0 +__ct__16RPBilBallManagerFv=0x802c4ee8 +__ct__16RPBilBallDisplayFUl=0x802d0a34 +__dt__16RPBilBallDisplayFv=0x802d0b44 + +getPosition__15RPPartyUtlModelCFv=0x801b8fa8 +getVelocity__15RPPartyUtlModelCFv=0x801b8fcc +FUN_801b8ff0__15RPPartyUtlModelCFv=0x801b8ff0 +getMtxZBase__15RPPartyUtlModelCFv=0x801b9014 +getMtxYBase__15RPPartyUtlModelCFv=0x801b9038 +getMtxXBase__15RPPartyUtlModelCFv=0x801b905c +getScale__15RPPartyUtlModelCFv=0x801b9080 +getModel__15RPPartyUtlModelCFv=0x801b9090 +isStopped__20RPPartyUtlModelRigidCFv=0x801bb80c + +setPosition__15RPPartyUtlModelFRCQ23EGG8Vector3f=0x801b8fb0 +setVelocity__15RPPartyUtlModelFRCQ23EGG8Vector3f=0x801b8fd4 +FUN_801b8ff8__15RPPartyUtlModelFRCQ23EGG8Vector3f=0x801b8ff8 +setMtxZBase__15RPPartyUtlModelFRCQ23EGG8Vector3f=0x801b901c +setMtxYBase__15RPPartyUtlModelFRCQ23EGG8Vector3f=0x801b9040 +setMtxXBase__15RPPartyUtlModelFRCQ23EGG8Vector3f=0x801b9064 +setScale__15RPPartyUtlModelFf=0x801b9088 +setModel__15RPPartyUtlModelFP10RPGrpModel=0x801b9098 + +calcModel__15RPPartyUtlModelFv=0x801b8d54 + +CreateInstance__16RPBilBallManagerFv=0x802c5208 +DestroyInstance__16RPBilBallManagerFv=0x802c51c4 +__dt__16RPBilBallManagerFv=0x802c5158 +UserDraw__16RPBilBallManagerFv=0x802c4ee4 + +Configure__16RPBilBallDisplayFv=0x802d092c +Reset__16RPBilBallDisplayFv=0x802d0920 +Calculate__16RPBilBallDisplayFv=0x802d07c8 +Exit__16RPBilBallDisplayFv=0x802d091c + +__ct__9RPBilBallFUl=0x802c2674 +__dt__9RPBilBallFv=0x802c2850 +Configure__9RPBilBallFv=0x802c2510 +Reset__9RPBilBallFv=0x802c24bc +Calculate__9RPBilBallFv=0x802c24ac +Exit__9RPBilBallFv=0x802c24b8 +UserDraw__9RPBilBallFv=0x802c200c + +getPosition__9RPBilBallCFv=0x802bd7f0 +getVelocity__9RPBilBallCFv=0x802c185c +getMtxZBase__9RPBilBallCFv=0x802c2acc +getMtxYBase__9RPBilBallCFv=0x802c2af4 +getMtxXBase__9RPBilBallCFv=0x802c2b1c +getScale__9RPBilBallCFv=0x802c2b44 + +setPosition__9RPBilBallFRCQ23EGG8Vector3f=0x802c2aa4 +setVelocity__9RPBilBallFRCQ23EGG8Vector3f=0x802c2ab8 +setMtxZBase__9RPBilBallFRCQ23EGG8Vector3f=0x802c2ae0 +setMtxYBase__9RPBilBallFRCQ23EGG8Vector3f=0x802c2b08 +setMtxXBase__9RPBilBallFRCQ23EGG8Vector3f=0x802c2b30 +setScale__9RPBilBallFf=0x802c2b58 +GetFootSpotPos__10RPBilTableFv=0x802baf18 + +unbindAllAnmObj__11RPSysLayoutFv=0x80194d54 +bindAnmObj__11RPSysLayoutFP14RPSysLytAnmObj=0x80194d80 + +__ct__8RPBilCueFUl=0x802c0bc0 +__dt__8RPBilCueFv=0x802c1060 +Configure__8RPBilCueFv=0x802c0970 +Reset__8RPBilCueFv=0x802c08b0 +Calculate__8RPBilCueFv=0x802c0390 +Exit__8RPBilCueFv=0x802c08a4 +UserDraw__8RPBilCueFv=0x802bcd6c + +State_PLACEFOUL_enter__8RPBilCueFv=0x802c02e0 +State_PLACEFOUL_calc__8RPBilCueFv=0x802c00d4 + +State_WAIT_enter__8RPBilCueFv=0x802bff04 +State_WAIT_calc__8RPBilCueFv=0x802bf9d4 + +State_HOLD_enter__8RPBilCueFv=0x802bf950 +State_HOLD_calc__8RPBilCueFv=0x802bf754 + +State_PULL_enter__8RPBilCueFv=0x802bf394 +State_PULL_calc__8RPBilCueFv=0x802be744 + +State_FASTTURN_enter__8RPBilCueFv=0x802be5b0 +State_FASTTURN_calc__8RPBilCueFv=0x802bdff8 + +State_HIT_enter__8RPBilCueFv=0x802bdf70 +State_HIT_calc__8RPBilCueFv=0x802bdc94 + +State_DUMMY_enter__8RPBilCueFv=0x802bdc90 +State_DUMMY_calc__8RPBilCueFv=0x802bdc8c + +CreateInstance__15RPBilCueManagerFv=0x802c1660 +DestroyInstance__15RPBilCueManagerFv=0x802c161c + +__vt__15RPBilCueManager=0x8035de58 +__dt__15RPBilCueManagerFv=0x802c15dc +sPlayerNum__9RPBilMain=0x8043ca04 + +__ct__20RPPartyUtlModelRigidFRCQ220RPPartyUtlModelRigid10RigidParam=0x801bd7e4 +Calculate__20RPPartyUtlModelRigidFv=0x801bd284 + +CalcMtx__8RPBilCueFv=0x802bd330 +CalcForce__8RPBilCueFv=0x802bd62c +FUN_802bd450__8RPBilCueFv=0x802bd450 +CalcMove__8RPBilCueFb=0x802bd0f8 +CalcDpd__8RPBilCueFv=0x802bcef0 + +LoadResFonts__16RPSysFontManagerFv=0x8018a1b4 +__ct__9RPSysFileFPCclPCv=0x80197924 +LoadFromDVD__20RPSysResourceManagerFPCcPQ23EGG4HeaplPl=0x80186754 +checkCompressed__Q23EGG6DecompFPUc=0x800ad72c +getExpandSize__Q23EGG6DecompFPUc=0x800ad7b0 +decode__Q23EGG6DecompFPUcPUc=0x800ac88c +__ct__18RPPartyBodyManagerFv=0x801cb250 +__dt__Q23EGG8DisposerFv=0x800ac520 +__dt__9RPSysFileFv=0x801978b0 +findContainHeap__Q23EGG4HeapFPCv=0x800a37ac +spInstance__18RPBilLytBallNumber=0x8043ca68 +__ct__12RPUtlLytBaseFv=0x801b9fc8 +__vt__18RPBilLytBallNumber=0x8035e680 +__dt__18RPBilLytBallNumberFv=0x802d34b4 +mountArchive__12RPUtlLytBaseFPQ23EGG7ArchivePCcP19RPSysLytResAccessor=0x801b9f88 +create__11RPSysLayoutFPQ23EGG4HeapP19RPSysLytResAccessorPCc=0x80194f88 +createAnmObj__11RPSysLayoutFPQ23EGG4HeapP19RPSysLytResAccessorPCc=0x80194d98 +findPane__11RPSysLayoutFPCc=0x801947b4 +UserDraw__18RPBilLytBallNumberFv=0x802d2d28 + +State_HIDE_enter__18RPBilLytBallNumberFv=0x802d3000 +State_HIDE_calc__18RPBilLytBallNumberFv=0x802d2f80 + +State_ANIMIN_enter__18RPBilLytBallNumberFv=0x802d2eb4 +State_ANIMIN_calc__18RPBilLytBallNumberFv=0x802d2e94 + +State_WAIT_enter__18RPBilLytBallNumberFv=0x802d2e90 +State_WAIT_calc__18RPBilLytBallNumberFv=0x802d2e68 + +State_ANIMOUT_enter__18RPBilLytBallNumberFv=0x802d2de4 +State_ANIMOUT_calc__18RPBilLytBallNumberFv=0x802d2dc4 + +VF_14__12RPUtlLytBaseFv=0x801ba014 +VF_18__12RPUtlLytBaseFv=0x801b9f84 + +Reset__18RPBilLytBallNumberFv=0x802d31f4 +Calculate__18RPBilLytBallNumberFv=0x802d3004 + +CreateInstance__18RPBilLytBallNumberFv=0x802d3538 +DestroyInstance__18RPBilLytBallNumberFv=0x802d34f4 +ident__Q23EGG9Matrix34f=0x8043a388 + +CreateData__20RPGrpModelResManagerFQ220RPGrpModelResManager4TypePvUl=0x801ac724 +GetPtr__20RPGrpModelResManagerCFQ220RPGrpModelResManager4TypeUsPCc=0x801ac550 +Construct__10RPGrpModelFUsPCcUlUlUl=0x801a7d6c +CreateBuffer__13RPGrpModelAnmFQ213RPGrpModelAnm3AnmUs=0x801a8450 +__ct__15RPPartyUtlModelFv=0x801b8e3c +__dt__15RPPartyUtlModelFv=0x801b8f40 +__ct__Q23EGG6ScreenFffffPCQ23EGG6ScreenQ33EGG7Frustum10CanvasMode=0x8009911c +CreateView3D__13RPGrpRendererFUcP11RPGrpCameraP11RPGrpScreen=0x801acff0 +__ct__11RPGrpCameraFv=0x801a6ca0 +LoadScnCameraMatrix__11RPGrpCameraFQ34nw4r3g3d9ResAnmScnUcf=0x801a6228 +GetResAnmScn__Q34nw4r3g3d7ResFileCFPCc=0x8005160c +MTX34RotXYZFIdx__Q24nw4r4mathFPQ34nw4r4math5MTX34fff=0x8002ff8c +SetMtx__Q34nw4r3g3d6ScnObjFQ44nw4r3g3d6ScnObj13ScnObjMtxTypePCQ34nw4r4math5MTX34=0x8006fc38 +SinCosFIdx__Q24nw4r4mathFPfPff=0x8002fa98 +FrSqrt__Q24nw4r4mathFf=0x8002f9ac +CosFIdx__Q24nw4r4mathFf=0x8002fa3c +SinFIdx__Q24nw4r4mathFf=0x8002f9d0 +create__19RPSysLytResAccessorFPQ23EGG4Heap=0x80196efc +mountArchive__19RPSysLytResAccessorFPvPCc=0x80196eb0 +findTextBox__11RPSysLayoutFPCc=0x80194704 +draw__11RPSysLayoutFv=0x80194250 +calc__11RPSysLayoutFv=0x801942b8 +system_halt=0x800a17d8 +GetPaneRect__Q34nw4r3lyt4PaneCFRCQ34nw4r3lyt8DrawInfo=0x80079324 +__ct__Q34nw4r3lyt8DrawInfoFv=0x80081978 +__dt__Q34nw4r3lyt8DrawInfoFv=0x800819ec + +spInstance__14RPTnkMapResMgr=0x8043c640 +CreateInstance__14RPTnkMapResMgrFv=0x801bfe24 +DestroyInstance__14RPTnkMapResMgrFv=0x801bfde0 +__ct__14RPTnkMapResMgrFv=0x801bfd08 +__dt__14RPTnkMapResMgrFv=0x801bfcc8 +s_cameraMtx__Q23EGG6DrawGX=0x8039f340 + +__ct__10RPTnkBlockFv=0x802619d0 +sWidth__10RPTnkBlock=0x8043b750 +sHeight__10RPTnkBlock=0x8043b754 +spInstance__13RPTnkBlockMgr=0x8043c8f8 +__ct__19RPTnkGameObjMgrBaseFv=0x802590b4 +__vt__13RPTnkBlockMgr=0x8035b748 +__dt__13RPTnkBlockMgrFv=0x80261f0c +UserDraw__14RPUtlActorBaseFv=0x801b6b60 +Exit__14RPUtlActorBaseFv=0x801b6b64 +Calculate__14RPUtlActorBaseFv=0x801b6b68 +Configure__14RPUtlActorBaseFv=0x801b6b74 +CreateInstance__13RPTnkBlockMgrFv=0x80261fa8 +DestroyInstance__13RPTnkBlockMgrFv=0x80261f64 +spInstance__13RPTnkFieldMgr=0x8043c8e0 +spInstance__13RPTnkSequence=0x8043c910 + +__dt__10RPTnkBlockFv=0x80261978 +InitModel__16RPUtlGameObjBaseFb=0x801b739c +GetAnmNumFrame__16RPUtlGameObjBaseCFQ213RPGrpModelAnm3AnmUs=0x801b6ef8 +GetAnmFrame__16RPUtlGameObjBaseCFQ213RPGrpModelAnm3AnmUs=0x801b6f48 +SetAnmUpdateRate__16RPUtlGameObjBaseFQ213RPGrpModelAnm3AnmUsf=0x801b6f60 +CancelAnm__16RPUtlGameObjBaseFQ213RPGrpModelAnm3AnmUs=0x801b6f78 +StartAnmBlend__16RPUtlGameObjBaseFQ213RPGrpModelAnm3AnmUsff=0x801b6f90 +StartAnm__16RPUtlGameObjBaseFQ213RPGrpModelAnm3AnmUsf=0x801b6fa8 +BindAnm__16RPUtlGameObjBaseFPCcUsQ213RPGrpModelAnm3AnmUs=0x801b6fdc +BindAnm__16RPUtlGameObjBaseFQ213RPGrpModelAnm3AnmUsUs=0x801b6fc0 +CreateAnm__16RPUtlGameObjBaseFQ213RPGrpModelAnm3AnmUs=0x801b7094 +CreateModel__16RPUtlGameObjBaseFPCcUsUs=0x801b70f4 +CreateModel__16RPUtlGameObjBaseFUs=0x801b70a0 +GetOwner__16RPTnkGameObjBaseCFv=0x80259a78 +SetOwner__16RPTnkGameObjBaseFP16RPTnkGameObjBase=0x802590f0 +IsExplode__16RPTnkGameObjBaseCFv=0x80259a70 +StartExplodeEffect__16RPTnkGameObjBaseFv=0x80259a6c +StopEffect__16RPTnkGameObjBaseFv=0x80259a6c +IsObjTrigger__16RPTnkGameObjBaseCFPC16RPTnkGameObjBase=0x802590f4 +IsExplodeBlock__16RPTnkGameObjBaseCFPC16RPTnkGameObjBase=0x802590fc +SetMinePos__16RPTnkGameObjBaseFRCQ23EGG8Vector3f=0x80259104 +GetID__16RPTnkGameObjBaseCFv=0x80259a50 +VF_90__16RPTnkGameObjBaseFv=0x80259110 +CalcBounding__16RPTnkGameObjBaseFv=0x80259114 +CheckSphereMine__16RPTnkGameObjBaseCFPC16RPTnkGameObjBasePf=0x80259118 +CheckSphere__16RPTnkGameObjBaseCFPC16RPTnkGameObjBasePf=0x8025922c +Destroy__16RPTnkGameObjBaseFv=0x80259340 +Init__16RPTnkGameObjBaseFRCQ23EGG8Vector3fUl=0x80259374 +ThirdCalc__16RPTnkGameObjBaseFv=0x8025942c +ApplyDelta__16RPTnkGameObjBaseFv=0x80259604 +ResetDelta__16RPTnkGameObjBaseFv=0x80259698 +InitParam__16RPTnkGameObjBaseFv=0x802596d0 +GetHeight__10RPTnkBlockCFv=0x80261a30 +CollideBounding__10RPTnkBlockCFPC16RPTnkGameObjBaseUl=0x802604e8 +SecondCalc__10RPTnkBlockFv=0x80260a14 +FirstCalc__10RPTnkBlockFv=0x80260a74 +CalcMove__10RPTnkBlockFv=0x80260bb4 +SetParam__10RPTnkBlockFv=0x80261840 +CalcModel__10RPTnkBlockFv=0x802606a8 +InitBounding__10RPTnkBlockFv=0x802614a8 +Configure__10RPTnkBlockFv=0x80260e78 +LoadResource__10RPTnkBlockFv=0x80260be8 +Reset__16RPTnkGameObjBaseFv=0x80259484 +Calculate__10RPTnkBlockFv=0x802609b4 +UserDraw__16RPUtlGameObjBaseFv=0x801b6ef0 +spInstance__12RPTnkMineMgr=0x8043c920 +IsExplodeBlock__12RPTnkMineMgrCFPC16RPTnkGameObjBase=0x802668d0 +StartBreakEffect__10RPTnkBlockFv=0x80260ec8 +spInstance__13RPTnkShellMgr=0x8043c900 +__ct__Q34nw4r3snd14SeqSoundHandleFPQ34nw4r3snd11SoundHandle=0x8003fcd0 +DetachSound__Q34nw4r3snd14SeqSoundHandleFv=0x8003fdd8 +DetachSound__Q34nw4r3snd11SoundHandleFv=0x80045c80 +detail_AttachSound__Q34nw4r3snd11SoundHandleFPQ44nw4r3snd6detail10BasicSound=0x80045c34 +detail_AttachSoundAsTempHandle__Q34nw4r3snd11SoundHandleFPQ44nw4r3snd6detail10BasicSound=0x80045bb8 +GetResMat__Q34nw4r3g3d6ResMdlCFPCc=0x80052e6c +UpdateFrame__10RPGrpModelFv=0x801a7a88 + +__ct__Q23EGG12ProcessMeterFb=0x800ab854 +__ct__Q33EGG12ProcessMeter10ProcessBarFQ34nw4r2ut5Colorff=0x800ab580 +__dt__Q23EGG6ThreadFv=0x800a3e70 +measureBeginFrame__Q23EGG12ProcessMeterFv=0x800aba3c +isVisible__Q23EGG12ProcessMeterFv=0x800abeec +setVisible__Q23EGG12ProcessMeterFb=0x800abec4 +draw__Q23EGG12ProcessMeterFv=0x800ac194 +callbackDrawSync__Q23EGG12ProcessMeterFUs=0x800abce8 +measureEndRender__Q23EGG12ProcessMeterFv=0x800abcd8 +measureBeginRender__Q23EGG12ProcessMeterFv=0x800abcc8 +measureEndFrame__Q23EGG12ProcessMeterFv=0x800abcb8 +run__Q23EGG12ProcessMeterFv=0x800ac4bc \ No newline at end of file diff --git a/base/symbols_resort.txt b/base/SymbolsResort.txt similarity index 99% rename from base/symbols_resort.txt rename to base/SymbolsResort.txt index 819c974..1911fb8 100644 --- a/base/symbols_resort.txt +++ b/base/SymbolsResort.txt @@ -127,6 +127,8 @@ __cvt_dbl_sll=0x80007d18 __cvt_dbl_ull=0x80007dc8 __wStringWrite=0x80012a28 __wpformatter=0x8001209c +tan=0x80016d80 +pow=0x80016e10 __DBIntrHandler=0x8001c204 DBInitComm=0x8001c228 @@ -2190,6 +2192,9 @@ nanddrv_unmount=0x800fe760 nanddrv_physical_read=0x800fe970 RFLiInitCharModel=0x80102634 RFLGetFavoriteColor=0x80102a20 +List_Init__Q24nw4r2utFPQ34nw4r2ut4ListUs=0x8010b9e0 +List_Append__Q24nw4r2utFPQ34nw4r2ut4ListPv=0x8010ba00 +List_GetNext__Q24nw4r2utFPCQ34nw4r2ut4ListPCv=0x8010bc00 Skip__Q44nw4r2ut10FileStream12FilePositionFl=0x8010c9c0 Append__Q44nw4r2ut10FileStream12FilePositionFl=0x8010ca30 Seek__Q44nw4r2ut10FileStream12FilePositionFlUl=0x8010ca80 @@ -2417,6 +2422,8 @@ Draw__Q34nw4r2ef24DrawSmoothStripeStrategyFRCQ34nw4r2ef8DrawInfoPQ34nw4r2ef15Par FLog__Q34nw4r4math6detailFf=0x8013b9b0 Hermite__Q24nw4r4mathFfffff=0x8013ba80 Bezier__Q24nw4r4mathFfffff=0x8013bac0 +FrSqrt__Q24nw4r4mathFf=0x8013ba50 +SinFIdx__Q24nw4r4mathFf=0x8013bba0 CosFIdx__Q24nw4r4mathFf=0x8013bc10 SinCosFIdx__Q24nw4r4mathFPfPff=0x8013bc70 AtanFIdx__Q24nw4r4mathFf=0x8013bce0 @@ -3590,13 +3597,22 @@ create__Q23EGG7ExpHeapFUlPQ23EGG4HeapUs=0x801c0e58 alloc__Q23EGG4HeapFUliPQ23EGG4Heap=0x801c1654 free__Q23EGG4HeapFPvPQ23EGG4Heap=0x801c19c4 sConfigData__11RPSysSystem=0x807ceb60 -getCoreStatus__Q23EGG14CoreControllerCFi=0x801c4380 +getCoreStatus__Q23EGG14CoreControllerFi=0x801c4380 getNthController__Q23EGG17CoreControllerMgrFi=0x801c4ab8 __dt__Q23EGG5SceneFv=0x801c8318 sCurrentHeap__Q23EGG4Heap=0x806f49b0 sTVMode__Q23EGG6Screen=0x806f4938 -sTVInfo__Q23EGG6Screen=0x806b4ad8 +sTVModeInfo__Q23EGG6Screen=0x806b4ad8 __ct__Q23EGG6ScreenFv=0x801b83d0 +__ct__Q23EGG8DisposerFv=0x801c9238 +__vt__Q23EGG7Archive=0x806b4fe0 +sIsArchiveListInitialized__Q23EGG7Archive=0x806f4a38 +sArchiveList__Q23EGG7Archive=0x807ce190 + +BeginDrawQuad__Q23EGG6DrawGXFQ33EGG6DrawGX12ColorChannelQ33EGG6DrawGX5ZModeQ33EGG6DrawGX5Blendbb=0x801a68f4 +makeIdentity__Q23EGG9Matrix34fFv=0x801c0678 +s_cameraMtx__Q23EGG6DrawGX=0x807cc980 +DrawDL__Q23EGG6DrawGXFQ33EGG6DrawGX2DLRCQ34nw4r4math5MTX34=0x801a8700 spInstance__11RPSysSystem=0x806f4c68 spInstance__13RPSysSceneMgr=0x806f4c98 @@ -3611,6 +3627,7 @@ draw__10RPSysSceneFv=0x8022f73c enter__10RPSysSceneFv=0x8022f9d8 exit__10RPSysSceneFv=0x8022f694 reinit__10RPSysSceneFv=0x8022f960 +isNandAccessEnable__10RPSysSceneCFv=0x8022fdb8 incoming_childDestroy__10RPSysSceneFv=0x8022f900 outgoing_childCreate__10RPSysSceneFv=0x8022f6fc pauseCallBack__10RPSysSceneFb=0x801cf764 diff --git a/base/symbols_sports.txt b/base/SymbolsSports.txt similarity index 100% rename from base/symbols_sports.txt rename to base/SymbolsSports.txt diff --git a/configure.py b/configure.py new file mode 100644 index 0000000..bb9ea13 --- /dev/null +++ b/configure.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 + +# =============================================================================# +# # +# Kokeshi build script # +# # +# =============================================================================# + +from tools.ninja_kokeshi import KokeshiProject + +# =============================================================================# +# Project configuration # +# =============================================================================# +proj = KokeshiProject() + +# =============================================================================# +# Game(s) that your mod should build for. +# By default, we try building for Wii Sports. +# +# You can build for multiple games by writing multiple pack names. +# Valid choices are: "sports" (Wii Sports), "play" (Wii Play), "resort" (WSR) +# +# To handle this in your code, expect preprocessor definitions of the format +# PACK_{NAME}, (i.e. PACK_SPORTS, PACK_RESORT). +# +# =============================================================================# +proj.packs = ["resort"] + +# =============================================================================# +# Common compiler flags to apply across all code. +# +# See _cflags_common_internal inside 'ninja_kokeshi.py' to see +# which flags are already in use. +# +# =============================================================================# +proj.cflags_common = [ + "-maxerrors 1", +] + +# =============================================================================# +# Compiler flags to apply across all module code. +# +# =============================================================================# +proj.cflags_module = [] + +# =============================================================================# +# Compiler flags to apply across all module code in release builds. +# (We don't support multiple build targets yet, so this goes unused.) +# +# =============================================================================# +proj.cflags_release = [] + +# =============================================================================# +# Compiler flags to apply across all module code in debug builds. +# (We don't support multiple build targets yet, so this goes unused.) +# +# =============================================================================# +proj.cflags_debug = [] + +# =============================================================================# +# Whether to include the latest Git repository commit hash (shortened) as a +# preprocessor definition ("GIT_COMMIT_HASH") when compiling the module. +# +# NOTE: It is assumed that the Git repository is the current working directory, +# and that command-line Git is installed on the current machine. +# +# =============================================================================# +proj.use_git_commit_hash = True + +# =============================================================================# +# Creates the Ninja build script for your configuration. +# +# To see additional project settings, see KokeshiProject +# inside 'ninja_kokeshi.py'. +# +# =============================================================================# +proj.emit() diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 0d7aca5..23e269a 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -247,7 +247,7 @@ public: // 1. Type aliases (`friend`, `typedef`, `using`) friend class BasketMgr; - typedef TList FruitBasketList; + typedef TList FruitBasketList; using IBasket::Foo; // 2. Nested types @@ -444,10 +444,10 @@ Macros can be documented like functions, but also a single-line comment will suf * @param major Major version number * @param minor Minor version number */ -#define K_BIN_VERSION(major, minor) ((major << 8) | minor) +#define K_VERSION(major, minor) ((major << 8) | minor) //! Helper for creating version numbers -#define K_BIN_VERSION(major, minor) ((major << 8) | minor) +#define K_VERSION(major, minor) ((major << 8) | minor) ``` ##### Data diff --git a/include/MSL/algorithm b/include/MSL/algorithm index 73280cc..98a9134 100644 --- a/include/MSL/algorithm +++ b/include/MSL/algorithm @@ -113,17 +113,13 @@ void sort(TIt first, TIt last, TCompare compare) { } static int shuffle = -4; - TIt m = first + - (len / static_cast(sizeof(TIt)) + shuffle % SHUFFLE_MAX); + TIt m = first + (len / 4 + shuffle % SHUFFLE_MAX); if (++shuffle >= SHUFFLE_MAX) { shuffle = SHUFFLE_MIN; } - TIt i1 = first + (len * static_cast(sizeof(TIt) - 1) / - static_cast(sizeof(TIt)) + - shuffle % SHUFFLE_MAX); - + TIt i1 = first + (len * 3 / 4 + shuffle % SHUFFLE_MAX); if (++shuffle >= SHUFFLE_MAX) { shuffle = SHUFFLE_MIN; } diff --git a/include/Pack/RPAudio.h b/include/Pack/RPAudio.h index 27da550..b852385 100644 --- a/include/Pack/RPAudio.h +++ b/include/Pack/RPAudio.h @@ -2,24 +2,6 @@ #define RP_AUDIO_H #include -// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// -#include -#include -#include +#include #endif diff --git a/include/Pack/RPAudio/RPSndAudioMgr.h b/include/Pack/RPAudio/RPSndAudioMgr.h index 77407df..f5e28ae 100644 --- a/include/Pack/RPAudio/RPSndAudioMgr.h +++ b/include/Pack/RPAudio/RPSndAudioMgr.h @@ -12,9 +12,6 @@ /** * @brief RP sound manager (BGM, SFX, etc.) - * - * @todo The %EGG inheritance is not quite correct. Virtual function calls do - * not work correctly. */ class RPSndAudioMgr : public EGG::ExpAudioMgr { RP_SINGLETON_DECL_EX(RPSndAudioMgr); @@ -25,10 +22,10 @@ class RPSndAudioMgr : public EGG::ExpAudioMgr { void setSystemSeFadeInFrame(s16 frame); bool startSound(u32 id) { - return RPSndAudioMgr::startSound(&mSndHandle, id); + return RPSndAudioMgr::startSound(&mSndHandleStrm, id); } bool startSound(const char* name) { - return RPSndAudioMgr::startSound(&mSndHandle, name); + return RPSndAudioMgr::startSound(&mSndHandleStrm, name); } void stopAllSoud(); @@ -40,9 +37,17 @@ class RPSndAudioMgr : public EGG::ExpAudioMgr { void changeScene(); + nw4r::snd::SoundHandle* getSoundHandleSeq() { + return &mSndHandleSeq; + } + nw4r::snd::SoundHandle* getSoundHandleStrm() { + return &mSndHandleStrm; + } + private: - char UNK_0x898[0x90]; - nw4r::snd::SoundHandle mSndHandle; // at 0x928 + char _8A0[0x920 - 0x8A0]; + nw4r::snd::SoundHandle mSndHandleSeq; // at 0x920 + nw4r::snd::SoundHandle mSndHandleStrm; // at 0x924 }; //! @} diff --git a/include/Pack/RPAudio/RPSndMoveValueF32.h b/include/Pack/RPAudio/RPSndMoveValueF32.h new file mode 100644 index 0000000..d871163 --- /dev/null +++ b/include/Pack/RPAudio/RPSndMoveValueF32.h @@ -0,0 +1,20 @@ +#ifndef RP_AUDIO_SND_MOVE_VALUE_F32_H +#define RP_AUDIO_SND_MOVE_VALUE_F32_H +#include + +//! @addtogroup rp_audio +//! @{ + +class RPSndMoveValueF32 { +public: + RPSndMoveValueF32(); + + virtual bool update(); // at 0x8 + +private: + char _04[0x1C - 0x4]; +}; + +//! @} + +#endif diff --git a/include/Pack/RPAudio/RPSndObject.h b/include/Pack/RPAudio/RPSndObject.h new file mode 100644 index 0000000..2482fb2 --- /dev/null +++ b/include/Pack/RPAudio/RPSndObject.h @@ -0,0 +1,170 @@ +#ifndef RP_AUDIO_SND_OBJECT_H +#define RP_AUDIO_SND_OBJECT_H +#include +#include + +#include +#include + +#include +#include + +//! @addtogroup rp_audio +//! @{ + +/****************************************************************************** + * + * RPSndAudioActorBase + * + ******************************************************************************/ +class RPSndAudioActorBase : public EGG::Disposer { +public: + RPSndAudioActorBase(UNKWORD arg0) : mIsSilenced(false), WORD_0x14(arg0) { + nw4r::ut::List_Append(&sActorList, this); + } + + virtual ~RPSndAudioActorBase() { + nw4r::ut::List_Remove(&sActorList, this); + } // at 0x8 + + virtual void stopSound(u32 id, int frames) = 0; // at 0xC + virtual void stopSound(unsigned int id, int frames) = 0; // at 0x10 + virtual void stopSound(const char* pName, int frames) = 0; // at 0x14 + virtual void stopAllSound(int frames) = 0; // at 0x18 + + virtual void setActorVolume(f32 volume, int frames) = 0; // at 0x1C + virtual void update() = 0; // at 0x20 + + static nw4r::ut::List& getActorList() { + return sActorList; + } + +protected: + RPSndMoveValueF32 mVolume; // at 0x8 + bool mIsSilenced; // at 0x10 + UNKWORD WORD_0x14; // at 0x14 + +private: + static nw4r::ut::List sActorList; +}; + +/****************************************************************************** + * + * TRPSndAudioHandles + * + ******************************************************************************/ +template class TRPSndAudioHandles { +public: + TRPSndAudioHandles() : mHandleCount(N), COUNT_0xC(N) {} + + ~TRPSndAudioHandles() { + mHandleCount = 0; + COUNT_0xC = 0; + } + + virtual f32 getOuterVolume() { + return 1.0f; + } // at 0x8 + virtual f32 getOuterPitch() { + return 1.0f; + } // at 0xC + +protected: + s32 mHandleCount; + s32 COUNT_0xC; + nw4r::snd::SoundHandle mSoundHandles[N]; +}; + +/****************************************************************************** + * + * TRPSndAudioActorBaseWithHandles + * + ******************************************************************************/ +template +class TRPSndAudioActorBaseWithHandles : public RPSndAudioActorBase, + public TRPSndAudioHandles { +public: + TRPSndAudioActorBaseWithHandles(UNKWORD arg0) : RPSndAudioActorBase(arg0) {} + + virtual const nw4r::math::VEC3* get3DPosition(int idx) { + return NULL; + } // at 0x10 +}; + +/****************************************************************************** + * + * TRPSndAudio3DActor + * + ******************************************************************************/ +template class TRPSndAudio3DActor : public EGG::AudioSound3DActor { +public: + TRPSndAudio3DActor(nw4r::snd::SoundArchivePlayer& rPlayer) { + for (int i = 0; i < N; i++) { +#line 375 + EGG_ASSERT(smCommon3DManager[i]); + + mSound3DActors[i] = + new nw4r::snd::Sound3DActor(rPlayer, smCommon3DManager[i]); + } + } + +protected: + nw4r::snd::Sound3DActor* mSound3DActors[N]; +}; + +/****************************************************************************** + * + * TRPSndObject + * + ******************************************************************************/ +template +class TRPSndObject : public TRPSndAudio3DActor, + public TRPSndAudioActorBaseWithHandles { +public: + enum RemoteFlag { + FLAG_REMOTE_1 = 1 << 0, + FLAG_REMOTE_2 = 1 << 1, + FLAG_REMOTE_3 = 1 << 2, + FLAG_REMOTE_4 = 1 << 3, + + FLAG_REMOTE_ALL = + FLAG_REMOTE_1 | FLAG_REMOTE_2 | FLAG_REMOTE_3 | FLAG_REMOTE_4 + }; + +public: + TRPSndObject(nw4r::snd::SoundArchivePlayer& rPlayer, + nw4r::snd::Sound3DManager& /* rManager */, + u32 remoteFlag = FLAG_REMOTE_ALL) + : TRPSndAudio3DActor(rPlayer), + TRPSndAudioActorBaseWithHandles(0), + BOOL_0x7C(false), + mRemoteFlag(remoteFlag) {} + + virtual const nw4r::math::VEC3* get3DPosition(int idx); // at 0x10 + virtual void set3DPosition(const nw4r::math::VEC3& rPos); // at 0x14 + + virtual void calc(); // at 0x18 + virtual void update(); // at 0x1C + + virtual nw4r::snd::SoundHandle* startSoundWithRemotePlayer(u32, u32, + s32); // at 0x20 + virtual nw4r::snd::SoundHandle* + startSoundWithRemotePlayer(unsigned int, u32, s32); // at 0x24 + virtual nw4r::snd::SoundHandle* startSoundWithRemotePlayer(const char*, u32, + s32); // at 0x28 + + virtual nw4r::snd::SoundHandle* startSound(u32 id, + u32 handle = 0); // at 0x20 + virtual nw4r::snd::SoundHandle* startSound(unsigned int id, + u32 handle = 0); // at 0x24 + + // TODO.... more virtual functions.... + +private: + bool BOOL_0x7C; + u32 mRemoteFlag; +}; + +//! @} + +#endif diff --git a/include/Pack/RPAudio/archive/rp_Bil_sound.h b/include/Pack/RPAudio/archive/rp_Bil_sound.h index d9264f0..6bbcd80 100644 --- a/include/Pack/RPAudio/archive/rp_Bil_sound.h +++ b/include/Pack/RPAudio/archive/rp_Bil_sound.h @@ -9,8 +9,6 @@ //! @} -namespace rp_Bil_sound { - enum { /* 0x00 */ RP_BIL_SE_KANSEI_END, /* 0x01 */ RP_BIL_SE_CUE_FIX, @@ -121,6 +119,4 @@ enum { /* 0x6A */ RP_COMMON_SE_KEY_CURSOR_01 }; -} // namespace rp_Bil_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Bom_sound.h b/include/Pack/RPAudio/archive/rp_Bom_sound.h index 80037c2..5434ea5 100644 --- a/include/Pack/RPAudio/archive/rp_Bom_sound.h +++ b/include/Pack/RPAudio/archive/rp_Bom_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Bom_sound { - -enum ESoundID { +enum { /* 0x00 */ RP_BOM_SE_COIN_BREED, /* 0x01 */ RP_BOM_SE_NG_01, /* 0x02 */ RP_BOM_SE_CHANGE_POSE, @@ -103,6 +101,4 @@ enum ESoundID { /* 0x58 */ RP_COMMON_SE_KEY_CURSOR_01 }; -} // namespace rp_Bom_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Bow_sound.h b/include/Pack/RPAudio/archive/rp_Bow_sound.h index ecb71a5..adc519d 100644 --- a/include/Pack/RPAudio/archive/rp_Bow_sound.h +++ b/include/Pack/RPAudio/archive/rp_Bow_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Bow_sound { - -enum ESoundID { +enum { /* 0x00 */ SE_TR_Training_Kabeyoke_Replay_WallEffect, /* 0x01 */ SE_TR_HitFloor, /* 0x02 */ SE_TR_HitFloor_TVSP, @@ -173,6 +171,4 @@ enum ESoundID { /* 0x9E */ RP_COM_GAME_SE_PAUSE_KEY_A_01 }; -} // namespace rp_Bow_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Box_sound.h b/include/Pack/RPAudio/archive/rp_Box_sound.h index e0934bd..2b0750e 100644 --- a/include/Pack/RPAudio/archive/rp_Box_sound.h +++ b/include/Pack/RPAudio/archive/rp_Box_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Box_sound { - -enum ESoundID { +enum { /* 0x000 */ SE_TR_punch_jab, /* 0x001 */ SE_TR_punch_jab_TVSP, /* 0x002 */ SE_TR_punch_straight, @@ -280,6 +278,4 @@ enum ESoundID { /* 0x109 */ RP_COM_GAME_SE_PAUSE_KEY_A_01 }; -} // namespace rp_Box_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Bsb_sound.h b/include/Pack/RPAudio/archive/rp_Bsb_sound.h index 84b35e9..2f77514 100644 --- a/include/Pack/RPAudio/archive/rp_Bsb_sound.h +++ b/include/Pack/RPAudio/archive/rp_Bsb_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Bsb_sound { - -enum ESoundID { +enum { /* 0x00 */ SE_TR_BallFall, /* 0x01 */ SE_TR_ScoreDispChange, /* 0x02 */ SE_TR_Furikaburi, @@ -192,6 +190,4 @@ enum ESoundID { /* 0xB1 */ RP_COM_GAME_SE_PAUSE_KEY_A_01 }; -} // namespace rp_Bsb_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Common_Party.h b/include/Pack/RPAudio/archive/rp_Common_Party.h index 5c22a59..45709d3 100644 --- a/include/Pack/RPAudio/archive/rp_Common_Party.h +++ b/include/Pack/RPAudio/archive/rp_Common_Party.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Common_Party { - -enum ESoundID { +enum { /* 0x00 */ RP_COMMON_SE_LOGO_01, /* 0x01 */ RP_COMMON_SE_WIN_OPEN_01, /* 0x02 */ RP_COMMON_SE_WIN_CLOSE_01, @@ -83,6 +81,4 @@ enum ESoundID { /* 0x44 */ RP_COMMON_SE_KEY_CURSOR_01 }; -} // namespace rp_Common_Party - #endif diff --git a/include/Pack/RPAudio/archive/rp_Common_Sports.h b/include/Pack/RPAudio/archive/rp_Common_Sports.h index b3795ad..8d38234 100644 --- a/include/Pack/RPAudio/archive/rp_Common_Sports.h +++ b/include/Pack/RPAudio/archive/rp_Common_Sports.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Common_Sports { - -enum ESoundID { +enum { /* 0x00 */ RP_COMMON_SE_LOGO_01, /* 0x01 */ RP_COMMON_SE_WIN_OPEN_01, /* 0x02 */ RP_COMMON_SE_WIN_CLOSE_01, @@ -92,6 +90,4 @@ enum ESoundID { /* 0x4D */ RP_COM_GAME_SE_PAUSE_KEY_A_01 }; -} // namespace rp_Common_Sports - #endif diff --git a/include/Pack/RPAudio/archive/rp_Cow_sound.h b/include/Pack/RPAudio/archive/rp_Cow_sound.h index 25ccdfc..346a537 100644 --- a/include/Pack/RPAudio/archive/rp_Cow_sound.h +++ b/include/Pack/RPAudio/archive/rp_Cow_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Cow_sound { - -enum ESoundID { +enum { /* 0x00 */ RP_COW_SE_CON_01_L_CTSP, /* 0x01 */ RP_COW_SE_CON_01_R_CTSP, /* 0x02 */ RP_COW_SE_CON_02_1P_TALK_CTSP, @@ -175,6 +173,4 @@ enum ESoundID { /* 0xA0 */ RP_COM_BGM_RENEW_RECORD }; -} // namespace rp_Cow_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Duc_sound.h b/include/Pack/RPAudio/archive/rp_Duc_sound.h index 5be8c71..f9a1541 100644 --- a/include/Pack/RPAudio/archive/rp_Duc_sound.h +++ b/include/Pack/RPAudio/archive/rp_Duc_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Duc_sound { - -enum ESoundID { +enum { /* 0x00 */ RP_DUC_AMB_01, /* 0x01 */ RP_DUC_SE_TARGET_BOUND_GRASS, /* 0x02 */ RP_DUC_SE_TARGET_GRASS_01, @@ -127,6 +125,4 @@ enum ESoundID { /* 0x70 */ RP_COM_BGM_RENEW_RECORD }; -} // namespace rp_Duc_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Fsh_sound.h b/include/Pack/RPAudio/archive/rp_Fsh_sound.h index 51afabd..60855e3 100644 --- a/include/Pack/RPAudio/archive/rp_Fsh_sound.h +++ b/include/Pack/RPAudio/archive/rp_Fsh_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Fsh_sound { - -enum ESoundID { +enum { /* 0x00 */ RP_FSH_SE_FISH_ROD_CATCH_01, /* 0x01 */ RP_FSH_SE_FISH_ROD_SWING_01, /* 0x02 */ RP_FSH_SE_FEED_FLY_01, @@ -134,6 +132,4 @@ enum ESoundID { /* 0x77 */ RP_COM_BGM_RENEW_RECORD }; -} // namespace rp_Fsh_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Gol_sound.h b/include/Pack/RPAudio/archive/rp_Gol_sound.h index be1306c..f466543 100644 --- a/include/Pack/RPAudio/archive/rp_Gol_sound.h +++ b/include/Pack/RPAudio/archive/rp_Gol_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Gol_sound { - -enum ESoundID { +enum { /* 0x00 */ SE_TR_FlagHit, /* 0x01 */ SE_TR_DRIVER_HIT, /* 0x02 */ SE_TR_DRIVER_HIT_TVSP, @@ -228,6 +226,4 @@ enum ESoundID { /* 0xD5 */ RP_COM_GAME_SE_PAUSE_KEY_A_01 }; -} // namespace rp_Gol_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Hky_sound.h b/include/Pack/RPAudio/archive/rp_Hky_sound.h index 5f1c76b..595d803 100644 --- a/include/Pack/RPAudio/archive/rp_Hky_sound.h +++ b/include/Pack/RPAudio/archive/rp_Hky_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Hky_sound { - -enum ESoundID { +enum { /* 0x00 */ RP_HKY_SE_HIT_A_01, /* 0x01 */ RP_HKY_SE_HIT_B_01, /* 0x02 */ RP_HKY_SE_Bound_Wall_A_01, @@ -90,6 +88,4 @@ enum ESoundID { /* 0x4B */ RP_COM_BGM_RENEW_RECORD }; -} // namespace rp_Hky_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Pnp_sound.h b/include/Pack/RPAudio/archive/rp_Pnp_sound.h index 3dee768..fbd802f 100644 --- a/include/Pack/RPAudio/archive/rp_Pnp_sound.h +++ b/include/Pack/RPAudio/archive/rp_Pnp_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Pnp_sound { - -enum ESoundID { +enum { /* 0x00 */ RP_PNP_SE_HIT_ME_L_01, /* 0x01 */ RP_PNP_SE_HIT_ME_L_02, /* 0x02 */ RP_PNP_SE_HIT_ME_L_03, @@ -135,6 +133,4 @@ enum ESoundID { /* 0x78 */ RP_COM_BGM_RENEW_RECORD }; -} // namespace rp_Pnp_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Static_sound.h b/include/Pack/RPAudio/archive/rp_Static_sound.h index 91067e1..71a6326 100644 --- a/include/Pack/RPAudio/archive/rp_Static_sound.h +++ b/include/Pack/RPAudio/archive/rp_Static_sound.h @@ -9,12 +9,8 @@ //! @} -namespace rp_Static_sound { - -enum ESoundID { +enum { /* 0x0 */ rp_STATIC_CONNECT_01_CTSP }; -} // namespace rp_Static_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Tnk_sound.h b/include/Pack/RPAudio/archive/rp_Tnk_sound.h index fc75c1c..ec4f5e4 100644 --- a/include/Pack/RPAudio/archive/rp_Tnk_sound.h +++ b/include/Pack/RPAudio/archive/rp_Tnk_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Tnk_sound { - -enum ESoundID { +enum { /* 0x00 */ RP_TNK_SE_RESULT_OPEN, /* 0x01 */ RP_TNK_SE_SHOOT_1P, /* 0x02 */ RP_TNK_SE_SHOOT_2P, @@ -130,6 +128,4 @@ enum ESoundID { /* 0x73 */ RP_COMMON_SE_KEY_CURSOR_01 }; -} // namespace rp_Tnk_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Tns_sound.h b/include/Pack/RPAudio/archive/rp_Tns_sound.h index ca13135..f30cfda 100644 --- a/include/Pack/RPAudio/archive/rp_Tns_sound.h +++ b/include/Pack/RPAudio/archive/rp_Tns_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Tns_sound { - -enum ESoundID { +enum { /* 0x00 */ SE_TR_TARGET_CRUSH, /* 0x01 */ SE_TR_WALL_CRUSH, /* 0x02 */ SE_TR_SERVE, @@ -186,6 +184,4 @@ enum ESoundID { /* 0xAB */ RP_COM_GAME_SE_PAUSE_KEY_A_01 }; -} // namespace rp_Tns_sound - #endif diff --git a/include/Pack/RPAudio/archive/rp_Wly_sound.h b/include/Pack/RPAudio/archive/rp_Wly_sound.h index d43c59b..f3b2035 100644 --- a/include/Pack/RPAudio/archive/rp_Wly_sound.h +++ b/include/Pack/RPAudio/archive/rp_Wly_sound.h @@ -9,9 +9,7 @@ //! @} -namespace rp_Wly_sound { - -enum ESoundID { +enum { /* 0x00 */ RP_WLY_SE_TIME_COUNT_01, /* 0x01 */ RP_WLY_SE_TIME_COUNT_02, /* 0x02 */ RP_WLY_SE_TIME_UP_01, @@ -144,6 +142,4 @@ enum ESoundID { /* 0x81 */ RP_COM_BGM_RENEW_RECORD }; -} // namespace rp_Wly_sound - #endif diff --git a/include/Pack/RPGraphics.h b/include/Pack/RPGraphics.h index b00f1a6..69ee68f 100644 --- a/include/Pack/RPGraphics.h +++ b/include/Pack/RPGraphics.h @@ -2,8 +2,10 @@ #define RP_GRAPHICS_H #include +#include #include #include +#include #include #include #include @@ -11,5 +13,8 @@ #include #include #include +#include +#include +#include #endif diff --git a/include/Pack/RPGraphics/RPGrpCamera.h b/include/Pack/RPGraphics/RPGrpCamera.h new file mode 100644 index 0000000..050cbcf --- /dev/null +++ b/include/Pack/RPGraphics/RPGrpCamera.h @@ -0,0 +1,37 @@ +#ifndef RP_GRAPHICS_CAMERA_H +#define RP_GRAPHICS_CAMERA_H +#include +#include + +#include + +class RPGrpCamera { +protected: + nw4r::math::MTX34 MTX_0x0; // at 0x0 + nw4r::math::MTX34 MTX_0x30; // at 0x30 + nw4r::math::MTX34 MTX_0x60; // at 0x60 + nw4r::math::MTX34 MTX_0x90; // at 0x90 + + nw4r::math::VEC3 VEC3_0xC0; // at 0xC0 + nw4r::math::VEC3 VEC3_0xCC; // at 0xCC + char _D8[0xF4 - 0xD8]; + nw4r::math::VEC3 VEC3_0xF4; // at 0xF4 + nw4r::math::VEC3 VEC3_0x100; // at 0x100 + + u32 mProjType; // at 0x10C + u16 mFlags; // at 0x110 + + nw4r::math::MTX34 MTX_0x114; // at 0x114 + nw4r::math::MTX34 MTX_0x144; // at 0x144 + +public: + RPGrpCamera(); + + virtual ~RPGrpCamera(); // at 0x8 + virtual void CopyFromAnother(const RPGrpCamera& rOther); // at 0xC + + void LoadScnCameraMatrix(const nw4r::g3d::ResAnmScn scn, u8 refNumber, + f32 frame); +}; + +#endif diff --git a/include/Pack/RPGraphics/RPGrpModel.h b/include/Pack/RPGraphics/RPGrpModel.h index deb6a1b..5b7c96d 100644 --- a/include/Pack/RPGraphics/RPGrpModel.h +++ b/include/Pack/RPGraphics/RPGrpModel.h @@ -1,31 +1,93 @@ #ifndef RP_GRAPHICS_MODEL_H #define RP_GRAPHICS_MODEL_H -#include "RPTypes.h" - +#include #include +#include class RPGrpModelMaterial; +class RPGrpModelAnm; class RPGrpModel { +protected: + enum FlagBit { + FLAG_VISIBLE = (1 << 0), + }; + +protected: +#if defined(PACK_RESORT) + char _00[0x38]; + RPGrpModelMaterial** mppMaterials; // at 0x38 + char _3C[0x44 - 0x3C]; + EGG::ModelEx* mModelEx; // at 0x44 +#else + u8 mViewNo; // at 0x0 + u8 mDrawScene; // at 0x1 + u8 mDrawGroup; // at 0x2 + char _03; + u16 mFlags; // at 0x4 + char _06[0x2C - 0x6]; + RPGrpModelAnm* mModelAnm; // at 0x2C + RPGrpModelMaterial** mppMaterials; // at 0x30 + char _34[0x40 - 0x34]; + EGG::ModelEx* mModelEx; // at 0x40 +#endif + public: + static RPGrpModel* Construct(u16 rd, const char* pName, u32 drawView, + u32 flags, u32 bufferOption); + static RPGrpModel* Construct(u16 rd, u32 drawView, u32 flags, + u32 bufferOption); + + void UpdateFrame(); + EGG::ModelEx* GetModelEx() const { return mModelEx; } + nw4r::g3d::ScnMdlSimple* GetScnMdlSimple() const { + return mModelEx->getScnMdlSimple(); + } + +#if !defined(PACK_RESORT) + RPGrpModelAnm* GetModelAnm() const { + return mModelAnm; + } +#endif + RPGrpModelMaterial* GetMaterial(u32 id) const { return mppMaterials[id]; } -private: -#if defined(PACK_RESORT) - char _00[0x38]; - RPGrpModelMaterial** mppMaterials; // at 0x38 - char _3C[0x44 - 0x3C]; - EGG::ModelEx* mModelEx; // at 0x44 -#else - char _00[0x40]; - EGG::ModelEx* mModelEx; // at 0x40 +#if !defined(PACK_RESORT) + void SetDrawScene(u8 scene) { + mDrawScene = scene; + } + void SetDrawGroup(u8 group) { + mDrawGroup = group; + } + + void SetVisible(bool enable) { + SetShapeVisible(enable); + SetJointVisible(enable); + } #endif + +public: + virtual UNKTYPE VF_0x8(UNKTYPE) = 0; // at 0x8 + virtual UNKTYPE VF_0xC(UNKTYPE) = 0; // at 0xC + + virtual UNKTYPE VF_0x10(UNKTYPE) = 0; // at 0x10 + virtual UNKTYPE VF_0x14(UNKTYPE) = 0; // at 0x14 + virtual UNKTYPE VF_0x18(UNKTYPE) = 0; // at 0x18 + virtual UNKTYPE VF_0x1C(UNKTYPE) = 0; // at 0x1C + + virtual UNKTYPE VF_0x20(UNKTYPE) = 0; // at 0x20 + virtual UNKTYPE VF_0x24(UNKTYPE) = 0; // at 0x24 + virtual UNKTYPE VF_0x28(UNKTYPE) = 0; // at 0x28 + virtual void SetJointVisible(bool enable) = 0; // at 0x2C + + virtual UNKTYPE VF_0x30(UNKTYPE) = 0; // at 0x30 + virtual void SetShapeVisible(bool enable) = 0; // at 0x34 }; #endif diff --git a/include/Pack/RPGraphics/RPGrpModelAnm.h b/include/Pack/RPGraphics/RPGrpModelAnm.h new file mode 100644 index 0000000..a2e9068 --- /dev/null +++ b/include/Pack/RPGraphics/RPGrpModelAnm.h @@ -0,0 +1,78 @@ +#ifndef RP_GRAPHICS_MODEL_ANM_H +#define RP_GRAPHICS_MODEL_ANM_H +#include +#include + +class RPGrpModelAnm { +public: + enum Anm { + Anm_ResAnmChr, + Anm_ResAnmClr, + Anm_ResAnmTexPat, + Anm_ResAnmTexSrt, + Anm_4, + Anm_ResAnmShp, + Anm_6, + Anm_7, + }; + + enum AnmPlayPolicy { + AnmPlayPolicy_OneTime, + AnmPlayPolicy_Loop, + }; + +protected: + char _00[0x68]; + +public: + virtual void VF_0x8(UNKTYPE) = 0; + virtual void Construct(Anm anm, u16 idx, u16 rd) = 0; + + virtual void Regist(Anm anm, u16 idx, u16 rd, char const* pName, + u32 arg4 = 0) = 0; // at 0x10 + virtual void VF_0x14(UNKTYPE) = 0; + virtual void VF_0x18(UNKTYPE) = 0; + virtual void VF_0x1C(UNKTYPE) = 0; + + virtual void VF_0x20(UNKTYPE) = 0; + virtual void VF_0x24(UNKTYPE) = 0; + virtual void VF_0x28(UNKTYPE) = 0; + virtual void VF_0x2C(UNKTYPE) = 0; + + virtual void VF_0x30(UNKTYPE) = 0; + virtual void VF_0x34(UNKTYPE) = 0; + virtual void VF_0x38(UNKTYPE) = 0; + + virtual void Cancel(Anm anm, u16 idx) = 0; + virtual void Start(Anm anm, u16 idx, f32 frame = 1.0f) = 0; // at 0x40 + + virtual f32 VF_0x44(UNKTYPE) = 0; + virtual f32 VF_0x48(UNKTYPE) = 0; + + virtual u16 GetNumFrame(Anm anm, u16 idx) const = 0; // at 0x4C + virtual AnmPlayPolicy GetAnmPlayPolicy(Anm anm, + u16 idx) const = 0; // at 0x50 + + virtual void SetFrame(Anm anm, u16 idx, f32 frame) = 0; // at 0x54 + virtual f32 GetFrame(Anm anm, u16 idx) const = 0; // at 0x58 + + virtual void SetUpdateRate(Anm anm, u16 idx, f32 rate) = 0; // at 0x5C + virtual f32 GetUpdateRate(Anm anm, u16 idx) const = 0; // at 0x60 + + virtual void SetEnableQuaternionBlend(bool enable) = 0; // at 0x64 + + virtual void VF_0x68(UNKTYPE) = 0; // at 0x68 + virtual void VF_0x6C(UNKTYPE) = 0; // at 0x6C + virtual void VF_0x70(UNKTYPE) = 0; // at 0x70 + virtual void VF_0x74(UNKTYPE) = 0; // at 0x74 + + virtual nw4r::g3d::AnmObj* GetAnmObj(Anm anm, u16 idx) const = 0; // at 0x78 + virtual ~RPGrpModelAnm(); // at 0x7C + + virtual void SetAnmObj(Anm anm, nw4r::g3d::AnmObj* pAnmObj) = 0; // at 0x80 + virtual void InternalCalc() = 0; // at 0x84 + + void CreateBuffer(Anm anm, u16 num); +}; + +#endif diff --git a/include/Pack/RPGraphics/RPGrpModelManager.h b/include/Pack/RPGraphics/RPGrpModelManager.h index 135dc1f..cbe3601 100644 --- a/include/Pack/RPGraphics/RPGrpModelManager.h +++ b/include/Pack/RPGraphics/RPGrpModelManager.h @@ -7,10 +7,17 @@ class RPGrpLightManager; class RPGrpFogManager; class RPGrpModelManager { - RP_SINGLETON_DECL(RPGrpModelManager); - public: - void CreateModelScene(u32, u8, u32, RPGrpLightManager*, RPGrpFogManager*); + void CreateModelScene(u32 index, u8 drawPathFlag, u32 viewNum, + RPGrpLightManager* pLightMgr, + RPGrpFogManager* pFogMgr); + + static RPGrpModelManager* GetCurrent() { + return spCurrent; + } + +private: + static RPGrpModelManager* spCurrent; }; #endif diff --git a/include/Pack/RPGraphics/RPGrpModelMaterial.h b/include/Pack/RPGraphics/RPGrpModelMaterial.h index 5c317d9..fb06c11 100644 --- a/include/Pack/RPGraphics/RPGrpModelMaterial.h +++ b/include/Pack/RPGraphics/RPGrpModelMaterial.h @@ -1,11 +1,38 @@ #ifndef RP_GRAPHICS_MODEL_MATERIAL_H #define RP_GRAPHICS_MODEL_MATERIAL_H #include "RPTypes.h" - #include class RPGrpModelMaterial { +private: +#if defined(PACK_SPORTS) || defined(PACK_PLAY) + u32 mSyncFlags; // at 0x0 + char _04[0x20 - 0x4]; + GXColor mTevKColors[GX_MAX_KCOLOR]; // at 0x20 + GXColorS10 mTevColors[GX_MAX_TEVREG - GX_TEVREG0]; // at 0x30 +#elif defined(PACK_RESORT) + u32 mSyncFlags; // at 0x0 + char _04[0xC - 0x4]; + GXColor mTevKColors[GX_MAX_KCOLOR]; // at 0xC + GXColorS10 mTevColors[GX_MAX_TEVREG - GX_TEVREG0]; // at 0x1C + char _34[0x80 - 0x34]; + nw4r::g3d::ScnMdl::CopiedMatAccess mCopiedMatAccess; // at 0x80 +// . . . +#endif + +public: + enum ESyncFlag { + ESyncFlag_Tev = 1 << 4, + }; + public: + RPGrpModelMaterial(); + virtual ~RPGrpModelMaterial(); + + void SetSyncFlag(u32 flags) { + mSyncFlags |= flags; + } + void SetTevKColor(GXTevKColorID id, GXColor color) { mTevKColors[id] = color; } @@ -13,17 +40,11 @@ class RPGrpModelMaterial { mTevColors[id - GX_TEVREG0] = color; } +#if defined(PACK_RESORT) nw4r::g3d::ScnMdl::CopiedMatAccess& GetCopiedMatAccess() { return mCopiedMatAccess; } - -private: - char _00[0xC]; - GXColor mTevKColors[GX_MAX_KCOLOR]; // at 0xC - GXColorS10 mTevColors[GX_MAX_TEVREG - GX_TEVREG0]; // at 0x1C - char _34[0x80 - 0x34]; - nw4r::g3d::ScnMdl::CopiedMatAccess mCopiedMatAccess; // at 0x80 - // . . . +#endif }; #endif diff --git a/include/Pack/RPGraphics/RPGrpModelResManager.h b/include/Pack/RPGraphics/RPGrpModelResManager.h index 240624d..45a832d 100644 --- a/include/Pack/RPGraphics/RPGrpModelResManager.h +++ b/include/Pack/RPGraphics/RPGrpModelResManager.h @@ -3,10 +3,101 @@ #include class RPGrpModelResManager { - RP_SINGLETON_DECL(RPGrpModelResManager); +public: + enum Type { + Type_0Bh = 0xB, + + Type_ResFile, + Type_ResMdl, + Type_ResPltt, + Type_ResTex, + Type_ResAnmChr, + Type_ResAnmVis, + Type_ResAnmClr, + Type_ResAnmTexPat, + Type_ResAnmTexSrt, + Type_ResAnmShp, + Type_ResAnmScn, + + Type_Max + }; + +protected: + struct ResHolder { + void* pResFileData; // at 0x0 + }; + + struct Res { + Type type; // at 0x0 + void* pData; // at 0x4 + ResHolder* pResHolder; // at 0x8 + char _0C[0x10 - 0xC]; + }; + +protected: + Res* mResourceList; // at 0x0 + u16 mResourceNum; // at 0x4 + + static RPGrpModelResManager* spCurrent; public: - void CreateResourceList(u16); + static RPGrpModelResManager* GetCurrent() { + return spCurrent; + } + + void CreateResourceList(u16 capacity); + + u16 CreateData(Type type, void* pData, u32 arg2 = 0); + + void* GetPtr(Type type, u16 file, int index) const; + void* GetPtr(Type type, u16 file, const char* pName) const; + + template T GetData(u16 file, int index) const; + template T GetData(u16 file, const char* pName) const; + +public: + RPGrpModelResManager(); + virtual ~RPGrpModelResManager(); }; +template <> +inline nw4r::g3d::ResFile +RPGrpModelResManager::GetData(u16 file, + int /* index */) const { + return nw4r::g3d::ResFile(mResourceList[file].pResHolder->pResFileData); +} + +#define GET_DATA_FUNC_IMPL(T) \ + template <> \ + inline nw4r::g3d::T RPGrpModelResManager::GetData( \ + u16 file, int index) const { \ + \ + const nw4r::g3d::ResFile resFile( \ + mResourceList[file].pResHolder->pResFileData); \ + \ + return resFile.Get##T(index); \ + } \ + template <> \ + inline nw4r::g3d::T RPGrpModelResManager::GetData( \ + u16 file, const char* pName) const { \ + \ + const nw4r::g3d::ResFile resFile( \ + mResourceList[file].pResHolder->pResFileData); \ + \ + return resFile.Get##T(pName); \ + } + +GET_DATA_FUNC_IMPL(ResMdl); +GET_DATA_FUNC_IMPL(ResPltt); +GET_DATA_FUNC_IMPL(ResTex); +GET_DATA_FUNC_IMPL(ResAnmChr); +GET_DATA_FUNC_IMPL(ResAnmVis); +GET_DATA_FUNC_IMPL(ResAnmClr); +GET_DATA_FUNC_IMPL(ResAnmTexPat); +GET_DATA_FUNC_IMPL(ResAnmTexSrt); +GET_DATA_FUNC_IMPL(ResAnmShp); +GET_DATA_FUNC_IMPL(ResAnmScn); + +#undef GET_DATA_FUNC_IMPL + #endif diff --git a/include/Pack/RPGraphics/RPGrpRenderer.h b/include/Pack/RPGraphics/RPGrpRenderer.h index b5f8a70..c2701d2 100644 --- a/include/Pack/RPGraphics/RPGrpRenderer.h +++ b/include/Pack/RPGraphics/RPGrpRenderer.h @@ -4,6 +4,8 @@ // Forward declarations class RPGrpScreen; +class RPGrpCamera; +class RPGrpView; class RPGrpRenderer { public: @@ -30,7 +32,9 @@ class RPGrpRenderer { void AppendDrawObject(IRPGrpDrawObject*); - void CreateView2D(u8, RPGrpScreen*); + void CreateView2D(u8 id, RPGrpScreen* pScreen); + void CreateView3D(u8 id, RPGrpCamera* pCamera, RPGrpScreen* pScreen); + void CorrectView(); static void SetEfbClearColor(u8 r, u8 g, u8 b); @@ -38,8 +42,8 @@ class RPGrpRenderer { static EDrawPass GetDrawPass() { return sDrawPass; } - static void SetDrawPass(EDrawPass pass) { - sDrawPass = pass; + static u8 GetViewID() { + return sCurrentViewID; } static RPGrpRenderer* GetCurrent() { @@ -53,9 +57,18 @@ class RPGrpRenderer { return sDrawPass == EDrawPass_Draw2D; } + RPGrpView* GetView(u32 no) const { + return mDrawViews[no]; + } + +private: + static const int MAX_VIEW = 32; + private: char UNK_0x0[0xC]; IRPGrpDrawObject* mDrawObjects; // at 0xC + char _10[0x4]; + RPGrpView* mDrawViews[MAX_VIEW]; // at 0x14 static EDrawPass sDrawPass; static u8 sCurrentViewID; diff --git a/include/Pack/RPGraphics/RPGrpScreen.h b/include/Pack/RPGraphics/RPGrpScreen.h index 71cf7dd..8048e3d 100644 --- a/include/Pack/RPGraphics/RPGrpScreen.h +++ b/include/Pack/RPGraphics/RPGrpScreen.h @@ -6,9 +6,14 @@ class RPGrpScreen : public EGG::Screen { public: RPGrpScreen() { - SetFarZ(10000.0f); + SetFarZ(100000.0f); } + RPGrpScreen(f32 x, f32 y, f32 width, f32 height, + const Screen* pParent = NULL, + CanvasMode canvasMode = CANVASMODE_LU) + : EGG::Screen(x, y, width, height, pParent, canvasMode) {} + virtual ~RPGrpScreen(); private: diff --git a/include/Pack/RPGraphics/RPGrpView.h b/include/Pack/RPGraphics/RPGrpView.h new file mode 100644 index 0000000..801d271 --- /dev/null +++ b/include/Pack/RPGraphics/RPGrpView.h @@ -0,0 +1,27 @@ +#ifndef RP_GRAPHICS_VIEW_H +#define RP_GRAPHICS_VIEW_H +#include + +// Forward declarations +class RPGrpCamera; + +class RPGrpView { +protected: + u8 mViewNo; // at 0x0 + u8 mDrawScene; // at 0x1 + char _02[0x1C - 0x2]; + +public: + virtual ~RPGrpView(); // at 0x8 + virtual UNKTYPE VF_0xC(UNKTYPE) = 0; // at 0xC + virtual void AttachCamera(RPGrpCamera* pCamera) = 0; // at 0x10 + + void SetDrawScene(u8 scene) { + mDrawScene = scene; + } + +private: + ; +}; + +#endif diff --git a/include/Pack/RPGraphics/RPGrpViewRender2D.h b/include/Pack/RPGraphics/RPGrpViewRender2D.h new file mode 100644 index 0000000..e07c1a2 --- /dev/null +++ b/include/Pack/RPGraphics/RPGrpViewRender2D.h @@ -0,0 +1,14 @@ +#ifndef RP_GRAPHICS_VIEW_RENDER_2D_H +#define RP_GRAPHICS_VIEW_RENDER_2D_H +#include +#include + +class RPGrpViewRender2D : public RPGrpView { +public: + ; + +private: + ; +}; + +#endif diff --git a/include/Pack/RPGraphics/RPGrpViewRender3D.h b/include/Pack/RPGraphics/RPGrpViewRender3D.h new file mode 100644 index 0000000..9fe7a0d --- /dev/null +++ b/include/Pack/RPGraphics/RPGrpViewRender3D.h @@ -0,0 +1,14 @@ +#ifndef RP_GRAPHICS_VIEW_RENDER_3D_H +#define RP_GRAPHICS_VIEW_RENDER_3D_H +#include +#include + +class RPGrpViewRender3D : public RPGrpView { +public: + ; + +private: + ; +}; + +#endif diff --git a/include/Pack/RPKernel.h b/include/Pack/RPKernel.h index 3206841..797fa10 100644 --- a/include/Pack/RPKernel.h +++ b/include/Pack/RPKernel.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/include/Pack/RPKernel/IRPSysAppMiiManager.h b/include/Pack/RPKernel/IRPSysAppMiiManager.h new file mode 100644 index 0000000..c0c2f4b --- /dev/null +++ b/include/Pack/RPKernel/IRPSysAppMiiManager.h @@ -0,0 +1,19 @@ +#ifndef RP_KERNEL_I_APP_MII_MANAGER_H +#define RP_KERNEL_I_APP_MII_MANAGER_H +#include + +//! @addtogroup rp_kernel +//! @{ + +/** + * @brief Pack Project application Mii manager + */ +class IRPSysAppMiiManager { +public: + // TODO + ; +}; + +//! @} + +#endif diff --git a/include/Pack/RPKernel/IRPSysKokeshiBodyManager.h b/include/Pack/RPKernel/IRPSysKokeshiBodyManager.h new file mode 100644 index 0000000..24368e7 --- /dev/null +++ b/include/Pack/RPKernel/IRPSysKokeshiBodyManager.h @@ -0,0 +1,41 @@ +#ifndef RP_KERNEL_I_KOKESHI_BODY_MANAGER_H +#define RP_KERNEL_I_KOKESHI_BODY_MANAGER_H +#include + +#include + +#include + +//! @addtogroup rp_kernel +//! @{ + +// Forward declarations +class RPGrpModel; + +/** + * @brief Kokeshi body manager + */ +class IRPSysKokeshiBodyManager { +public: + virtual u16 GetFriendClothesStartIndex() = 0; // at 0x8 + virtual u16 GetFriendClothesIndexRange() = 0; // at 0xC + + virtual const char* GetBodyFileName(u16, RFLSex) = 0; // at 0x10 + virtual u16 GetDummyHeadModelndex() = 0; // at 0x14 + virtual const char* GetClothesFileName() = 0; // at 0x18 + virtual void GetClothesName(u16, RFLSex, const char**, + const char**) = 0; // at 0x1C + + virtual void GetHeadJointMtx(u16, RPGrpModel*, + nw4r::math::MTX34*) = 0; // at 0x20 + virtual void GetLeftHandJointMtx(u16, RPGrpModel*, + nw4r::math::MTX34*) = 0; // at 0x24 + virtual void GetRightHandJointMtx(u16, RPGrpModel*, + nw4r::math::MTX34*) = 0; // at 0x28 + + virtual ~IRPSysKokeshiBodyManager() = 0; // at 0x2C +}; + +//! @} + +#endif diff --git a/include/Pack/RPKernel/RPSysAvatar.h b/include/Pack/RPKernel/RPSysAvatar.h index 9ecb737..040af7f 100644 --- a/include/Pack/RPKernel/RPSysAvatar.h +++ b/include/Pack/RPKernel/RPSysAvatar.h @@ -8,7 +8,7 @@ class RPSysAvatar { public: RPSysAvatar(const RPSysKokeshiGenInfo*); virtual ~RPSysAvatar(); - virtual void LoadResource(const RPSysKokeshiOverloadInfo*); + virtual void LoadResource(const RPSysKokeshiOverloadInfo* = NULL); virtual void ApplyLightTexture(u8) = 0; private: diff --git a/include/Pack/RPKernel/RPSysEffectBase.h b/include/Pack/RPKernel/RPSysEffectBase.h new file mode 100644 index 0000000..4be57fa --- /dev/null +++ b/include/Pack/RPKernel/RPSysEffectBase.h @@ -0,0 +1,68 @@ +#ifndef RP_KERNEL_EFFECT_BASE_H +#define RP_KERNEL_EFFECT_BASE_H +#include + +#include + +class RPSysEffect { +public: + RPSysEffect(const char* pName, u32 drawScene, u32 owner); + virtual ~RPSysEffect(); // at 0x8 + + virtual bool create(); // at 0xC + virtual void VF_10(); // at 0x10 + virtual void VF_14(); // at 0x14 + virtual void forceKill(); // at 0x18 + virtual void VF_1C(); // at 0x1C + + virtual void setDisableDraw(bool disable); // at 0x20 + virtual void VF_24(); // at 0x24 + virtual void setLife(f32 life); // at 0x28 + virtual void setEmitRatio(f32 ratio); // at 0x2C + + virtual void VF_30(); // at 0x30 + virtual void VF_34(); // at 0x34 + virtual void VF_38(); // at 0x38 + virtual void VF_3C(); // at 0x3C + + virtual void VF_40(); // at 0x40 + virtual void VF_44(); // at 0x44 + virtual void VF_48(); // at 0x48 + virtual void VF_4C(); // at 0x4C + + virtual void setColor(u8 r, u8 g, u8 b, u8 a); // at 0x50 + virtual void VF_54(); // at 0x54 + virtual void VF_58(); // at 0x58 + virtual void VF_5C(); // at 0x5C + + virtual void VF_60(); // at 0x60 + virtual void VF_64(); // at 0x64 + virtual void VF_68(); // at 0x68 + virtual void VF_6C(); // at 0x6C + + virtual void VF_70(); // at 0x70 + virtual void VF_74(); // at 0x74 + virtual void setScale(const nw4r::math::VEC3& rScale); // at 0x78 + virtual void setPos(const nw4r::math::VEC3& rPos); // at 0x7C + + virtual void setMtx(const nw4r::math::MTX34& rMtx); // at 0x80 + virtual void VF_84(); // at 0x84 + virtual void update(); // at 0x88 + virtual void VF_8C(); // at 0x8C + + virtual void VF_90(); // at 0x90 + virtual void VF_94(); // at 0x94 + + nw4r::ef::EffectHandle& GetHandle() { + return mEffectHandle; + } + const nw4r::ef::EffectHandle& GetHandle() const { + return mEffectHandle; + } + +private: + char _04[0x78 - 0x4]; + nw4r::ef::EffectHandle mEffectHandle; // at 0x78 +}; + +#endif diff --git a/include/Pack/RPKernel/RPSysEffectCreator.h b/include/Pack/RPKernel/RPSysEffectCreator.h new file mode 100644 index 0000000..de778e7 --- /dev/null +++ b/include/Pack/RPKernel/RPSysEffectCreator.h @@ -0,0 +1,9 @@ +#ifndef RP_KERNEL_EFFECT_CREATOR_H +#define RP_KERNEL_EFFECT_CREATOR_H +#include + +class RPSysEffectCreator { +public: +}; + +#endif diff --git a/include/Pack/RPKernel/RPSysEffectMgr.h b/include/Pack/RPKernel/RPSysEffectMgr.h index ce8bb99..2cb8b33 100644 --- a/include/Pack/RPKernel/RPSysEffectMgr.h +++ b/include/Pack/RPKernel/RPSysEffectMgr.h @@ -1,9 +1,29 @@ #ifndef RP_KERNEL_EFFECT_MGR_H #define RP_KERNEL_EFFECT_MGR_H -#include "types.h" +#include class RPSysEffectMgr { - RP_SINGLETON_DECL(RPSysEffectMgr); + RP_SINGLETON_DECL_EX(RPSysEffectMgr); + +public: + enum EDrawScene { + EDrawScene_Layer0, + EDrawScene_Layer1, + EDrawScene_Layer2, + EDrawScene_Layer3, + + EDrawScene_Cursor = 15, + + EDrawScene_Max = 64, + }; + + enum EEffectOwner { + EEffectOwner_Scene, + EEffectOwner_CursorMgr, + EEffectOwner_Work, + + EEffectOwner_Max + }; public: void LoadResource(); diff --git a/include/Pack/RPKernel/RPSysFile.h b/include/Pack/RPKernel/RPSysFile.h index 5b8ba4c..6af8d9a 100644 --- a/include/Pack/RPKernel/RPSysFile.h +++ b/include/Pack/RPKernel/RPSysFile.h @@ -26,6 +26,27 @@ class RPSysFile : public EGG::Disposer { */ virtual ~RPSysFile(); + /** + * @brief Gets the path to this file + */ + const char* GetPath() const { + return mPath; + } + + /** + * @brief Gets the size of this file + */ + u32 GetSize() const { + return mSize; + } + + /** + * @brief Gets the data of this file + */ + const void* GetData() const { + return mpData; + } + public: //! Link node used for cache lists nw4r::ut::Link node; // at 0x10 diff --git a/include/Pack/RPKernel/RPSysFrameCtrl.h b/include/Pack/RPKernel/RPSysFrameCtrl.h index ef4e290..366a0a2 100644 --- a/include/Pack/RPKernel/RPSysFrameCtrl.h +++ b/include/Pack/RPKernel/RPSysFrameCtrl.h @@ -4,8 +4,36 @@ class RPSysFrameCtrl { public: + enum EPlayMode { + PLAYMODE_ONETIME, + PLAYMODE_INOUT, + PLAYMODE_LOOP, + }; + + enum EPlayFlag { + FLAG_PLAY_FINISHED = 1 << 0, + }; + + enum ETypeFlag { + FLAG_TYPE_F32 = 1 << 0, + }; + + //! TODO + void play() { + mFrameNoF32 = mFrameNo; + mPlayFlags = 0; + mTypeFlags = FLAG_TYPE_F32; + } + private: - char UNK_0x0[0x10]; + u8 mPlayMode; // at 0x0 + u8 mPlayFlags; // at 0x1 + u16 mTypeFlags; // at 0x2 + s16 mFrameNo; // at 0x4 + s16 mFrameNum; // at 0x6 + char _8[0xC - 0x8]; + f32 mRate; // at 0xC + f32 mFrameNoF32; // at 0x10 }; #endif diff --git a/include/Pack/RPKernel/RPSysKokeshiIcon.h b/include/Pack/RPKernel/RPSysKokeshiIcon.h index 9636558..f5df673 100644 --- a/include/Pack/RPKernel/RPSysKokeshiIcon.h +++ b/include/Pack/RPKernel/RPSysKokeshiIcon.h @@ -1,12 +1,14 @@ #ifndef RP_KERNEL_KOKESHI_ICON_H #define RP_KERNEL_KOKESHI_ICON_H -#include "RPTypes.h" +#include +#include -class RPSysKokeshiIcon { +class RPSysKokeshiIcon : public RPSysAvatar { public: RPSysKokeshiIcon(const RPSysKokeshiGenInfo*); - virtual ~RPSysKokeshiIcon(); - virtual void LoadResource(const RPSysKokeshiOverloadInfo*); + virtual ~RPSysKokeshiIcon(); // at 0x8 + + virtual void LoadResource(const RPSysKokeshiOverloadInfo* = NULL); virtual void ApplyLightTexture(u8); }; diff --git a/include/Pack/RPKernel/RPSysKokeshiManager.h b/include/Pack/RPKernel/RPSysKokeshiManager.h index ee5fbd4..e183654 100644 --- a/include/Pack/RPKernel/RPSysKokeshiManager.h +++ b/include/Pack/RPKernel/RPSysKokeshiManager.h @@ -1,17 +1,26 @@ #ifndef RP_KERNEL_KOKESHI_MANAGER_H #define RP_KERNEL_KOKESHI_MANAGER_H -#include "RPTypes.h" +#include + +// Forward declarations +class IRPSysKokeshiBodyManager; class RPSysKokeshiManager { RP_SINGLETON_DECL(RPSysKokeshiManager); public: - enum GenType { - - }; + enum GenType {}; public: void LoadStaticResource(); + + void SetBodyManager(IRPSysKokeshiBodyManager* pManager) { + mBodyManager = pManager; + } + +private: + char _04[0x54]; + IRPSysKokeshiBodyManager* mBodyManager; // at 0x58 }; #endif diff --git a/include/Pack/RPKernel/RPSysLayout.h b/include/Pack/RPKernel/RPSysLayout.h index dbd3aa1..ab3c13d 100644 --- a/include/Pack/RPKernel/RPSysLayout.h +++ b/include/Pack/RPKernel/RPSysLayout.h @@ -6,6 +6,8 @@ #include #include +#include + // Forward declarations class RPSysLytBounding; class RPSysLytTextBox; @@ -340,6 +342,10 @@ class RPSysLayout { return findPane("RootPane"); } + nw4r::lyt::DrawInfo* getDrawInfo() { + return mDrawInfo; + } + private: u16 mFlags; // at 0x0 f32 FLOAT_0x4; diff --git a/include/Pack/RPKernel/RPSysLytAnmObj.h b/include/Pack/RPKernel/RPSysLytAnmObj.h index 096f13d..86d4004 100644 --- a/include/Pack/RPKernel/RPSysLytAnmObj.h +++ b/include/Pack/RPKernel/RPSysLytAnmObj.h @@ -5,8 +5,19 @@ class RPSysLytAnmObj { public: + RPSysFrameCtrl* getFrameCtrl() { + return &mFrameCtrl; + } + + void play() { + mFrameCtrl.play(); + } + private: + u32 _00; RPSysFrameCtrl mFrameCtrl; // at 0x4 + u16 _18; + u32 _1C; }; #endif diff --git a/include/Pack/RPKernel/RPSysLytResAccessor.h b/include/Pack/RPKernel/RPSysLytResAccessor.h index 15811fa..09a73f6 100644 --- a/include/Pack/RPKernel/RPSysLytResAccessor.h +++ b/include/Pack/RPKernel/RPSysLytResAccessor.h @@ -48,7 +48,7 @@ class RPSysLytResAccessor { * @return Success * @address 80198b6c */ - bool mountArchive(void* archive, const char* dir); + bool mountArchive(void* archive, const char* dir = nullptr); /** * @brief Get resource from the open archive diff --git a/include/Pack/RPKernel/RPSysMessage.h b/include/Pack/RPKernel/RPSysMessage.h index 35ef941..f09a9a8 100644 --- a/include/Pack/RPKernel/RPSysMessage.h +++ b/include/Pack/RPKernel/RPSysMessage.h @@ -16,7 +16,8 @@ class RPSysMessage : public EGG::MsgRes { * @details MsgInfoBlock stores the sizes of its entries, * allowing games to add extra features to their text. */ - struct RPMsgInfoBlockEntry : public EGG::MsgRes::MsgInfoBlockEntry { + struct RPMsgInfoBlockEntry + : public EGG::MsgRes::MessageInfoDataBlock::Entry { // @brief Text scale u16 mScale; // at 0x8 // @brief Text kerning diff --git a/include/Pack/RPParty.h b/include/Pack/RPParty.h index 1a6f87d..de60d11 100644 --- a/include/Pack/RPParty.h +++ b/include/Pack/RPParty.h @@ -1,17 +1,14 @@ #ifndef RP_PARTY_H #define RP_PARTY_H -#include -#include -#include -#include -#include -#include -#include +#include +#include #include #include #include #include #include +#include +#include #endif diff --git a/include/Pack/RPParty/RPBilScene.h b/include/Pack/RPParty/RPBilScene.h new file mode 100644 index 0000000..a3102bf --- /dev/null +++ b/include/Pack/RPParty/RPBilScene.h @@ -0,0 +1,19 @@ +#ifndef RP_PARTY_BIL_SCENE_H +#define RP_PARTY_BIL_SCENE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilBall.h b/include/Pack/RPParty/RPBilScene/RPBilBall.h index b57604d..4f82f92 100644 --- a/include/Pack/RPParty/RPBilScene/RPBilBall.h +++ b/include/Pack/RPParty/RPBilScene/RPBilBall.h @@ -1,30 +1,107 @@ #ifndef RP_PARTY_BIL_BALL_H #define RP_PARTY_BIL_BALL_H -#include "RPTypes.h" -#include +#include +#include +#include +#include -class RPBilBall { +// Forward declarations +class RPSysEffect; + +class RPBilBall : public RPPartyUtlModel { public: - enum EState { EState_Null, EState_Wait, EState_Pocket, EState_OffTable }; + enum EState { EState_None, EState_Wait, EState_Pocket, EState_OffTable }; + + RPBilBall(u32 no); + virtual ~RPBilBall(); + + virtual const EGG::Vector3f& getPosition() const; // at 0x34 + virtual void setPosition(const EGG::Vector3f& pos); // at 0x38 + + virtual const EGG::Vector3f& getVelocity() const; // at 0x3C + virtual void setVelocity(const EGG::Vector3f& vel); // at 0x40 + + virtual const EGG::Vector3f& getMtxZBase() const; // at 0x4C + virtual void setMtxZBase(const EGG::Vector3f& z); // at 0x50 + + virtual const EGG::Vector3f& getMtxYBase() const; // at 0x54 + virtual void setMtxYBase(const EGG::Vector3f& y); // at 0x58 + + virtual const EGG::Vector3f& getMtxXBase() const; // at 0x5C + virtual void setMtxXBase(const EGG::Vector3f& x); // at 0x60 - bool IsCueBall() const { - return mId == 0; + virtual f32 getScale() const; // at 0x64 + virtual void setScale(f32 scale); // at 0x68 + + virtual void Configure(); // at 0x78 + virtual void Reset(); // at 0x7C + virtual void Calculate(); // at 0x80 + virtual void Exit(); // at 0x84 + virtual void UserDraw(); // at 0x88 + + void PreCalculate(); + void PostCalculate(); + + void ResetRack(); + + bool IsStopped() const { + return mpRigidBody->isStopped(); + } + + bool IsChangingState() const { + return mStateMachine->IsChangingState(); } bool IsState(EState state) const { return mStateMachine->IsState(state); } + bool IsStateNow(EState state) const { + return mStateMachine->IsStateNow(state); + } void ChangeState(EState state) { mStateMachine->ChangeState(state); } -private: - // RPPartyGameObjBase -> IRPSysHostIOSocket, etc. - char _00[0x60]; + u32 GetIndex() const { + return mIndex; + } + + s32 GetTurnNoPocket() const { + return mTurnNoPocket; + } + s32 GetTurnNoOffTable() const { + return mTurnNoOffTable; + } + + bool IsEnabled() const { + return mIsEnabled; + } - u32 mId; // at 0x60 + void SetFloorBounceNum(s32 num) { + mFloorBounceNum = num; + } + + RPPartyUtlModelRigid* GetRigidBody() const { + return mpRigidBody; + } + + s32 GetClosePocketIndex() const; + + bool CheckRayIntersect(const EGG::Ray3f& rRay, f32 radius, + EGG::Vector3f& rHitPos, f32& rHitDist); + +private: + u32 mIndex; // at 0x60 RPUtlBaseFsm* mStateMachine; // at 0x64 + s32 mTurnNoPocket; // at 0x68 + s32 mTurnNoOffTable; // at 0x6C + bool mIsEnabled; // at 0x70 + bool _71; // at 0x70 + s32 mFloorBounceNum; // at 0x74 + UNKTYPE* mpSndObject; // at 0x78 + RPPartyUtlModelRigid* mpRigidBody; // at 0x7C + RPSysEffect* mpTailEffect; // at 0x80 }; #endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilBallDisplay.h b/include/Pack/RPParty/RPBilScene/RPBilBallDisplay.h new file mode 100644 index 0000000..4c7e7e6 --- /dev/null +++ b/include/Pack/RPParty/RPBilScene/RPBilBallDisplay.h @@ -0,0 +1,36 @@ +#ifndef RP_PARTY_BIL_BALL_DISPLAY_H +#define RP_PARTY_BIL_BALL_DISPLAY_H +#include +#include +#include + +class RPBilBallDisplay : public RPPartyUtlModel { +public: + enum EState { EState_Hide, EState_AnimIn, EState_Wait, EState_AnimOut }; + + RPBilBallDisplay(u32 index); + virtual ~RPBilBallDisplay(); + + virtual void Configure(); // at 0x78 + virtual void Reset(); // at 0x7C + virtual void Calculate(); // at 0x80 + virtual void Exit(); // at 0x84 + + bool IsState(EState state) const { + return mStateMachine->IsState(state); + } + + void ChangeState(EState state) { + mStateMachine->ChangeState(state); + } + + void StartAnimOut(); + void CalcDisplay(u32 player, f32 offsetY, u32 pocketNum, u32 displayNo); + +private: + u32 mIndex; // at 0x60 + char _64[0x84 - 0x64]; + RPUtlBaseFsm* mStateMachine; // at 0x84 +}; + +#endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilBallGuide.h b/include/Pack/RPParty/RPBilScene/RPBilBallGuide.h new file mode 100644 index 0000000..7486201 --- /dev/null +++ b/include/Pack/RPParty/RPBilScene/RPBilBallGuide.h @@ -0,0 +1,20 @@ +#ifndef RP_PARTY_BIL_BALL_GUIDE_H +#define RP_PARTY_BIL_BALL_GUIDE_H +#include +#include +#include + +class RPBilBallGuide : public RPPartyUtlModel { +public: + virtual void Configure(); // at 0x78 + virtual void Reset(); // at 0x7C + virtual void Calculate(); // at 0x80 + virtual void Exit(); // at 0x84 + virtual void UserDraw(); // at 0x88 + +private: + u32 mId; // at 0x60 + char _64[0x4]; +}; + +#endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilBallManager.h b/include/Pack/RPParty/RPBilScene/RPBilBallManager.h index b2620be..6d3474d 100644 --- a/include/Pack/RPParty/RPBilScene/RPBilBallManager.h +++ b/include/Pack/RPParty/RPBilScene/RPBilBallManager.h @@ -1,22 +1,58 @@ #ifndef RP_PARTY_BIL_BALL_MANAGER_H #define RP_PARTY_BIL_BALL_MANAGER_H -#include "RPTypes.h" -#include +#include +#include -class RPBilBallManager { +// Forward declarations +class RPBilBall; +class RPBilBallGuide; +class RPBilBallPlaceFoul; +class RPBilBallDisplay; +class RPSysKokeshiIcon; +template class TRPSndObject; + +class RPBilBallManager : public RPPartyUtlModel { RP_SINGLETON_DECL(RPBilBallManager); public: - RPBilBall* GetBall(int i) { - return mBalls[i]; - } + virtual void Configure(); // at 0x78 + virtual void Reset(); // at 0x7C + virtual void Calculate(); // at 0x80 + virtual void Exit(); // at 0x84 -public: + virtual void UserDraw(); // at 0x88 + +private: + enum EFoulType { + EFoulType_None = -1, + EFoulType_OffTable, + EFoulType_CuePocket, + EFoulType_MissTarget, + EFoulType_WrongBall, + }; + + static const int PLAYER_MAX = 2; static const int BALL_MAX = 10; + static const int GUIDE_BALL_MAX = 10; + +private: + void CalcBallCollision(); + void CalcTableCollision(); private: - char _04[0x7C - 0x4]; - RPBilBall* mBalls[BALL_MAX]; // at 0x7C + u32 mLayoutNo; // at 0x60 + s32 mBallNum; // at 0x64 + s32 mTurnNo; // at 0x68 + u32 mFirstHitBall; // at 0x6C + EFoulType mFoulType; // at 0x70 + bool mStartedFoulSE; // at 0x74 + s32 mTurnEndTimer; // at 0x78 + RPBilBall* mpBalls[BALL_MAX]; // at 0x7C + RPBilBallGuide* mpGuideBalls[GUIDE_BALL_MAX]; // at 0xA4 + RPBilBallPlaceFoul* mpPlaceFoulBall; // at 0xCC + RPBilBallDisplay* mpDisplayBalls[BALL_MAX]; // at 0xD0 + RPSysKokeshiIcon* mpKokeshiIcons[PLAYER_MAX]; // at 0xF8 + TRPSndObject<4>* mpSndObject; // at 0x100 }; #endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilBallPlaceFoul.h b/include/Pack/RPParty/RPBilScene/RPBilBallPlaceFoul.h new file mode 100644 index 0000000..aad5050 --- /dev/null +++ b/include/Pack/RPParty/RPBilScene/RPBilBallPlaceFoul.h @@ -0,0 +1,19 @@ +#ifndef RP_PARTY_BIL_BALL_PLACE_FOUL_H +#define RP_PARTY_BIL_BALL_PLACE_FOUL_H +#include +#include +#include + +class RPBilBallPlaceFoul : public RPPartyUtlModel { +public: + virtual void Configure(); // at 0x78 + virtual void Reset(); // at 0x7C + virtual void Calculate(); // at 0x80 + virtual void Exit(); // at 0x84 + virtual void UserDraw(); // at 0x88 + +private: + u32 mId; // at 0x60 +}; + +#endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilCue.h b/include/Pack/RPParty/RPBilScene/RPBilCue.h index d6d0430..3258ff2 100644 --- a/include/Pack/RPParty/RPBilScene/RPBilCue.h +++ b/include/Pack/RPParty/RPBilScene/RPBilCue.h @@ -14,14 +14,16 @@ class RPBilCue : public RPPartyUtlModel { public: enum EState { - EState_Null, + EState_None, EState_PlaceFoul, EState_Wait, EState_Hold, EState_Pull, EState_FastTurn, EState_Hit, - EState_Dummy + EState_Dummy, + + EState_Max }; enum EDotState { @@ -39,19 +41,56 @@ class RPBilCue : public RPPartyUtlModel { }; public: + RPBilCue(u32 index); + virtual ~RPBilCue(); + + virtual void Configure(); // at 0x78 + virtual void Reset(); // at 0x7C + virtual void Calculate(); // at 0x80 + virtual void Exit(); // at 0x84 + virtual void UserDraw(); // at 0x88 + void CalcPosition(); void CalcForce(); + void FUN_802bd450(); + + void CalcMove(bool forward); + void CalcMtx(); + void CalcDpd(); + + bool IsState(EState state) const { + return mpStateMachine->IsState(state); + } + void ChangeState(EState state) { + mpStateMachine->ChangeState(state); + } void SetAimPosition(const EGG::Vector2f& pos) { mAimPosition = pos; mValidAim = true; } + const EGG::Vector3f& GetHitForce() const { + return mHitForce; + } + +public: + RP_UTL_FSM_STATE_DECL(PLACEFOUL); + RP_UTL_FSM_STATE_DECL(WAIT); + RP_UTL_FSM_STATE_DECL(HOLD); + RP_UTL_FSM_STATE_DECL(PULL); + RP_UTL_FSM_STATE_DECL(FASTTURN); + RP_UTL_FSM_STATE_DECL(HIT); + RP_UTL_FSM_STATE_DECL(DUMMY); + private: char _60[0x8]; RPUtlBaseFsm* mpStateMachine; // at 0x68 EDotState mDotState; // at 0x6C - char _70[0xA4 - 0x70]; + char _70[0x88 - 0x70]; + + EGG::Vector3f mHitForce; // at 0x88 + char _94[0xA4 - 0x94]; bool mValidAim; // at 0xA4 EGG::Vector2f mAimPosition; // at 0xA8 @@ -66,6 +105,8 @@ class RPBilCue : public RPPartyUtlModel { char _6880[0x68AC - 0x6880]; ECursor mCursor; // at 0x68AC + + char _0x68B0[0x68CC - 0x68B0]; }; #endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilCueManager.h b/include/Pack/RPParty/RPBilScene/RPBilCueManager.h index 297660c..2662432 100644 --- a/include/Pack/RPParty/RPBilScene/RPBilCueManager.h +++ b/include/Pack/RPParty/RPBilScene/RPBilCueManager.h @@ -1,23 +1,36 @@ #ifndef RP_PARTY_BIL_CUE_MANAGER_H #define RP_PARTY_BIL_CUE_MANAGER_H -#include "RPTypes.h" -#include -#include +#include +#include +#include + +// Forward declarations +class RPBilCue; class RPBilCueManager { RP_SINGLETON_DECL(RPBilCueManager); public: - RPBilCue* GetCue(int i) { - return mCues[i]; + RPBilCue* GetCue(u32 index) { + return mpCues[index]; } private: - static const int scCueNum = 2; + static const u32 MAX_CUE = 2; - int mCueNum; // at 0x4 + s32 mCueNum; // at 0x4 char _08[0x10 - 0x8]; - RPBilCue* mCues[scCueNum]; // at 0x10 + RPBilCue* mpCues[MAX_CUE]; // at 0x10 }; +#if defined(__KOKESHI__) +DECL_WEAK inline RPBilCueManager::RPBilCueManager() { + for (int i = 0; i < MAX_CUE; i++) { + mpCues[i] = new RPBilCue(i); + } + + mCueNum = RPBilMain::GetPlayerNum(); +} +#endif + #endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilDefine.h b/include/Pack/RPParty/RPBilScene/RPBilDefine.h new file mode 100644 index 0000000..91c4c95 --- /dev/null +++ b/include/Pack/RPParty/RPBilScene/RPBilDefine.h @@ -0,0 +1,41 @@ +#ifndef RP_PARTY_BIL_DEFINE_H +#define RP_PARTY_BIL_DEFINE_H +#include + +namespace RPBilDefine { + +/** + * @brief Model view ID + */ +enum EDrawView { + EView_0, + EView_3DDisplay, + EView_2, + EView_3, + EView_3DTable, + EView_2DLayout, + EView_6, + EView_7, + EView_8, + EView_9, + EView_10, + + EView_Max +}; + +/** + * @brief Model scene ID + */ +enum EDrawScene { + EDrawScene_0, + EDrawScene_Table, + EDrawScene_2, + EDrawScene_3, + EDrawScene_Display, + + EDrawScene_Max +}; + +} // namespace RPBilDefine + +#endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilLytBallNumber.h b/include/Pack/RPParty/RPBilScene/RPBilLytBallNumber.h new file mode 100644 index 0000000..f54f099 --- /dev/null +++ b/include/Pack/RPParty/RPBilScene/RPBilLytBallNumber.h @@ -0,0 +1,101 @@ +#ifndef RP_PARTY_BIL_LYT_BALL_NUMBER_H +#define RP_PARTY_BIL_LYT_BALL_NUMBER_H +#include +#include +#include +#include + +#include + +#include + +// Forward declarations +class RPSysLayout; +class RPSysLytAnmObj; + +class RPBilLytBallNumber : public RPUtlLytBase, public IRPGrpDrawObject { + RP_SINGLETON_DECL(RPBilLytBallNumber); + +public: + enum EState { + EState_Hide, + EState_AnimIn, + EState_Wait, + EState_AnimOut, + + EState_Max + }; + + virtual void LoadResource(EGG::Archive* pArchive); + virtual void Reset(); + virtual void Calculate(); + + virtual void UserDraw(); + + bool IsState(EState state) const { + return mStateMachine->IsState(state); + } + void ChangeState(EState state) { + mStateMachine->ChangeState(state); + } + +private: + enum EAnmObj { + EAnmObj_In, + EAnmObj_Out, + EAnmObj_Number1, + EAnmObj_Number2, + EAnmObj_Number3, + EAnmObj_Number4, + EAnmObj_Number5, + EAnmObj_Number6, + EAnmObj_Number7, + EAnmObj_Number8, + EAnmObj_Number9, + + EAnmObj_Max + }; + +private: + RP_UTL_FSM_STATE_DECL(HIDE); + RP_UTL_FSM_STATE_DECL(ANIMIN); + RP_UTL_FSM_STATE_DECL(WAIT); + RP_UTL_FSM_STATE_DECL(ANIMOUT); + +private: + RPUtlBaseFsm* mStateMachine; // at 0x10 + bool mDoAnimIn; // at 0x14 + bool _15; + bool _16; + s32 mBallNo; // at 0x18 + s32 _1C; // at 0x1C + RPSysLayout* mpLayout; // at 0x20 + RPSysLytAnmObj* mpAnmObjs[EAnmObj_Max]; // at 0x24 + nw4r::lyt::Pane* N_number_00; // at 0x50 +}; + +#if defined(__KOKESHI__) +DECL_WEAK inline RPBilLytBallNumber::RPBilLytBallNumber() { + mStateMachine = new RPUtlBaseFsm(this, EState_Max); + + mStateMachine->RegistState(&RPBilLytBallNumber::State_HIDE_enter, + &RPBilLytBallNumber::State_HIDE_calc, + EState_Hide); + + mStateMachine->RegistState(&RPBilLytBallNumber::State_ANIMIN_enter, + &RPBilLytBallNumber::State_ANIMIN_calc, + EState_AnimIn); + + mStateMachine->RegistState(&RPBilLytBallNumber::State_WAIT_enter, + &RPBilLytBallNumber::State_WAIT_calc, + EState_Wait); + + mStateMachine->RegistState(&RPBilLytBallNumber::State_ANIMOUT_enter, + &RPBilLytBallNumber::State_ANIMOUT_calc, + EState_AnimOut); + + RPGrpRenderer::GetCurrent()->AppendDrawObject(this); +} +#endif + +#endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilMain.h b/include/Pack/RPParty/RPBilScene/RPBilMain.h index 17f4d0d..dca6a1d 100644 --- a/include/Pack/RPParty/RPBilScene/RPBilMain.h +++ b/include/Pack/RPParty/RPBilScene/RPBilMain.h @@ -13,8 +13,14 @@ class RPBilMain { void Calculate(); void Reset(); + static u32 GetPlayerNum() { + return sPlayerNum; + } + private: RPUtlBaseFsm* mpStateMachine; // at 0x4 + + static u32 sPlayerNum; }; #endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilPocketCamManager.h b/include/Pack/RPParty/RPBilScene/RPBilPocketCamManager.h new file mode 100644 index 0000000..c0e50b2 --- /dev/null +++ b/include/Pack/RPParty/RPBilScene/RPBilPocketCamManager.h @@ -0,0 +1,14 @@ +#ifndef RP_PARTY_BIL_POCKET_CAM_MANAGER_H +#define RP_PARTY_BIL_POCKET_CAM_MANAGER_H +#include +#include + +class RPBilPocketCamManager { + RP_SINGLETON_DECL(RPBilPocketCamManager); + +public: + void HurryUp(); + void StartCamera(s32 pocketIndex); +}; + +#endif diff --git a/include/Pack/RPParty/RPBilScene/RPBilTable.h b/include/Pack/RPParty/RPBilScene/RPBilTable.h new file mode 100644 index 0000000..3cd7331 --- /dev/null +++ b/include/Pack/RPParty/RPBilScene/RPBilTable.h @@ -0,0 +1,16 @@ +#ifndef RP_PARTY_BIL_TABLE_H +#define RP_PARTY_BIL_TABLE_H +#include + +#include + +class RPBilTable { + RP_SINGLETON_DECL(RPBilTable); + +public: + bool IsValidPlaceFoul(const EGG::Vector3f& rPos, f32 radius) const; + + static EGG::Vector3f GetFootSpotPos(); +}; + +#endif diff --git a/include/Pack/RPParty/RPDucScene.h b/include/Pack/RPParty/RPDucScene.h new file mode 100644 index 0000000..ebd98a4 --- /dev/null +++ b/include/Pack/RPParty/RPDucScene.h @@ -0,0 +1,10 @@ +#ifndef RP_PARTY_DUC_SCENE_H +#define RP_PARTY_DUC_SCENE_H + +#include +#include +#include +#include +#include + +#endif diff --git a/include/Pack/RPParty/RPDucScene/RPDucCursor.h b/include/Pack/RPParty/RPDucScene/RPDucCursor.h new file mode 100644 index 0000000..150bb70 --- /dev/null +++ b/include/Pack/RPParty/RPDucScene/RPDucCursor.h @@ -0,0 +1,48 @@ +#ifndef RP_PARTY_DUC_CURSOR_H +#define RP_PARTY_DUC_CURSOR_H +#include + +#include + +// Forward declarations +class RPSysEffect; +template class TRPSndObject; + +class RPDucCursor /* : some common base */ { +public: + enum EEffectState { + EEffectState_Hide, + EEffectState_HideTail, + EEffectState_Show, + }; + +public: + RPDucCursor(); + virtual ~RPDucCursor(); // at 0x8 + + virtual void Configure(); // at 0xC + virtual void LoadResource(); // at 0x10 + virtual void Reset(); // at 0x14 + virtual void Calculate(); // at 0x18 + + virtual void VF_1C(); // at 0x1C + virtual void VF_20(); // at 0x20 + virtual void CreateMainEffect(); // at 0x24 + virtual void CreateTailEffect(); // at 0x28 + virtual void SetEffectState(EEffectState state); // at 0x2C + virtual void CalcEffectPos(); // at 0x30 + virtual void VF_34(); // at 0x34 + +private: + nw4r::math::VEC3 mPosition; // at 0x4 + char _10[0x84 - 0x10]; + s32 mChannel; // at 0x84 + s32 mState; // at 0x88 + RPSysEffect* mpMainEff; // at 0x8C + RPSysEffect* mpMainEffMulti; // at 0x90 + RPSysEffect* mpTailEff; // at 0x94 + RPSysEffect* mpTailEffMulti; // at 0x98 + TRPSndObject<4>* mpSndObject; // at 0x9C +}; + +#endif diff --git a/include/Pack/RPParty/RPDucScene/RPDucCursorMgr.h b/include/Pack/RPParty/RPDucScene/RPDucCursorMgr.h new file mode 100644 index 0000000..63927ed --- /dev/null +++ b/include/Pack/RPParty/RPDucScene/RPDucCursorMgr.h @@ -0,0 +1,40 @@ +#ifndef RP_PARTY_DUC_CURSOR_MGR_H +#define RP_PARTY_DUC_CURSOR_MGR_H +#include + +#include + +// Forward declarations +class RPDucCursor; + +class RPDucCursorMgr { + RP_SINGLETON_DECL(RPDucCursorMgr); + +public: + virtual UNKTYPE FUN_801b6b74(UNKTYPE); // at 0xC + virtual UNKTYPE FUN_80244a40(UNKTYPE); // at 0x10 + + virtual void Reset(); // at 0x14 + virtual void Calculate(); // at 0x18 + virtual void Exit(); // at 0x1C + + virtual UNKTYPE FUN_80244790(UNKTYPE); // at 0x20 + + void PlayCursorOnSfx(s32 idx); + void SetEffectState(s32 idx, RPDucCursor::EEffectState state); + + void CreateCursors(u32 num); + +private: + static const int MAX_CURSORS = 4; + + u32 mCursorCapacity; // at 0x4 + u32 mCursorNum; // at 0x8 + RPDucCursor* mpCursors[MAX_CURSORS]; // at 0xC +}; + +#if defined(__KOKESHI__) +DECL_WEAK inline RPDucCursorMgr::RPDucCursorMgr() {} +#endif + +#endif diff --git a/include/Pack/RPParty/RPDucScene/RPDucDefine.h b/include/Pack/RPParty/RPDucScene/RPDucDefine.h new file mode 100644 index 0000000..bc38eff --- /dev/null +++ b/include/Pack/RPParty/RPDucScene/RPDucDefine.h @@ -0,0 +1,21 @@ +#ifndef RP_PARTY_DUC_DEFINE_H +#define RP_PARTY_DUC_DEFINE_H +#include + +namespace RPDucDefine { + +/** + * @brief Model draw scene ID + */ +enum EDrawScene { + EDrawScene_0, + EDrawScene_1, + EDrawScene_2, + EDrawScene_3, + + EDrawScene_Max +}; + +} // namespace RPDucDefine + +#endif diff --git a/include/Pack/RPParty/RPDucScene/RPDucScene.h b/include/Pack/RPParty/RPDucScene/RPDucScene.h new file mode 100644 index 0000000..68bf921 --- /dev/null +++ b/include/Pack/RPParty/RPDucScene/RPDucScene.h @@ -0,0 +1,10 @@ +#ifndef RP_PARTY_DUC_SCENE_H +#define RP_PARTY_DUC_SCENE_H +#include "RPTypes.h" +#include + +class RPDucScene : public RPSysScene { +public: +}; + +#endif diff --git a/include/Pack/RPParty/RPDucScene/RPDucSequence.h b/include/Pack/RPParty/RPDucScene/RPDucSequence.h new file mode 100644 index 0000000..2db851f --- /dev/null +++ b/include/Pack/RPParty/RPDucScene/RPDucSequence.h @@ -0,0 +1,29 @@ +#ifndef RP_PARTY_DUC_SEQUENCE_H +#define RP_PARTY_DUC_SEQUENCE_H +#include "RPTypes.h" + +class RPDucSequence { + RP_SINGLETON_DECL(RPDucSequence); + +public: + void SetLevelNo(u32 no) { + mLevelNo = no; + } + u32 GetLevelNo() const { + return mLevelNo; + } + + void SetMaxLevelNo(u32 no) { + mMaxLevelNo = no; + } + u32 GetMaxLevelNo() const { + return mMaxLevelNo; + } + +private: + char _04[0x10 - 0x4]; + u32 mLevelNo; // at 0x10 + u32 mMaxLevelNo; // at 0x14 +}; + +#endif diff --git a/include/Pack/RPParty/RPPartyAppMiiManager.h b/include/Pack/RPParty/RPPartyAppMiiManager.h new file mode 100644 index 0000000..f19b131 --- /dev/null +++ b/include/Pack/RPParty/RPPartyAppMiiManager.h @@ -0,0 +1,20 @@ +#ifndef RP_PARTY_APP_MII_MANAGER_H +#define RP_PARTY_APP_MII_MANAGER_H +#include +#include + +//! @addtogroup rp_kernel +//! @{ + +/** + * @brief Party Pack application Mii manager + */ +class RPPartyAppMiiManager : public IRPSysAppMiiManager { +public: + // TODO + ; +}; + +//! @} + +#endif diff --git a/include/Pack/RPParty/RPPartyBodyManager.h b/include/Pack/RPParty/RPPartyBodyManager.h new file mode 100644 index 0000000..9fdc3b7 --- /dev/null +++ b/include/Pack/RPParty/RPPartyBodyManager.h @@ -0,0 +1,36 @@ +#ifndef RP_PARTY_BODY_MANAGER_H +#define RP_PARTY_BODY_MANAGER_H +#include +#include + +//! @addtogroup rp_kernel +//! @{ + +/** + * @brief Party Pack kokeshi body manager + */ +class RPPartyBodyManager : public IRPSysKokeshiBodyManager { +public: + RPPartyBodyManager(); + virtual ~RPPartyBodyManager(); // at 0x2C + + virtual u16 GetFriendClothesStartIndex(); // at 0x8 + virtual u16 GetFriendClothesIndexRange(); // at 0xC + + virtual const char* GetBodyFileName(u16, RFLSex); // at 0x10 + virtual u16 GetDummyHeadModelndex(); // at 0x14 + virtual const char* GetClothesFileName(); // at 0x18 + virtual void GetClothesName(u16, RFLSex, const char**, + const char**); // at 0x1C + + virtual void GetHeadJointMtx(u16, RPGrpModel*, + nw4r::math::MTX34*); // at 0x20 + virtual void GetLeftHandJointMtx(u16, RPGrpModel*, + nw4r::math::MTX34*); // at 0x24 + virtual void GetRightHandJointMtx(u16, RPGrpModel*, + nw4r::math::MTX34*); // at 0x28 +}; + +//! @} + +#endif diff --git a/include/Pack/RPParty/RPPartyGameMgr.h b/include/Pack/RPParty/RPPartyGameMgr.h index e99dfd8..76eb4dd 100644 --- a/include/Pack/RPParty/RPPartyGameMgr.h +++ b/include/Pack/RPParty/RPPartyGameMgr.h @@ -7,6 +7,25 @@ class RPPartyGameMgr { public: void Reset(); + + void SetPlayerNum(s32 num) { + mPlayerNum = num; + } + s32 GetPlayerNum() const { + return mPlayerNum; + } + + u32 GetVariable() const { + return mVariable; + } + void SetVariable(u32 no) { + mVariable = no; + } + +private: + s32 mPlayerNum; // at 0x4 + char _08[0x1C - 0x8]; + u32 mVariable; // at 0x1C }; #endif diff --git a/include/Pack/RPParty/RPPartySystemData.h b/include/Pack/RPParty/RPPartySystemData.h index e9cb2e8..50ff171 100644 --- a/include/Pack/RPParty/RPPartySystemData.h +++ b/include/Pack/RPParty/RPPartySystemData.h @@ -39,21 +39,23 @@ class RPPartySystemData { GAME_BIL, // Billiards GAME_FSH, // Fishing GAME_COW, // Charge! - GAME_TNK // Tanks! + GAME_TNK, // Tanks! + GAME_MAX }; // @brief Bit indices for the dialog seen bitfield enum EDialogSeen { - DIALOG_WELCOME, // Game is played for first time - DIALOG_STAGE_TWO, // Stage two is unlocked - DIALOG_STAGE_THREE, // Stage three is unlocked - DIALOG_STAGE_FOUR, // Stage four is unlocked - DIALOG_STAGE_FIVE, // Stage five is unlocked - DIALOG_STAGE_SIX, // Stage six is unlocked - DIALOG_STAGE_SEVEN, // Stage seven is unlocked - DIALOG_STAGE_EIGHT, // Stage eight is unlocked - DIALOG_FINAL_STAGE, // Stage nine (final stage) is unlocked - DIALOG_WII_REMOTE_MASTER // All stages are completed + DIALOG_WELCOME, // Game is played for first time + DIALOG_STAGE_TWO, // Stage two is unlocked + DIALOG_STAGE_THREE, // Stage three is unlocked + DIALOG_STAGE_FOUR, // Stage four is unlocked + DIALOG_STAGE_FIVE, // Stage five is unlocked + DIALOG_STAGE_SIX, // Stage six is unlocked + DIALOG_STAGE_SEVEN, // Stage seven is unlocked + DIALOG_STAGE_EIGHT, // Stage eight is unlocked + DIALOG_FINAL_STAGE, // Stage nine (final stage) is unlocked + DIALOG_WII_REMOTE_MASTER, // All stages are completed + DIALOG_MAX }; public: @@ -61,7 +63,15 @@ class RPPartySystemData { * @brief Check if a game has been unlocked * @address 8018d6ac */ - bool isGameUnlock(u32 id) const; + bool isGameOpen(u32 idx) const; + + void setGameOpen(u32 idx) { + mGameUnlockBitfield |= 1 << idx; + } + + void setDialogSeen(u32 idx) { + mDialogSeenBitfield |= 1 << idx; + } private: // @brief Mii History for every possible amount of players diff --git a/include/Pack/RPParty/RPPartyUtlModel.h b/include/Pack/RPParty/RPPartyUtlModel.h index 9b034c4..08829c1 100644 --- a/include/Pack/RPParty/RPPartyUtlModel.h +++ b/include/Pack/RPParty/RPPartyUtlModel.h @@ -5,7 +5,10 @@ #include #include #include -#include + +#include + +#include // Forward declarations class RPGrpModel; @@ -45,7 +48,17 @@ class RPPartyUtlModel : public RP_DEBUG_STUB_1, virtual void setModel(RPGrpModel* model); virtual void calcModel(); -private: + void setMtx(const nw4r::math::MTX34& rMtx) { + EGG::Vector3f x(rMtx._00, rMtx._10, rMtx._20); + EGG::Vector3f y(rMtx._01, rMtx._11, rMtx._21); + EGG::Vector3f z(rMtx._02, rMtx._12, rMtx._22); + + setMtxXBase(x); + setMtxYBase(y); + setMtxZBase(z); + } + +protected: EGG::Vector3f mPosition; // at 0x10 EGG::Vector3f mVelocity; // at 0x1C EGG::Vector3f _28; // at 0x28 diff --git a/include/Pack/RPParty/RPPartyUtlModelRigid.h b/include/Pack/RPParty/RPPartyUtlModelRigid.h new file mode 100644 index 0000000..90d3ef2 --- /dev/null +++ b/include/Pack/RPParty/RPPartyUtlModelRigid.h @@ -0,0 +1,62 @@ +#ifndef RP_PARTY_UTL_MODEL_RIGID_H +#define RP_PARTY_UTL_MODEL_RIGID_H +#include + +#include + +#include + +// Forward declarations +class RPGrpModel; + +/** + * @brief Party Pack rigid body physics utility + */ +class RPPartyUtlModelRigid : public RPPartyUtlModel { +public: + struct RigidParam { + s32 id; // at 0x0 + f32 mass; // at 0x4 + f32 gravity; // at 0x8 + f32 radius; // at 0xC + f32 _10; + f32 friction; // at 0x14 + f32 _18; + f32 _1C; + }; + + struct RigidBounding { + EGG::Vector3f min; // at 0x0 + EGG::Vector3f max; // at 0xC + }; + +public: + RPPartyUtlModelRigid(const RigidParam& rParam); + virtual ~RPPartyUtlModelRigid(); + + void Calculate(); + + bool isStopped() const; + + f32 getFriction() const { + return mParam.friction; + } + + f32 getRadius() const { + return mParam.radius; + } + +private: + RigidParam mParam; // at 0x60 + + EGG::Matrix34f _80; + EGG::Matrix34f _B0; + EGG::Vector3f mAngularVel; // at 0xE0 + char _EC[0xFC - 0xEC]; + + RigidBounding* _FC; + RigidBounding* _100; + RigidBounding* _104; +}; + +#endif diff --git a/include/Pack/RPParty/RPTnkScene.h b/include/Pack/RPParty/RPTnkScene.h new file mode 100644 index 0000000..546f93d --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene.h @@ -0,0 +1,18 @@ +#ifndef RP_PARTY_TNK_SCENE_H +#define RP_PARTY_TNK_SCENE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkBlock.h b/include/Pack/RPParty/RPTnkScene/RPTnkBlock.h new file mode 100644 index 0000000..402c912 --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkBlock.h @@ -0,0 +1,89 @@ +#ifndef RP_PARTY_TNK_BLOCK_H +#define RP_PARTY_TNK_BLOCK_H +#include +#include +#include + +#include + +/** + * @brief Tanks block object + */ +class RPTnkBlock : public RPTnkGameObjBase { +public: + RPTnkBlock(); + virtual ~RPTnkBlock(); // at 0x8 + + virtual void Configure(); // at 0xC + virtual void LoadResource(); // at 0x10 + virtual void Calculate(); // at 0x18 + + virtual void CalcModel(); // at 0x24 + + virtual void SetParam(); // at 0x64 + virtual void SetUserParam(u32 value); // at 0x68 + + virtual void CalcMove(); // at 0x6C + virtual void FirstCalc(); // at 0x70 + virtual void SecondCalc(); // at 0x74 + + virtual bool CollideBounding(const RPTnkGameObjBase* pOther, + u32 flags) const; // at 0x94 + + virtual u32 GetType() const; // at 0x9C + virtual u32 GetHeight() const; // at 0xA0 + + void StartBreakEffect(); + + static f32 GetSizeWidth() { + return sWidth; + } + static f32 GetSizeHeight() { + return sHeight; + } + +private: + typedef void (RPTnkBlock::*StateFunc)(); + + enum EState { + EState_Main, + + EState_Max + }; + + enum EModel { + EModel_Block1, + EModel_Block7, + EModel_Block8, + + EModel_Max + }; + +private: + void InitBounding(); + void CalcShadow(); + +private: + u32 mType; // at 0xB0 + u32 mState; // at 0xB4 + char _B8[0x138 - 0xB8]; + u32 mUpTileHeight; // at 0x138 + u32 mRightTileHeight; // at 0x13C + u32 mDownTileHeight; // at 0x140 + u32 mLeftTileHeight; // at 0x144 + bool mIsBreak; // at 0x148 + u32 mHeight; // at 0x14C + char _150[0x158 - 0x150]; + RPGrpModel* mpBlockModels[EModel_Max]; // at 0x158 + RPGrpModel* mpBlockShadowModel; // at 0x164 + EGG::Vector3f mShadowScale; // at 0x168 + StateFunc mStateFunctions[EState_Max]; // at 0x174 + +private: + static f32 sWidth; + static f32 sHeight; +}; + +DECOMP_SIZE_ASSERT(RPTnkBlock, 0x180); + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkBlockMgr.h b/include/Pack/RPParty/RPTnkScene/RPTnkBlockMgr.h new file mode 100644 index 0000000..8ffade0 --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkBlockMgr.h @@ -0,0 +1,24 @@ +#ifndef RP_PARTY_TNK_BLOCK_MGR_H +#define RP_PARTY_TNK_BLOCK_MGR_H +#include +#include +#include + +/** + * @brief Tanks block object manager + */ +class RPTnkBlockMgr : public RPTnkGameObjMgrBase { + RP_SINGLETON_DECL(RPTnkBlockMgr); + +public: + virtual RPTnkBlock* Create(); // at 0x24 + virtual void Finalize(); // at 0x2C + + void Clear(); +}; + +#if defined(__KOKESHI__) +DECL_WEAK inline RPTnkBlockMgr::RPTnkBlockMgr() {} +#endif + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkDefine.h b/include/Pack/RPParty/RPTnkScene/RPTnkDefine.h new file mode 100644 index 0000000..8696cdf --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkDefine.h @@ -0,0 +1,37 @@ +#ifndef RP_PARTY_TNK_DEFINE_H +#define RP_PARTY_TNK_DEFINE_H +#include + +namespace RPTnkDefine { + +/** + * @brief Model view ID + */ +enum EView { + EView_0, + EView_Actor, +}; + +/** + * @brief Model draw scene ID + */ +enum EDrawScene { + EDrawScene_Actor, + EDrawScene_1, + EDrawScene_2, + EDrawScene_3, + EDrawScene_4, + + EDrawScene_Max +}; + +/** + * @brief Model draw group ID + */ +enum EDrawGroup { + EDrawGroup_Actor, +}; + +} // namespace RPTnkDefine + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkFieldMgr.h b/include/Pack/RPParty/RPTnkScene/RPTnkFieldMgr.h new file mode 100644 index 0000000..45ab331 --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkFieldMgr.h @@ -0,0 +1,44 @@ +#ifndef RP_PARTY_TNK_FIELD_MGR_H +#define RP_PARTY_TNK_FIELD_MGR_H +#include +#include + +/** + * @brief Tanks field manager + */ +class RPTnkFieldMgr { + RP_SINGLETON_DECL(RPTnkFieldMgr); + +public: + f32 GetFieldWidthPixel() const { + return mFieldWidthPixel; + } + f32 GetFieldHeightPixel() const { + return mFieldHeightPixel; + } + + u32 GetFieldWidthBlock() const { + return mFieldWidthBlock; + } + u32 GetFieldHeightBlock() const { + return mFieldHeightBlock; + } + + f32 GetBlockSizeX() const { + return mBlockSizeX; + } + f32 GetBlockSizeZ() const { + return mBlockSizeZ; + } + +private: + f32 mFieldWidthPixel; // at 0x4 + f32 mFieldHeightPixel; // at 0x8 + u32 mFieldWidthBlock; // at 0xC + u32 mFieldHeightBlock; // at 0x10 + + f32 mBlockSizeX; // at 0x14 + f32 mBlockSizeZ; // at 0x18 +}; + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkGameObjBase.h b/include/Pack/RPParty/RPTnkScene/RPTnkGameObjBase.h new file mode 100644 index 0000000..24d737a --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkGameObjBase.h @@ -0,0 +1,111 @@ +#ifndef RP_PARTY_TNK_GAME_OBJ_BASE_H +#define RP_PARTY_TNK_GAME_OBJ_BASE_H +#include +#include + +#include + +// Forward declarations +template class TRPSndObject; + +/** + * @brief Basic tanks game actor + */ +class RPTnkGameObjBase : public RPUtlGameObjBase { +public: + /** + * @brief Block collision flags + */ + enum EBlockColFlag { + BLOCKCOL_NO_FLAT = (1 << 0), //!< Ignore blocks where height=1 + BLOCKCOL_NO_UPTALL = (1 << 1), //!< Ignore blocks where up height=2 + }; + +public: + RPTnkGameObjBase(); + virtual ~RPTnkGameObjBase(); // at 0x8 + + virtual void Configure(); // at 0xC + virtual void LoadResource(); // at 0x10 + virtual void Reset(); // at 0x14 + virtual void Calculate(); // at 0x18 + + virtual void InitParam(); // at 0x58 + + virtual void ResetDelta(); // at 0x5C + virtual void ApplyDelta(); // at 0x60 + + virtual void SetParam(); // at 0x64 + virtual void SetUserParam(u32 value); // at 0x68 + + virtual void CalcMove(); // at 0x6C + virtual void FirstCalc(); // at 0x70 + virtual void SecondCalc(); // at 0x74 + virtual void ThirdCalc(); // at 0x78 + + virtual void Init(const EGG::Vector3f& rPosition, u32 param); // at 0x7C + virtual void Destroy(); // at 0x80 + + virtual bool CheckSphere(const RPTnkGameObjBase* pOther, + f32* pHitDist) const; // at 0x84 + virtual bool CheckSphereMine(const RPTnkGameObjBase* pOther, + f32* pHitDist) const; // at 0x88 + + virtual void CalcBounding(); // at 0x8C + virtual void VF_90(); // at 0x90 + virtual bool CollideBounding(const RPTnkGameObjBase* pOther, + u32 flags) const; // at 0x94 + + virtual u32 GetID() const; // at 0x98 + virtual u32 GetType() const; // at 0x9C + virtual u32 GetHeight() const; // at 0xA0 + + virtual void SetMinePos(const EGG::Vector3f& rPosition); // at 0xA4 + virtual bool + IsExplodeBlock(const RPTnkGameObjBase* pOther) const; // at 0xA8 + virtual bool IsObjTrigger(const RPTnkGameObjBase* pOther) const; // at 0xAC + virtual void StopEffect(); // at 0xB0 + virtual void StartExplodeEffect(); // at 0xB4 + virtual bool IsExplode() const; // at 0xB8 + + virtual void SetOwner(RPTnkGameObjBase* pOwner); // at 0xBC + virtual RPTnkGameObjBase* GetOwner() const; // at 0xC0 + + const EGG::Vector3f& GetVelocity() const { + return mVelocity; + } + + bool IsAlive() const { + return mLifeTime >= 0; + } + bool IsDead() const { + return mLifeTime < 0; + } + + s32 GetLifeTime() const { + return mLifeTime; + } + void SetLifeTime(s32 lifeTime) { + mLifeTime = lifeTime; + } + +private: + EGG::Vector3f mVelocity; // at 0x48 + EGG::Vector3f g_reject_vel; // at 0x54 + EGG::Vector3f g_reject_vel2; // at 0x60 + EGG::Vector3f g_reject_vel3; // at 0x6C + EGG::Vector3f _78; // at 0x78 + + EGG::Vector3f mHitOffset; // at 0x84 + f32 mHitRadius; // at 0x90 + EGG::Vector3f mHitOffsetSP; // at 0x94 + + s32 mLifeTime; // at 0xA0 + char _A4[0xAC - 0xA4]; + + TRPSndObject<4>* mpSndObject; // at 0xAC +}; + +DECOMP_SIZE_ASSERT(RPTnkGameObjBase, 0xB0); + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkGameObjMgrBase.h b/include/Pack/RPParty/RPTnkScene/RPTnkGameObjMgrBase.h new file mode 100644 index 0000000..9bc4c9a --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkGameObjMgrBase.h @@ -0,0 +1,50 @@ +#ifndef RP_PARTY_TNK_GAME_OBJ_MGR_BASE_H +#define RP_PARTY_TNK_GAME_OBJ_MGR_BASE_H +#include +#include + +#include + +// Forward declarations +class RPTnkGameObjBase; + +/** + * @brief Tanks game object manager + */ +class RPTnkGameObjMgrBase : public RPUtlActorBase { +public: + RPTnkGameObjMgrBase(); + virtual ~RPTnkGameObjMgrBase(); // at 0x8 + + virtual void LoadResource(); // at 0x10 + virtual void Reset(); // at 0x14 + + virtual RPTnkGameObjBase* Create() = 0; // at 0x24 + virtual void Reserve(u32 num); // at 0x28 + virtual void Finalize() = 0; // at 0x2C + + virtual void CalcMove(); // at 0x30 + virtual void FirstCalc(); // at 0x34 + virtual void SecondCalc(); // at 0x38 + virtual void ThirdCalc(); // at 0x3C + + virtual void OnCalculate(); // at 0x40 + virtual void CalcLifeTime(); // at 0x44 + virtual void CalcModel(); // at 0x48 + + virtual void Init(const EGG::Vector3f& rPosition, u32 param); // at 0x4C + virtual void Destroy(); // at 0x50 + +protected: + typedef RPTnkGameObjBase** Iterator; + typedef const RPTnkGameObjBase** ConstIterator; + +protected: + u32 mCapacity; // at 0x4 + u32 mSize; // at 0x8 + RPTnkGameObjBase** mppData; // at 0xC + RPTnkGameObjBase** mppDataFree; // at 0x10 + RPTnkGameObjBase** mppDataEnd; // at 0x14 +}; + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkMapMgr.h b/include/Pack/RPParty/RPTnkScene/RPTnkMapMgr.h new file mode 100644 index 0000000..71110e1 --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkMapMgr.h @@ -0,0 +1,15 @@ +#ifndef RP_PARTY_TNK_MAP_MGR_H +#define RP_PARTY_TNK_MAP_MGR_H +#include + +// Forward declarations +class RPTnkMapResMgr; + +class RPTnkMapMgr { + RP_SINGLETON_DECL(RPTnkMapMgr); + +private: + RPTnkMapResMgr* mpResMgr; // at 0x4 +}; + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkMapResMgr.h b/include/Pack/RPParty/RPTnkScene/RPTnkMapResMgr.h new file mode 100644 index 0000000..7c39552 --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkMapResMgr.h @@ -0,0 +1,30 @@ +#ifndef RP_PARTY_TNK_MAP_RES_MGR_H +#define RP_PARTY_TNK_MAP_RES_MGR_H +#include + +struct RPTnkMapData { + u32 width; // at 0x0 + u32 height; // at 0x4 + u32 balloonP1; // at 0x8 + u32 balloonP2; // at 0xC + u32 tiles[1]; // at 0x10... +}; + +class RPTnkMapResMgr { + RP_SINGLETON_DECL(RPTnkMapResMgr); + +public: + static const int MAX_MAP = 30; + + enum EGameMode { + EGameMode_1P, + EGameMode_VS, + + EGameMode_Max, + }; + +private: + enum EBalloonPos {}; +}; + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkMine.h b/include/Pack/RPParty/RPTnkScene/RPTnkMine.h new file mode 100644 index 0000000..4fac401 --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkMine.h @@ -0,0 +1,15 @@ +#ifndef RP_PARTY_TNK_MINE_H +#define RP_PARTY_TNK_MINE_H +#include +#include + +/** + * @brief Tanks mine object + */ +class RPTnkMine : public RPTnkGameObjBase { +public: + RPTnkMine(); + virtual ~RPTnkMine(); // at 0x8 +}; + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkMineMgr.h b/include/Pack/RPParty/RPTnkScene/RPTnkMineMgr.h new file mode 100644 index 0000000..bc00e03 --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkMineMgr.h @@ -0,0 +1,25 @@ +#ifndef RP_PARTY_TNK_MINE_MGR_H +#define RP_PARTY_TNK_MINE_MGR_H +#include +#include +#include + +/** + * @brief Tanks mine object manager + */ +class RPTnkMineMgr : public RPTnkGameObjMgrBase { + RP_SINGLETON_DECL(RPTnkMineMgr); + +public: + virtual RPTnkMine* Create(); // at 0x24 + virtual void Finalize(); // at 0x2C + + bool IsExplodeBlock(const RPTnkGameObjBase* pOther) const; + bool IsExplodeMine(const RPTnkGameObjBase* pOther) const; +}; + +#if defined(__KOKESHI__) +DECL_WEAK inline RPTnkMineMgr::RPTnkMineMgr() {} +#endif + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkSequence.h b/include/Pack/RPParty/RPTnkScene/RPTnkSequence.h new file mode 100644 index 0000000..5d3de3f --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkSequence.h @@ -0,0 +1,35 @@ +#ifndef RP_PARTY_TNK_SEQUENCE_H +#define RP_PARTY_TNK_SEQUENCE_H +#include + +class RPTnkSequence /* some base class */ { + RP_SINGLETON_DECL(RPTnkSequence); + +public: + void SetLevelNo(u32 no) { + mLevelNo = no; + } + u32 GetLevelNo() const { + return mLevelNo; + } + + void SetMaxLevelNo(u32 no) { + mMaxLevelNo = no; + } + u32 GetMaxLevelNo() const { + return mMaxLevelNo; + } + + u32 GetPlayerNum() const { + return mPlayerNum; + } + +private: + char _04[0x8 - 0x4]; + u32 mLevelNo; // at 0x8 + u32 mMaxLevelNo; // at 0xC + char _10[0x28 - 0x10]; + u32 mPlayerNum; // at 0x28 +}; + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkShell.h b/include/Pack/RPParty/RPTnkScene/RPTnkShell.h new file mode 100644 index 0000000..b666906 --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkShell.h @@ -0,0 +1,24 @@ +#ifndef RP_PARTY_TNK_SHELL_H +#define RP_PARTY_TNK_SHELL_H +#include +#include + +/** + * @brief Tanks shell (bullet) object + */ +class RPTnkShell : public RPTnkGameObjBase { +public: + RPTnkShell(); + virtual ~RPTnkShell(); // at 0x8 + + void SetForceKill(bool enable) { + mIsForceKill = enable; + } + +private: + u32 mRicochetRemain; // at 0xB0 + char _B4[0xC5 - 0xB4]; + bool mIsForceKill; // at 0xC5 +}; + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkShellMgr.h b/include/Pack/RPParty/RPTnkScene/RPTnkShellMgr.h new file mode 100644 index 0000000..c63a768 --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkShellMgr.h @@ -0,0 +1,25 @@ +#ifndef RP_PARTY_TNK_SHELL_MGR_H +#define RP_PARTY_TNK_SHELL_MGR_H +#include +#include +#include + +/** + * @brief Tanks mine object manager + */ +class RPTnkShellMgr : public RPTnkGameObjMgrBase { + RP_SINGLETON_DECL(RPTnkShellMgr); + +public: + virtual RPTnkShell* Create(); // at 0x24 + virtual void Finalize(); // at 0x2C + +private: + char _18[0x40 - 0x18]; +}; + +#if defined(__KOKESHI__) +DECL_WEAK inline RPTnkShellMgr::RPTnkShellMgr() {} +#endif + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkTank.h b/include/Pack/RPParty/RPTnkScene/RPTnkTank.h new file mode 100644 index 0000000..76c117c --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkTank.h @@ -0,0 +1,15 @@ +#ifndef RP_PARTY_TNK_TANK_H +#define RP_PARTY_TNK_TANK_H +#include +#include + +/** + * @brief Tanks tank object + */ +class RPTnkTank : public RPTnkGameObjBase { +public: + RPTnkTank(); + virtual ~RPTnkTank(); // at 0x8 +}; + +#endif diff --git a/include/Pack/RPParty/RPTnkScene/RPTnkTankMgr.h b/include/Pack/RPParty/RPTnkScene/RPTnkTankMgr.h new file mode 100644 index 0000000..53d1537 --- /dev/null +++ b/include/Pack/RPParty/RPTnkScene/RPTnkTankMgr.h @@ -0,0 +1,25 @@ +#ifndef RP_PARTY_TNK_TANK_MGR_H +#define RP_PARTY_TNK_TANK_MGR_H +#include +#include +#include + +/** + * @brief Tanks tank object manager + */ +class RPTnkTankMgr : public RPTnkGameObjMgrBase { + RP_SINGLETON_DECL(RPTnkTankMgr); + +public: + virtual RPTnkTank* Create(); // at 0x24 + virtual void Finalize(); // at 0x2C + +private: + char _18[0x3C - 0x18]; +}; + +#if defined(__KOKESHI__) +DECL_WEAK inline RPTnkTankMgr::RPTnkTankMgr() {} +#endif + +#endif diff --git a/include/Pack/RPParty/RPWlyScene/RPWlyMain.h b/include/Pack/RPParty/RPWlyScene/RPWlyMain.h new file mode 100644 index 0000000..0c670fb --- /dev/null +++ b/include/Pack/RPParty/RPWlyScene/RPWlyMain.h @@ -0,0 +1,12 @@ +#ifndef RP_PARTY_WLY_MAIN_H +#define RP_PARTY_WLY_MAIN_H +#include "RPTypes.h" + +class RPWlyMain { + RP_SINGLETON_DECL(RPWlyMain); + +public: + void Reset(); +}; + +#endif diff --git a/include/Pack/RPSystem/RPSysPauseMgr.h b/include/Pack/RPSystem/RPSysPauseMgr.h index 2f9cb05..599a8cb 100644 --- a/include/Pack/RPSystem/RPSysPauseMgr.h +++ b/include/Pack/RPSystem/RPSysPauseMgr.h @@ -6,7 +6,14 @@ class RPSysPauseMgr { RP_SINGLETON_DECL(RPSysPauseMgr); public: + bool isPause() const { + return mFlags & 1; + } + void LoadResource(); + +private: + u32 mFlags; // at 0x0 }; #endif diff --git a/include/Pack/RPSystem/RPSysProjectLocal.h b/include/Pack/RPSystem/RPSysProjectLocal.h index a47dbbb..16ccc30 100644 --- a/include/Pack/RPSystem/RPSysProjectLocal.h +++ b/include/Pack/RPSystem/RPSysProjectLocal.h @@ -67,6 +67,13 @@ class RPSysProjectLocal { */ void setLanguage(EArea lang); + /** + * @brief Gets the current Pack Project game ID + */ + RPSysSceneCreator::EPackID getPack() const { + return mPack; + } + private: //! Game region ERegion mRegion; // at 0x8 diff --git a/include/Pack/RPSystem/RPSysResourceManager.h b/include/Pack/RPSystem/RPSysResourceManager.h index fcf3daa..4d46953 100644 --- a/include/Pack/RPSystem/RPSysResourceManager.h +++ b/include/Pack/RPSystem/RPSysResourceManager.h @@ -164,10 +164,10 @@ class RPSysResourceManager { void GetGameSoundLocalPath(char* pBuffer, u32 bufSize, s32 id); private: - //! Resource cache for common archives - nw4r::ut::List mCommonCache; // at 0x4 - //! Resource cache for other files loaded from the DVD - nw4r::ut::List mUserCache; // at 0x10 + //! Resource cache for compressed files + nw4r::ut::List mFileCache; // at 0x4 + //! Resource cache for decompressed files + nw4r::ut::List mDecompFileCache; // at 0x10 //! Work buffer for building filepaths char* mpPathWork; // at 0x1C diff --git a/include/Pack/RPSystem/RPSysSaveData.h b/include/Pack/RPSystem/RPSysSaveData.h index cf396ed..984f8f1 100644 --- a/include/Pack/RPSystem/RPSysSaveData.h +++ b/include/Pack/RPSystem/RPSysSaveData.h @@ -5,9 +5,9 @@ #include "RPTypes.h" // Forward declarations -class RPPartyCommonData; +class RPPartySystemData; class RPPartyPlayerData; -class RPSportsCommonData; +class RPSportsSystemData; class RPSportsPlayerData; /** @@ -50,7 +50,7 @@ class RPSysSaveData { void read(EGG::RamStream* stream, const void* rawSave); // @address 8018c32c - RPPartyCommonData* getPartyCommonData() const; + RPPartySystemData* getPartySystemData() const; // @address 8018c334 void setPartyPlayerData(const RPPartyPlayerData* playerData, u32 id); @@ -58,9 +58,9 @@ class RPSysSaveData { RPPartyPlayerData* getPartyPlayerData(u32 id) const; // @address 8018c41c - void setSportsCommonData(const RPSportsCommonData* cmnData); + void setSportsSystemData(const RPSportsSystemData* cmnData); // @address 8018c684 - RPSportsCommonData* getSportsCommonData() const; + RPSportsSystemData* getSportsSystemData() const; // @address 8018c68c void setSportsPlayerData(const RPSportsPlayerData* playerData, u32 id); @@ -77,12 +77,12 @@ class RPSysSaveData { private: // @brief Flags regarding the status of the data u32 mErrors; // at 0x0 - // @brief Wii Sports common save data - RPSportsCommonData* mSportsCmnData; // at 0x4 + // @brief Wii Sports System save data + RPSportsSystemData* mSportsCmnData; // at 0x4 // @brief Wii Sports player list (100 entries) RPSportsPlayerData* mSportsPlayerList; // at 0x8 - // @brief Wii Play common save data - RPPartyCommonData* mPartyCmnData; // at 0xC + // @brief Wii Play System save data + RPPartySystemData* mPartyCmnData; // at 0xC // @brief Wii Play player list (100 entries) RPPartyPlayerData* mPartyPlayerList; // at 0x10 diff --git a/include/Pack/RPSystem/RPSysSaveDataMgr.h b/include/Pack/RPSystem/RPSysSaveDataMgr.h index 71a740d..3ab1aa3 100644 --- a/include/Pack/RPSystem/RPSysSaveDataMgr.h +++ b/include/Pack/RPSystem/RPSysSaveDataMgr.h @@ -12,6 +12,9 @@ //! @addtogroup rp_system //! @{ +// Forward declarations +class RPSysSaveData; + /** * @brief Save data manager * @wfuname @@ -55,12 +58,14 @@ class RPSysSaveDataMgr : public IRPSysHostIOSocket { * @return Copy of the system data */ RPSportsSystemData getSportsSystemData() const; +#if defined(PACK_SPORTS) /** * @brief Sets the Sports Pack system data * * @param rData System data */ void setSportsSystemData(const RPSportsSystemData& rData); +#endif /** * @brief Gets the Party Pack player data corresponding to the player index @@ -83,6 +88,14 @@ class RPSysSaveDataMgr : public IRPSysHostIOSocket { * @return Copy of the system data */ RPPartySystemData getPartySystemData() const; +#if defined(PACK_PLAY) + /** + * @brief Sets the Party Pack system data + * + * @param rData System data + */ + void setPartySystemData(const RPPartySystemData& rData); +#endif /**@}*/ /** @@ -142,6 +155,16 @@ class RPSysSaveDataMgr : public IRPSysHostIOSocket { * @return Success */ bool saveAsync(); + + /** + * @brief Saves the save file to the NAND + * @details If saving is disabled, this function does nothing. + */ + void saveSync(); + /** + * @brief Loads the save file from the NAND + */ + void loadSync(); /**@}*/ /** @@ -252,10 +275,15 @@ class RPSysSaveDataMgr : public IRPSysHostIOSocket { //!< currently displayed EFlag_11, EFlag_NandError, //!< Unrecoverable NAND error - EFlag_12, + EFlag_13, }; private: + /** + * @brief Constructor + */ + RPSysSaveDataMgr(); + /** * @brief Prompts the user to continue without saving */ @@ -274,16 +302,6 @@ class RPSysSaveDataMgr : public IRPSysHostIOSocket { */ void createBannerFile(); - /** - * @brief Saves the save file to the NAND - * @details If saving is disabled, this function does nothing. - */ - void saveSync(); - /** - * @brief Loads the save file from the NAND - */ - void loadSync(); - /** * @brief Saves the banner file to the NAND * diff --git a/include/Pack/RPSystem/RPSysSystem.h b/include/Pack/RPSystem/RPSysSystem.h index 0af7019..5fef2ac 100644 --- a/include/Pack/RPSystem/RPSysSystem.h +++ b/include/Pack/RPSystem/RPSysSystem.h @@ -39,7 +39,7 @@ class RPSysSystem { /** * @brief Gets this class's singleton instance */ - static RPSysSystem* getInstance() { + static RPSysSystem* instance() { return spInstance; } diff --git a/include/Pack/RPTypes.h b/include/Pack/RPTypes.h index 56441f9..d6fe2f9 100644 --- a/include/Pack/RPTypes.h +++ b/include/Pack/RPTypes.h @@ -16,7 +16,7 @@ public: \ static void CreateInstance(); \ static void DestroyInstance(); \ - static T* getInstance() { \ + static T* instance() { \ return spInstance; \ }; \ \ @@ -48,7 +48,7 @@ private: \ public: \ static T* CreateInstance(EGG::Heap* pHeap); \ static void DestroyInstance(); \ - static T* getInstance() { \ + static T* instance() { \ return spInstance; \ } \ \ @@ -85,7 +85,7 @@ private: \ //! Accesses RP singleton instance by typename #ifndef RP_GET_INSTANCE -#define RP_GET_INSTANCE(T) T::getInstance() +#define RP_GET_INSTANCE(T) T::instance() #endif //! @brief Holds year, month, month day diff --git a/include/Pack/RPUtility/RPUtlActorBase.h b/include/Pack/RPUtility/RPUtlActorBase.h new file mode 100644 index 0000000..2679db9 --- /dev/null +++ b/include/Pack/RPUtility/RPUtlActorBase.h @@ -0,0 +1,22 @@ +#ifndef RP_UTILITY_ACTOR_BASE_H +#define RP_UTILITY_ACTOR_BASE_H +#include +#include + +/** + * @brief Basic actor with lifecycle hooks + */ +class RPUtlActorBase : public RP_DEBUG_STUB_1 { +public: + RPUtlActorBase(); + virtual ~RPUtlActorBase(); // at 0x8 + + virtual void Configure(); // at 0xC + virtual void LoadResource(); // at 0x10 + virtual void Reset(); // at 0x14 + virtual void Calculate(); // at 0x18 + virtual void Exit(); // at 0x1C + virtual void UserDraw(); // at 0x20 +}; + +#endif diff --git a/include/Pack/RPUtility/RPUtlBaseFsm.h b/include/Pack/RPUtility/RPUtlBaseFsm.h index dbce74a..e947143 100644 --- a/include/Pack/RPUtility/RPUtlBaseFsm.h +++ b/include/Pack/RPUtility/RPUtlBaseFsm.h @@ -42,7 +42,7 @@ template class RPUtlBaseFsm { * @param calc State update function * @param id State ID */ - void RegistState(StateFunc enter, StateFunc calc, u32 id) { + void RegistState(StateFunc enter, StateFunc calc, int id) { mEnterFns[id] = enter; mCalcFns[id] = calc; } @@ -50,7 +50,7 @@ template class RPUtlBaseFsm { /** * @brief Change to new state */ - void ChangeState(u32 id) { + void ChangeState(int id) { mNextState = id; mDoEnter = true; mDoExit = true; @@ -81,10 +81,17 @@ template class RPUtlBaseFsm { } } + /** + * @brief Check for entering a new state + */ + bool IsChangingState() const { + return mDoEnter; + } + /** * @brief Check for a specific state */ - bool IsState(u32 id) const { + bool IsState(int id) const { // Currently in the state if (mState == id) { return true; @@ -98,6 +105,13 @@ template class RPUtlBaseFsm { return false; } + /** + * @brief Check for a specific state on this tick only + */ + bool IsStateNow(int id) const { + return mState == id; + } + private: /** * @brief Enter the current state diff --git a/include/Pack/RPUtility/RPUtlGameObjBase.h b/include/Pack/RPUtility/RPUtlGameObjBase.h new file mode 100644 index 0000000..3a87ae7 --- /dev/null +++ b/include/Pack/RPUtility/RPUtlGameObjBase.h @@ -0,0 +1,69 @@ +#ifndef RP_UTILITY_GAME_OBJ_BASE_H +#define RP_UTILITY_GAME_OBJ_BASE_H +#include +#include +#include + +#include + +/** + * @brief Basic game object actor + */ +class RPUtlGameObjBase : public RPUtlActorBase { +public: + RPUtlGameObjBase(); + virtual ~RPUtlGameObjBase(); // at 0x8 + + virtual void Calculate(); // at 0x18 + virtual void UserDraw(); // at 0x20 + + virtual void CalcModel(); // at 0x24 + + virtual void CreateModel(const char* pName, u16 arg1, u16 arg2); // at 0x28 + virtual void CreateModel(u16 rd); // at 0x2C + virtual void CreateAnm(RPGrpModelAnm::Anm anm, u16 num); // at 0x30 + + virtual void BindAnm(const char* pName, u16 arg1, RPGrpModelAnm::Anm anm, + u16 no); // at 0x34 + virtual void BindAnm(RPGrpModelAnm::Anm anm, u16 no, u16 rd); // at 0x38 + + virtual void StartAnm(RPGrpModelAnm::Anm anm, u16 no, + f32 frame); // at 0x3C + virtual void StartAnmBlend(RPGrpModelAnm::Anm anm, u16 no, f32 frame, + f32 weight); // at 0x40 + + virtual void CancelAnm(RPGrpModelAnm::Anm anm, u16 no); // at 0x44 + + virtual void SetAnmUpdateRate(RPGrpModelAnm::Anm anm, u16 no, + f32 rate); // at 0x48 + + virtual f32 GetAnmFrame(RPGrpModelAnm::Anm anm, u16 no) const; // at 0x4C + virtual f32 GetAnmNumFrame(RPGrpModelAnm::Anm anm, u16 no) const; // at 0x50 + + virtual void InitModel(bool arg0); // at 0x54 + + const EGG::Vector3f& GetPosition() const { + return mPosition; + } + const EGG::Vector3f& GetScale() const { + return mScale; + } + const EGG::Matrix33f& GetTransform() const { + return mTransform; + } + + RPGrpModel* GetModel() const { + return mpModel; + } + +private: + EGG::Vector3f mPosition; // at 0x4 + EGG::Vector3f mScale; // at 0x10 + EGG::Matrix33f mTransform; // at 0x1C + bool _40; + RPGrpModel* mpModel; // at 0x44 +}; + +DECOMP_SIZE_ASSERT(RPUtlGameObjBase, 0x48); + +#endif diff --git a/include/Pack/RPUtility/RPUtlLytBase.h b/include/Pack/RPUtility/RPUtlLytBase.h index 0d5cb0d..1d45127 100644 --- a/include/Pack/RPUtility/RPUtlLytBase.h +++ b/include/Pack/RPUtility/RPUtlLytBase.h @@ -11,14 +11,16 @@ class RPUtlLytBase { public: RPUtlLytBase(); - virtual void LoadResource(EGG::Archive* arc); - virtual void Reset(); - virtual void Calculate(); - virtual void UserDraw(); - virtual void VF_18(); - // virtual ~RPUtlLytBase() = 0; + virtual void LoadResource(EGG::Archive* pArchive); // at 0x8 + virtual void Reset(); // at 0xC + virtual void Calculate(); // at 0x10 + virtual void VF_14(); // at 0x14 + virtual void VF_18(); // at 0x18 -private: + static void mountArchive(EGG::Archive* pArchive, const char* pPath, + RPSysLytResAccessor* pAccessor); + +protected: RPSysLytResAccessor* mAccessor; // at 0x4 }; diff --git a/include/Sports2/Swf/Sp2SwfScene.h b/include/Sports2/Swf/Sp2SwfScene.h index cac4760..7e58df7 100644 --- a/include/Sports2/Swf/Sp2SwfScene.h +++ b/include/Sports2/Swf/Sp2SwfScene.h @@ -11,7 +11,7 @@ class PrcRuleObject; class Scene /* : public RPSysMplsGameScene */ { public: - static Scene* getInstance() { + static Scene* instance() { return sInstance; } diff --git a/include/__doxygen.hpp b/include/__doxygen.hpp index 237d720..30cf063 100644 --- a/include/__doxygen.hpp +++ b/include/__doxygen.hpp @@ -362,6 +362,10 @@ //! @defgroup libkiwi_prim prim //! @brief Primitives +//! @ingroup libkiwi +//! @defgroup libkiwi_resource resource +//! @brief Asset patching system + //! @ingroup libkiwi //! @defgroup libkiwi_support support //! @brief Compiler runtime/RVL SDK implementation @@ -515,6 +519,32 @@ namespace json {} //! @} +//! @addtogroup libkiwi +//! @{ + +//! @brief libkiwi CHIP-8 emulator +namespace chip8 {} + +//! @} + +//! @addtogroup libkiwi +//! @{ + +//! @brief libkiwi Host I/O +namespace hostio { + +//! @addtogroup libkiwi +//! @{ + +//! @brief libkiwi Host I/O internals +namespace detail {} + +//! @} + +} + +//! @} + } // namespace kiwi //! @} diff --git a/include/decomp.h b/include/decomp.h index fc862f9..7ca4bb6 100644 --- a/include/decomp.h +++ b/include/decomp.h @@ -44,4 +44,7 @@ #define DECOMP_DONT_INLINE __attribute__((never_inline)) #endif +#define DECOMP_SIZE_ASSERT(cls, size) \ + extern u8 __SZ_PREDICATE[(sizeof(cls) == size) ? 1 : -1] + #endif diff --git a/include/egg/audio.h b/include/egg/audio.h index 945485e..8147db5 100644 --- a/include/egg/audio.h +++ b/include/egg/audio.h @@ -1,13 +1,13 @@ #ifndef EGG_PUBLIC_AUDIO_H #define EGG_PUBLIC_AUDIO_H +#include +#include #include #include #include #include #include -#include #include -#include #endif diff --git a/include/egg/audio/eggAudio3DActor.h b/include/egg/audio/eggAudio3DActor.h new file mode 100644 index 0000000..8cf1384 --- /dev/null +++ b/include/egg/audio/eggAudio3DActor.h @@ -0,0 +1,25 @@ +#ifndef EGG_AUDIO_3D_ACTOR_H +#define EGG_AUDIO_3D_ACTOR_H +#include + +#include + +namespace EGG { + +class AudioSound3DActor { +public: + static void setCommonPlayer(nw4r::snd::SoundArchivePlayer* pPlayer) { + smCommonPlayer = pPlayer; + } + static void setCommonManager(nw4r::snd::Sound3DManager* pManager) { + smCommon3DManager = pManager; + } + +private: + static nw4r::snd::SoundArchivePlayer* smCommonPlayer; + static nw4r::snd::Sound3DManager* smCommon3DManager; +}; + +} // namespace EGG + +#endif diff --git a/include/egg/audio/eggAudio3DMgr.h b/include/egg/audio/eggAudio3DMgr.h new file mode 100644 index 0000000..09ae7f0 --- /dev/null +++ b/include/egg/audio/eggAudio3DMgr.h @@ -0,0 +1,93 @@ +#ifndef EGG_AUDIO_3D_MGR_H +#define EGG_AUDIO_3D_MGR_H +#include + +#include + +#include + +namespace EGG { + +template class TAudioSound3DMgr { +public: + struct TAudioSound3DMgrArg { + s32 maxPrioReduction; // at 0x0 + f32 interiorSize; // at 0x4 + f32 maxVolumeDistance; // at 0x8 + f32 unitDistance; // at 0xC + }; + +public: + TAudioSound3DMgr() : mListenerCount(N), mCameraCount(1) { + mSoundArchive3D = NULL; + } + + void initialize3D(TAudioSound3DMgrArg* arg) { +#line 63 + EGG_ASSERT(arg); + + for (int i = 0; i < N; i++) { + mSound3DManagers[i].SetMaxPriorityReduction(arg->maxPrioReduction); + + mSound3DListeners[i].SetInteriorSize(arg->interiorSize); + mSound3DListeners[i].SetMaxVolumeDistance(arg->maxVolumeDistance); + mSound3DListeners[i].SetUnitDistance(arg->unitDistance); + + mSound3DManagers[i].AddListener(&mSound3DListeners[i]); + } + } + + void setUseArchive3D(nw4r::snd::SoundArchive* archive, + nw4r::snd::SoundHeap* heap) { + + mSoundArchive3D = archive; + + if (mSoundArchive3D == NULL) { + return; + } + +#line 92 + EGG_ASSERT(heap); + + for (int i = 0; i < N; i++) { + u32 heapSize = mSound3DManagers[i].GetRequiredMemSize(archive); + void* pHeapBuffer = heap->Alloc(heapSize, NULL, NULL); + mSound3DManagers[i].Setup(archive, pHeapBuffer, heapSize); + } + } + + void clearArchive3D() { + mSoundArchive3D = NULL; + } + + nw4r::snd::Sound3DManager& getSound3DManager(s32 cam_num) { + return mSound3DManagers[cam_num]; + } + + void setListenerMatrix(s32 cam_num, const nw4r::math::MTX34& rMtx) { +#line 107 + EGG_ASSERT(cam_num=cam_count); + + mCameraCount = cam_count; + } + +private: + nw4r::snd::Sound3DManager mSound3DManagers[N]; + nw4r::snd::Sound3DListener mSound3DListeners[N]; + nw4r::snd::SoundArchive* mSoundArchive3D; + + s32 mListenerCount; + s32 mCameraCount; +}; + +} // namespace EGG + +#endif diff --git a/include/egg/audio/eggAudioArcPlayerMgr.h b/include/egg/audio/eggAudioArcPlayerMgr.h index f548af7..0a73885 100644 --- a/include/egg/audio/eggAudioArcPlayerMgr.h +++ b/include/egg/audio/eggAudioArcPlayerMgr.h @@ -1,138 +1,153 @@ -#ifndef EGG_AUDIO_ARCPLAYER_MGR_H -#define EGG_AUDIO_ARCPLAYER_MGR_H -#include "snd_DvdSoundArchive.h" -#include "snd_MemorySoundArchive.h" -#include "snd_NandSoundArchive.h" -#include "snd_SoundArchivePlayer.h" -#include "snd_SoundHeap.h" -#include "types_egg.h" -#include "types_nw4r.h" - -#include +#ifndef EGG_AUDIO_ARC_PLAYER_MGR_H +#define EGG_AUDIO_ARC_PLAYER_MGR_H +#include + +#include + +#include +#include namespace EGG { + class ArcPlayer { public: enum SARC_STORAGE { - STORAGE_NONE, - STORAGE_DVD, - STORAGE_NAND, - STORAGE_CNT, - STORAGE_MEM + SARC_STORAGE_NONE, + SARC_STORAGE_DVD, + SARC_STORAGE_NAND, + SARC_STORAGE_CNT, + SARC_STORAGE_MEM }; - ArcPlayer(nw4r::snd::SoundHeap*); +public: + explicit ArcPlayer(nw4r::snd::SoundHeap* pHeap); virtual ~ArcPlayer(); // at 0x8 - bool setSteamBlocks(u32); - void stopAllSound(); - - u32 changeNameToId(const char* name) { - return mOpenSndArchive->ConvertLabelStringToSoundId(name); - } - nw4r::snd::SoundArchivePlayer* getPlayer() { - return mActiveSndArchivePlayer; - } - - virtual UNKTYPE* openArchive(const char*, nw4r::snd::SoundHeap*, - SARC_STORAGE, CNTHandle*); // at 0xC - virtual UNKTYPE* openDvdArchive(const char*, - nw4r::snd::SoundHeap*); // at 0x10 - virtual UNKTYPE* openNandArchive(const char*, - nw4r::snd::SoundHeap*); // at 0x14 - virtual UNKTYPE* openCntArchive(const char*, CNTHandle*, - nw4r::snd::SoundHeap*); // at 0x18 - virtual UNKTYPE* setupMemoryArchive(const void*, - nw4r::snd::SoundHeap*); // at 0x1C - - virtual UNKTYPE* setupMemoryArchive(const void* p, - nw4r::snd::SoundHeap* heap, - s32) // at 0x20 - { - return setupMemoryArchive(p, heap); - } - - virtual UNKTYPE closeArchive(); // at 0x24 - virtual bool loadGroup(unsigned int, nw4r::snd::SoundHeap*, u32); // at 0x28 - virtual bool loadGroup(int, nw4r::snd::SoundHeap*, u32); // at 0x2C - virtual bool loadGroup(const char*, nw4r::snd::SoundHeap*, u32); // at 0x30 - virtual void calc(); // at 0x34 - virtual bool startSound(nw4r::snd::SoundHandle* handle, u32 id) // at 0x38 - { - return mActiveSndArchivePlayer->StartSound(handle, id); - } + virtual nw4r::snd::SoundArchivePlayer* + openArchive(const char* pPath, nw4r::snd::SoundHeap* pHeap, + SARC_STORAGE storage, + CNTHandle* pHandle); // at 0xC + + virtual nw4r::snd::SoundArchivePlayer* + openDvdArchive(const char* pPath, + nw4r::snd::SoundHeap* pHeap); // at 0x10 + + virtual nw4r::snd::SoundArchivePlayer* + openNandArchive(const char* pPath, + nw4r::snd::SoundHeap* pHeap); // at 0x14 + + virtual nw4r::snd::SoundArchivePlayer* + openCntArchive(const char* pPath, CNTHandle* pHandle, + nw4r::snd::SoundHeap* pHeap); // at 0x18 + + virtual nw4r::snd::SoundArchivePlayer* + setupMemoryArchive(const void* pPath, + nw4r::snd::SoundHeap* pHeap); // at 0x1C + virtual nw4r::snd::SoundArchivePlayer* + setupMemoryArchive(const void* pBinary, nw4r::snd::SoundHeap* pHeap, + s32 /* arg2 */) { + return setupMemoryArchive(pBinary, pHeap); + } // at 0x20 + + virtual void closeArchive(); // at 0x24 + + virtual bool loadGroup(unsigned int id, nw4r::snd::SoundHeap* pHeap, + u32 blockSize); // at 0x28 + virtual bool loadGroup(int id, nw4r::snd::SoundHeap* pHeap, + u32 blockSize); // at 0x2C + virtual bool loadGroup(const char* pName, nw4r::snd::SoundHeap* pHeap, + u32 blockSize); // at 0x30 + + virtual void calc(); // at 0x34 + + virtual bool startSound(nw4r::snd::SoundHandle* pHandle, u32 id) { + return mPlayer->StartSound(pHandle, id); + } // at 0x38 + virtual bool startSound(nw4r::snd::SoundHandle* pHandle, unsigned int id) { + return mPlayer->StartSound(pHandle, id); + } // at 0x3C + virtual bool startSound(nw4r::snd::SoundHandle* pHandle, + const char* pName) { + + u32 id = nw4r::snd::SoundArchive::INVALID_ID; + if (mArchive != NULL) { + id = changeNameToId(pName); + } + + return mPlayer->StartSound(pHandle, id); + } // at 0x40 + + virtual bool prepareSound(nw4r::snd::SoundHandle* pHandle, u32 id) { + return mPlayer->PrepareSound(pHandle, id); + } // at 0x44 + virtual bool prepareSound(nw4r::snd::SoundHandle* pHandle, + unsigned int id) { + return mPlayer->PrepareSound(pHandle, id); + } // at 0x48 + virtual bool prepareSound(nw4r::snd::SoundHandle* pHandle, + const char* pName) { + u32 id = nw4r::snd::SoundArchive::INVALID_ID; + if (mArchive != NULL) { + id = changeNameToId(pName); + } + + return mPlayer->PrepareSound(pHandle, id); + } // at 0x4C + + virtual bool holdSound(nw4r::snd::SoundHandle* pHandle, u32 id) { + return mPlayer->HoldSound(pHandle, id); + } // at 0x50 + virtual bool holdSound(nw4r::snd::SoundHandle* pHandle, unsigned int id) { + return mPlayer->HoldSound(pHandle, id); + } // at 0x54 + virtual bool holdSound(nw4r::snd::SoundHandle* pHandle, const char* pName) { + u32 id = nw4r::snd::SoundArchive::INVALID_ID; + if (mArchive != NULL) { + id = changeNameToId(pName); + } + + return mPlayer->HoldSound(pHandle, id); + } // at 0x58 + + bool setSteamBlocks(u32 numBlocks); + void stopAllSound(); - virtual bool startSound(nw4r::snd::SoundHandle* handle, - unsigned int id) // at 0x3C - { - return ArcPlayer::startSound(handle, (u32)id); + u32 changeNameToId(const char* pName) { + return mArchive->ConvertLabelStringToSoundId(pName); } - - virtual bool startSound(nw4r::snd::SoundHandle* handle, - const char* name) // at 0x40 - { - u32 id = -1; - if (mOpenSndArchive) - id = changeNameToId(name); - - return ArcPlayer::startSound(handle, id); + const char* changeIdToName(u32 id) { + return mArchive->GetSoundLabelString(id); } - virtual bool prepareSound(nw4r::snd::SoundHandle* handle, u32 id) // at 0x44 - { - return mActiveSndArchivePlayer->PrepareSound(handle, id); + const char* getSoundWithOffsetDirect(const char* pName, u32 offset) { + u32 id = changeNameToId(pName); + return changeIdToName(id + offset); } - virtual bool prepareSound(nw4r::snd::SoundHandle* handle, - unsigned int id) // at 0x48 - { - return ArcPlayer::prepareSound(handle, (u32)id); + nw4r::snd::SoundArchive& getSoundArchive() { + return *mArchive; } - - virtual bool prepareSound(nw4r::snd::SoundHandle* handle, - const char* name) // at 0x4C - { - u32 id = -1; - if (mOpenSndArchive) - id = changeNameToId(name); - - return ArcPlayer::prepareSound(handle, id); + nw4r::snd::SoundArchivePlayer& getPlayer() { + return *mPlayer; } - virtual bool holdSound(nw4r::snd::SoundHandle* handle, u32 id) // at 0x50 - { - return mActiveSndArchivePlayer->HoldSound(handle, id); - } +protected: + bool mIsOpeningArchive; // at 0x4 + bool mIsLoadingGroup; // at 0x5 - virtual bool holdSound(nw4r::snd::SoundHandle* handle, - unsigned int id) // at 0x54 - { - return ArcPlayer::holdSound(handle, (u32)id); - } + nw4r::snd::SoundArchive* mArchive; // at 0x8 + nw4r::snd::DvdSoundArchive mDvdSoundArchive; // at 0xC + nw4r::snd::NandSoundArchive mNandSoundArchive; // at 0x198 + nw4r::snd::MemorySoundArchive mMemorySoundArchive; // at 0x374 - virtual bool holdSound(nw4r::snd::SoundHandle* handle, - const char* name) // at 0x58 - { - u32 id = -1; - if (mOpenSndArchive) - id = changeNameToId(name); + nw4r::snd::SoundArchivePlayer mSoundArchivePlayer; // at 0x4C4 + nw4r::snd::SoundArchivePlayer* mPlayer; // at 0x5A4 - return ArcPlayer::holdSound(handle, id); - } - -private: - bool mIsOpeningArchive; // at 0x4 - bool mIsLoadingGroup; // at 0x5 - nw4r::snd::SoundArchive* mOpenSndArchive; // at 0x8 - nw4r::snd::DvdSoundArchive mDvdSndArchive; // at 0xC - nw4r::snd::NandSoundArchive mNandSndArchive; // at 0x198 - nw4r::snd::MemorySoundArchive mMemorySndArchive; // at 0x374 - nw4r::snd::SoundArchivePlayer mSndArchivePlayer; // at 0x4C4 - nw4r::snd::SoundArchivePlayer* mActiveSndArchivePlayer; // at 0x5A4 - nw4r::snd::SoundHeap* mSoundHeap; // at 0x5A8 - SARC_STORAGE mStorage; // at 0x5AC - u32 mSteamBlocks; // at 0x5B0 + nw4r::snd::SoundHeap* mSoundHeap; // at 0x5A8 + SARC_STORAGE mStorage; // at 0x5AC + u32 mStreamBlocks; // at 0x5B0 }; + }; // namespace EGG #endif diff --git a/include/egg/audio/eggAudioExpMgr.h b/include/egg/audio/eggAudioExpMgr.h index 5b5835a..2baf217 100644 --- a/include/egg/audio/eggAudioExpMgr.h +++ b/include/egg/audio/eggAudioExpMgr.h @@ -1,15 +1,101 @@ -#ifndef EGG_AUDIO_AUDIO_EXP_MGR_H -#define EGG_AUDIO_AUDIO_EXP_MGR_H -#include "eggAudioFxMgr.h" -#include "eggAudioMgr.h" -#include "eggAudioSound3DMgr.h" -#include "types_egg.h" +#ifndef EGG_AUDIO_EXP_MGR_H +#define EGG_AUDIO_EXP_MGR_H +#include + +#include +#include +#include + +#include + +#include + +#include +#include namespace EGG { +/****************************************************************************** + * + * SimpleAudioMgrWithSound3D + * + ******************************************************************************/ +#ifndef __DECOMP_NON_MATCHING +class SimpleAudioMgrWithSound3D + : public SimpleAudioMgr, + public TAudioSound3DMgr { +private: + // Dummy class to instantiate necessary weak functions + virtual ~SimpleAudioMgrWithSound3D(); +}; +#endif + +/****************************************************************************** + * + * SimpleAudioMgrWithFx + * + ******************************************************************************/ +#ifndef __DECOMP_NON_MATCHING +class SimpleAudioMgrWithFx : public SimpleAudioMgr, public AudioFxMgr { +private: + // Dummy class to instantiate necessary weak functions + virtual ~SimpleAudioMgrWithFx(); +}; +#endif + +/****************************************************************************** + * + * ExpAudioMgr + * + ******************************************************************************/ class ExpAudioMgr : public SimpleAudioMgr, - public TAudioSound3DMgr<4>, - public AudioFxMgr {}; + public TAudioSound3DMgr, + public AudioFxMgr { +public: + struct ExpAudioMgrArg : SimpleAudioMgrArg, + TAudioSound3DMgrArg, + AudioFxMgrArg { + + // TODO: How is this calculated? + static const u32 DEFAULT_FX_HEAP_SIZE = 0x25800; + + ExpAudioMgrArg(); + }; + +public: + ExpAudioMgr(); + virtual ~ExpAudioMgr(); // at 0x8 + + virtual void initialize(Arg* pArg); // at 0x8 + + virtual nw4r::snd::SoundArchivePlayer* + setupMemoryArchive(const void* pPath, + nw4r::snd::SoundHeap* pHeap); // at 0x1C + + virtual void closeArchive(); // at 0x24 + + virtual nw4r::snd::SoundArchivePlayer* + openArchive(const char* pPath, nw4r::snd::SoundHeap* pHeap, + SARC_STORAGE storage, CNTHandle* pHandle); // at 0xC + + virtual nw4r::snd::SoundArchivePlayer* + setupMemoryArchive(const void* pBinary, nw4r::snd::SoundHeap* pHeap, + s32 /* arg2 */) { + return setupMemoryArchive(pBinary, pHeap); + } // at 0x20 + + virtual bool loadState(s32 id) { +#line 171 + // "When the archive is open, it cannot be returned to level 1 state." + EGG_ASSERT_MSG(id > 1 || mPlayer->IsAvailable() != true, + "アーカイブオープン時はレベル1のステートには戻せません。"); + + return SoundHeapMgr::loadState(id); + } // at 0x8 + +private: + ; +}; } // namespace EGG diff --git a/include/egg/audio/eggAudioFxMgr.h b/include/egg/audio/eggAudioFxMgr.h index f1d76ff..9972513 100644 --- a/include/egg/audio/eggAudioFxMgr.h +++ b/include/egg/audio/eggAudioFxMgr.h @@ -1,37 +1,108 @@ -#ifndef EGG_AUDIO_AUDIO_FX_MGR_H -#define EGG_AUDIO_AUDIO_FX_MGR_H -#include "types_egg.h" -#include +#ifndef EGG_AUDIO_FX_MGR_H +#define EGG_AUDIO_FX_MGR_H +#include + +#include namespace EGG { +// Forward declarations +class ExpHeap; + +/****************************************************************************** + * + * AudioFx + * + ******************************************************************************/ class AudioFx { +public: + enum Type { + TYPE_AXFX_NONE, + TYPE_AXFX_REVERBHI, + TYPE_AXFX_REVERBHI_DPL2, + TYPE_AXFX_REVERBSTD, + TYPE_AXFX_CHORUS, + TYPE_AXFX_DELAY, + + TYPE_AXFX_MAX + }; + public: AudioFx(); ~AudioFx(); - void init(nw4r::snd::AuxBus, void*, u32); + + void init(nw4r::snd::AuxBus bus, void* pHeapBuffer, u32 heapSize); + bool create(u32 fxType, const void* pParam); void destroy(); private: - UNKWORD WORD_0x0; - nw4r::snd::AuxBus mAuxBus; // at 0x4 - UNKWORD WORD_0x8; - UNKWORD WORD_0xC; - ExpHeap* mExpHeap; // at 0x10 - UNKWORD WORD_0x14; + // clang-format off + bool createFxReverbHi(const nw4r::snd::FxReverbHi::ReverbHiParam* pParam); + bool createFxReverbHiDpl2(const nw4r::snd::FxReverbHiDpl2::ReverbHiDpl2Param* pParam); + bool createFxChorus(const nw4r::snd::FxChorus::ChorusParam* pParam); + bool createFxDelay(const nw4r::snd::FxDelay::DelayParam* pParam); + // clang-format on + +private: + nw4r::snd::FxBase* mFxBase; // at 0x0 + nw4r::snd::AuxBus mAuxBus; // at 0x4 + const void* mParam; // at 0x8 + Type mType; // at 0xC + ExpHeap* mHeap; // at 0x10 + u8* mWorkBuffer; // at 0x14 }; +/****************************************************************************** + * + * AudioFxMgr + * + ******************************************************************************/ class AudioFxMgr { public: + /************************************************************************** + * AudioFxMgrArg + **************************************************************************/ struct AudioFxMgrArg { - u32 neededAllocSize[nw4r::snd::AUX_BUS_NUM]; // at 0x0 + u32 heapSize[nw4r::snd::AUX_BUS_NUM]; // at 0x0 }; +public: AudioFxMgr(); ~AudioFxMgr(); + bool initializeFx(nw4r::snd::SoundHeap* pHeap, AudioFxMgrArg* pArg); + + bool setFxReverbHi(nw4r::snd::AuxBus bus, + const nw4r::snd::FxReverbHi::ReverbHiParam* pParam); + + bool setFxReverbHiDpl2( + nw4r::snd::AuxBus bus, + const nw4r::snd::FxReverbHiDpl2::ReverbHiDpl2Param* pParam); + + bool setFxChorus(nw4r::snd::AuxBus bus, + const nw4r::snd::FxChorus::ChorusParam* pParam); + + bool setFxDelay(nw4r::snd::AuxBus bus, + const nw4r::snd::FxDelay::DelayParam* pParam); + + void clearFx(nw4r::snd::AuxBus bus); + + // clang-format off + static const nw4r::snd::FxReverbHi::ReverbHiParam* getDefaultFxReverbHi(); + static const nw4r::snd::FxReverbHiDpl2::ReverbHiDpl2Param* getDefaultFxReverbHiDpl2(); + static const nw4r::snd::FxChorus::ChorusParam* getDefaultFxChorus(); + static const nw4r::snd::FxDelay::DelayParam* getDefaultFxDelay(); + // clang-format on + private: AudioFx mAudioFx[nw4r::snd::AUX_BUS_NUM]; // at 0x0 + + // clang-format off + static const nw4r::snd::FxReverbHi::ReverbHiParam sDefaultFxReverbHi; + static const nw4r::snd::FxReverbHiDpl2::ReverbHiDpl2Param sDefaultFxReverbHiDpl2; + static const nw4r::snd::FxChorus::ChorusParam sDefaultFxChorus; + static const nw4r::snd::FxDelay::DelayParam sDefaultFxDelay; + // clang-format on }; } // namespace EGG diff --git a/include/egg/audio/eggAudioHeapMgr.h b/include/egg/audio/eggAudioHeapMgr.h index 1934e16..c87660b 100644 --- a/include/egg/audio/eggAudioHeapMgr.h +++ b/include/egg/audio/eggAudioHeapMgr.h @@ -1,49 +1,98 @@ #ifndef EGG_AUDIO_HEAP_MGR_H #define EGG_AUDIO_HEAP_MGR_H -#include "snd_SoundHeap.h" -#include "types_egg.h" +#include + +#include #include namespace EGG { + +// Forward declarations +class Allocator; +class Heap; + class SoundHeapMgr { public: - SoundHeapMgr() : mHeap() { - OSInitMessageQueue(&mMesgQueue1, &mMesg1, 4); - OSInitMessageQueue(&mMesgQueue2, &mMesg2, 4); - OSInitMessageQueue(&mMesgQueue3, &mMesg3, 4); + SoundHeapMgr() { + // @bug Forgot to initialize GetLevel message queue??? + OSInitMessageQueue(&mLoadStateMesgQueue, mLoadStateMesgBuffer, + ARRAY_SIZE(mLoadStateMesgBuffer)); + + OSInitMessageQueue(&mSaveStateMesgQueue, mSaveStateMesgBuffer, + ARRAY_SIZE(mSaveStateMesgBuffer)); + + OSInitMessageQueue(&mResponseMesgQueue, mResponseMesgBuffer, + ARRAY_SIZE(mResponseMesgBuffer)); } ~SoundHeapMgr() { destroySoundHeap(); } - // TO-DO: Implement these weak funcs - virtual UNKWORD loadState(s32); // at 0x8 - virtual UNKWORD getCurrentLevel(); // at 0xC - virtual void saveState(); // at 0x10 + virtual bool loadState(s32 id) { + s32 level = mHeap.GetCurrentLevel(); - void createSoundHeap(Heap*, u32); - void createSoundHeap(Allocator*, u32); - void destroySoundHeap(); + if (id > 0 && level >= id) { + mHeap.LoadState(id); + return true; + } + + return false; + } // at 0x8 + + virtual s32 getCurrentLevel() { + return mHeap.GetCurrentLevel(); + } // at 0xC + + virtual void stateProc() { + OSMessage mesg; + + if (OSReceiveMessage(&mLoadStateMesgQueue, &mesg, 0)) { + s32 id = reinterpret_cast(mesg); + OSMessage result = reinterpret_cast(loadState(id)); + OSSendMessage(&mResponseMesgQueue, result, 0); + } + + if (OSReceiveMessage(&mSaveStateMesgQueue, &mesg, 0)) { + OSMessage result = reinterpret_cast(saveState()); + OSSendMessage(&mResponseMesgQueue, result, 0); + } - nw4r::snd::SoundHeap* getSoundHeap() { - return &mHeap; + if (OSReceiveMessage(&mGetLevelMesgQueue, &mesg, 0)) { + OSMessage result = reinterpret_cast(getCurrentLevel()); + OSSendMessage(&mResponseMesgQueue, result, 0); + } + } // at 0x10 + + s32 saveState() { + return mHeap.SaveState(); + } + + nw4r::snd::SoundHeap& getSoundHeap() { + return mHeap; } -private: + void createSoundHeap(Heap* pHeap, u32 size); + void createSoundHeap(Allocator* pAllocator, u32 size); + void destroySoundHeap(); + +protected: nw4r::snd::SoundHeap mHeap; // at 0x4 - u8 UNK_0x38[0x68 - 0x38]; - OSMessageQueue mMesgQueue1; // at 0x68 - OSMessage mMesg1; // at 0x88 - u8 UNK_0x8C[0x98 - 0x8C]; - OSMessageQueue mMesgQueue2; // at 0x98 - OSMessage mMesg2; // at 0xB8 - u8 UNK_0xBC[0xC8 - 0xBC]; - OSMessageQueue mMesgQueue3; // at 0xC8 - OSMessage mMesg3; // at 0xE8 - u8 UNK_0xEC[0xF8 - 0xEC]; + + OSMessageQueue mGetLevelMesgQueue; // at 0x30 + OSMessage mGetLevelMesgBuffer[4]; // at 0x50 + + OSMessageQueue mLoadStateMesgQueue; // at 0x60 + OSMessage mLoadStateMesgBuffer[4]; // at 0x80 + + OSMessageQueue mSaveStateMesgQueue; // at 0x90 + OSMessage mSaveStateMesgBuffer[4]; // at 0xB0 + + OSMessageQueue mResponseMesgQueue; // at 0xC0 + OSMessage mResponseMesgBuffer[4]; // at 0xE0 }; + } // namespace EGG #endif diff --git a/include/egg/audio/eggAudioMgr.h b/include/egg/audio/eggAudioMgr.h index 02e36ab..dc36533 100644 --- a/include/egg/audio/eggAudioMgr.h +++ b/include/egg/audio/eggAudioMgr.h @@ -1,26 +1,111 @@ -#ifndef EGG_AUDIO_AUDIO_MGR_H -#define EGG_AUDIO_AUDIO_MGR_H -#include "eggAudioArcPlayerMgr.h" -#include "eggAudioHeapMgr.h" -#include "eggAudioSystem.h" -#include "eggIAudioMgr.h" -#include "types_egg.h" +#ifndef EGG_AUDIO_MGR_H +#define EGG_AUDIO_MGR_H +#include + +#include +#include +#include namespace EGG { +// Forward declarations +class Heap; + +/****************************************************************************** + * + * IAudioMgr + * + ******************************************************************************/ +class IAudioMgr { +public: + /************************************************************************** + * Arg + **************************************************************************/ + struct Arg { + Heap* pHeap; // at 0x0 + UNKWORD WORD_0x4; + s32 soundThreadPrio; // at 0x8 + s32 dvdThreadPrio; // at 0xC + u32 soundThreadStackSize; // at 0x10 + u32 dvdThreadStackSize; // at 0x14 + + Arg() { + pHeap = NULL; + + // clang-format off + soundThreadPrio = nw4r::snd::SoundSystem::DEFAULT_SOUND_THREAD_PRIORITY; + dvdThreadPrio = nw4r::snd::SoundSystem::DEFAULT_DVD_THREAD_PRIORITY; + // clang-format on + + WORD_0x4 = 0; + + soundThreadStackSize = 0; + dvdThreadStackSize = 0; + } + }; + +public: + virtual void initialize(Arg* pArg) {} // at 0x8 + virtual void calc() = 0; // at 0xC + +protected: + bool mIsInitialized; // at 0x4 +}; + +/****************************************************************************** + * + * SimpleAudioMgr + * + ******************************************************************************/ class SimpleAudioMgr : public IAudioMgr, public SoundHeapMgr, public ArcPlayer, public AudioSystem { public: + /************************************************************************** + * SimpleAudioMgrArg + **************************************************************************/ struct SimpleAudioMgrArg : IAudioMgr::Arg { + // TODO: How is this calculated? + static const u32 DEFAULT_SOUND_HEAP_SIZE = 0x8CA000; + + u32 streamBlocks; // at 0x18 + u32 soundHeapSize; // at 0x1C + SimpleAudioMgrArg(); }; +public: SimpleAudioMgr(); - virtual ~SimpleAudioMgr(); // at 0x80 - virtual void initialize(IAudioMgr::Arg*); // at 0x8 - virtual void calc(); // at 0xC + virtual ~SimpleAudioMgr(); // at 0x8 + + virtual void initialize(Arg* pArg); // at 0x8 + virtual void calc(); // at 0xC + + virtual nw4r::snd::SoundArchivePlayer* + openDvdArchive(const char* pPath, + nw4r::snd::SoundHeap* pHeap); // at 0x10 + + virtual nw4r::snd::SoundArchivePlayer* + openNandArchive(const char* pPath, + nw4r::snd::SoundHeap* pHeap); // at 0x14 + + virtual nw4r::snd::SoundArchivePlayer* + openCntArchive(const char* pPath, CNTHandle* pHandle, + nw4r::snd::SoundHeap* pHeap); // at 0x18 + + virtual nw4r::snd::SoundArchivePlayer* + setupMemoryArchive(const void* pPath, + nw4r::snd::SoundHeap* pHeap); // at 0x1C + + virtual void closeArchive(); // at 0x24 + + virtual bool loadGroup(unsigned int id, nw4r::snd::SoundHeap* pHeap, + u32 blockSize); // at 0x28 + virtual bool loadGroup(int id, nw4r::snd::SoundHeap* pHeap, + u32 blockSize); // at 0x2C + virtual bool loadGroup(const char* pName, nw4r::snd::SoundHeap* pHeap, + u32 blockSize); // at 0x30 }; } // namespace EGG diff --git a/include/egg/audio/eggAudioSound3DMgr.h b/include/egg/audio/eggAudioSound3DMgr.h deleted file mode 100644 index c9a4cbd..0000000 --- a/include/egg/audio/eggAudioSound3DMgr.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef EGG_AUDIO_AUDIO_SOUND_3D_MGR_H -#define EGG_AUDIO_AUDIO_SOUND_3D_MGR_H -#include -#include - -namespace EGG { - -template class TAudioSound3DMgr { -private: - nw4r::snd::Sound3DManager mManagers[N]; - nw4r::snd::Sound3DListener mListeners[N]; -}; - -} // namespace EGG - -#endif diff --git a/include/egg/audio/eggAudioSystem.h b/include/egg/audio/eggAudioSystem.h index f4217ab..e78d78c 100644 --- a/include/egg/audio/eggAudioSystem.h +++ b/include/egg/audio/eggAudioSystem.h @@ -1,20 +1,49 @@ -#ifndef EGG_AUDIO_AUDIO_SYSTEM_H -#define EGG_AUDIO_AUDIO_SYSTEM_H -#include "types_egg.h" +#ifndef EGG_AUDIO_SYSTEM_H +#define EGG_AUDIO_SYSTEM_H +#include namespace EGG { -struct AudioSystem { + +class AudioSystem { +public: + enum EResetStatus { + RESET_STATUS_NONE, + RESET_STATUS_QUEUED, + RESET_STATUS_FINISH, + }; + + enum EShutDownStatus { + SHUTDOWN_STATUS_NONE, + SHUTDOWN_STATUS_QUEUED, + SHUTDOWN_STATUS_FINISH, + }; + +public: + static AudioSystem* instance() { + return sInstanse; + } + + void calc(); + + EResetStatus getResetStatus() { + return mResetStatus; + } + EShutDownStatus getShutDownStatus() { + return mShutDownStatus; + } + +protected: AudioSystem(); ~AudioSystem(); - void calc(); +private: f32 FLOAT_0x0; - UNKWORD WORD_0x4; - UNKWORD WORD_0x8; - UNKWORD WORD_0xC; + EResetStatus mResetStatus; // at 0x4 + EShutDownStatus mShutDownStatus; // at 0x8 static AudioSystem* sInstanse; }; + } // namespace EGG #endif diff --git a/include/egg/audio/eggIAudioMgr.h b/include/egg/audio/eggIAudioMgr.h deleted file mode 100644 index 6c1bbe4..0000000 --- a/include/egg/audio/eggIAudioMgr.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef EGG_AUDIO_I_AUDIO_MGR_H -#define EGG_AUDIO_I_AUDIO_MGR_H -#include "types_egg.h" - -namespace EGG { -class IAudioMgr { -public: - struct Arg { - Arg() { - mHeap = NULL; - WORD_0x8 = 4; - WORD_0xC = 3; - WORD_0x4 = 0; - WORD_0x10 = 0; - WORD_0x14 = 0; - WORD_0x18 = 1; - WORD_0x1C = 0x8CA000; - } - - Heap* mHeap; - UNKWORD WORD_0x4; - s32 WORD_0x8; - s32 WORD_0xC; - UNKWORD WORD_0x10; - UNKWORD WORD_0x14; - UNKWORD WORD_0x18; - u32 WORD_0x1C; - }; - - virtual void initialize(Arg*) {} - virtual void calc() = 0; - -protected: - bool mIsInitialized; // at 0x4 -}; -} // namespace EGG - -#endif diff --git a/include/egg/core.h b/include/egg/core.h index 628c150..975f30d 100644 --- a/include/egg/core.h +++ b/include/egg/core.h @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -16,21 +15,22 @@ #include #include #include -#include #include #include #include -#include #include #include #include #include #include +#include +#include #include #include #include #include #include +#include #include #include diff --git a/include/egg/core/eggAllocator.h b/include/egg/core/eggAllocator.h index 269ec68..7cf159a 100644 --- a/include/egg/core/eggAllocator.h +++ b/include/egg/core/eggAllocator.h @@ -1,16 +1,23 @@ #ifndef EGG_CORE_ALLOCATOR_H #define EGG_CORE_ALLOCATOR_H -#include "types_egg.h" +#include -#include +#include namespace EGG { -struct Allocator : MEMAllocator { - Allocator(Heap*, s32); + +// Forward declarations +class Heap; + +class Allocator : public MEMAllocator { +public: + Allocator(Heap* pHeap, s32 align = 32); virtual ~Allocator(); - virtual void* alloc(u32); - virtual void free(void*); + + virtual void* alloc(u32 size); + virtual void free(void* pBlock); }; + } // namespace EGG #endif diff --git a/include/egg/core/eggArchive.h b/include/egg/core/eggArchive.h index b5cd2c3..67bf620 100644 --- a/include/egg/core/eggArchive.h +++ b/include/egg/core/eggArchive.h @@ -1,54 +1,70 @@ #ifndef EGG_CORE_ARCHIVE_H #define EGG_CORE_ARCHIVE_H -#include "eggAssert.h" -#include "eggDisposer.h" -#include "types_egg.h" -#include "ut_list.h" +#include -#include -#include +#include + +#include + +#include + +#include namespace EGG { -struct Archive : Disposer { - struct FileInfo { - u32 offset; - u32 length; - }; - inline Archive() { - INT_0x14 = 1; - INT_0x10 = 0; - memset(&mHandle, 0, sizeof(mHandle)); +// Forward declarations +class Heap; - if (!sIsArchiveListInitialized) { - nw4r::ut::List_Init(&sArchiveList, offsetof(Archive, mNode)); - sIsArchiveListInitialized = true; - } +class Archive : public Disposer { +public: + enum MountType { MOUNT_TYPE_NONE, MOUNT_TYPE_MEM, MOUNT_TYPE_FST }; - appendList(this); - } + class FileInfo { + friend class Archive; - inline static void appendList(Archive* p) { - nw4r::ut::List_Append(&sArchiveList, p); - } + public: + FileInfo() : mStartOffset(0), mLength(0) {} - inline static void removeList(Archive* p) { - nw4r::ut::List_Remove(&sArchiveList, p); - } + u32 getStartOffset() const { + return mStartOffset; + } + u32 getLength() const { + return mLength; + } + private: + u32 mStartOffset; // at 0x0 + u32 mLength; // at 0x4 + }; + +public: + static Archive* mount(void* pArcBinary, Heap* pHeap, int align); + static Archive* findArchive(void* pArcBinary); + + Archive(); virtual ~Archive(); // at 0x8 - static Archive* mount(void*, Heap*, int); - void* getFile(const char*, FileInfo*); - bool initHandle(void*); // inlined - int INT_0x10; - int INT_0x14; + void* getFile(const char* pPath, FileInfo* pInfo); + +private: + bool initHandle(void* pArcBinary); + + static void appendList(Archive* pArchive); + static void removeList(Archive* pArchive); + +private: + MountType mMountType; // at 0x10 + u32 mRefCount; // at 0x14 ARCHandle mHandle; // at 0x18 - nw4r::ut::Link mNode; // at 0x34 +public: + NW4R_UT_LIST_LINK_DECL(); // at 0x34 + +private: static nw4r::ut::List sArchiveList; static bool sIsArchiveListInitialized; }; + } // namespace EGG #endif diff --git a/include/egg/core/eggAsyncDisplay.h b/include/egg/core/eggAsyncDisplay.h index abc808c..f1ab5ec 100644 --- a/include/egg/core/eggAsyncDisplay.h +++ b/include/egg/core/eggAsyncDisplay.h @@ -1,45 +1,56 @@ #ifndef EGG_CORE_ASYNC_DISPLAY_H #define EGG_CORE_ASYNC_DISPLAY_H -#include "eggDisplay.h" -#include "types_egg.h" -#include "types_nw4r.h" +#include -#include -#include +#include + +#include + +#include namespace EGG { -struct AsyncDisplay : Display { - AsyncDisplay(u8); + +class AsyncDisplay : public Display { +public: + explicit AsyncDisplay(u8 frameRate); + + virtual void beginFrame(); // at 0x8 + virtual void beginRender(); // at 0xC + virtual void endRender(); // at 0x10 + + virtual u32 getTickPerFrame(); // at 0x18 + + void postVRetrace(); + void clearEFB(); + +private: + enum SyncMode { + SYNC_MODE_NONE, + SYNC_MODE_NTSC, + }; + +private: + void calcS(); void syncTick(); - void clearEFB(u16, u16, u16, u16, u16, u16, nw4r::ut::Color); - virtual void beginFrame(); - virtual void beginRender(); - virtual void endRender(); - virtual u32 getTickPerFrame(); - - char UNK_0x28[0x30]; - OSThreadQueue mThreadQueue; // at 0x58 - UNKWORD WORD_0x60; - f32 FLOAT_0x64; - UNKWORD WORD_0x68; - UNKWORD WORD_0x6C; - u8 BYTE_0x70; - char UNK_0x71[3]; - u32 WORD_0x74; - UNKWORD WORD_0x78; - s32 OSTICK_0x7C; - s32 OSTICK_0x80; + + void clearEFB(u16 fbWidth, u16 fbHeight, u16 x, u16 y, u16 width, + u16 height, nw4r::ut::Color color); + +private: + OSAlarm mSyncAlarm; // at 0x28 + OSThreadQueue mSyncQueue; // at 0x58 + SyncMode mSyncMode; // at 0x60 + + f32 mTimeScale; // at 0x64 + u32 mPrevTickCount; // at 0x68 + u32 mTickCount; // at 0x6C + u8 mFrameRateNTSC; // at 0x70 + u32 mTickPerRetraceNTSC; // at 0x74 + u32 mTickPerRetrace; // at 0x78 + s32 mTickCostTick; // at 0x7C + s32 mPrevTickTick; // at 0x80 }; -} // namespace EGG -#ifdef __cplusplus -extern "C" { -#endif -void PostRetraceCallback(u32 retraceCount); -void DrawDoneCallback(void); -static EGG::AsyncDisplay* spSelector; -#ifdef __cplusplus -} -#endif +} // namespace EGG #endif diff --git a/include/egg/core/eggBitFlag.h b/include/egg/core/eggBitFlag.h index 6e1d1ea..b3c9d6b 100644 --- a/include/egg/core/eggBitFlag.h +++ b/include/egg/core/eggBitFlag.h @@ -1,55 +1,116 @@ #ifndef EGG_CORE_BIT_FLAG_H #define EGG_CORE_BIT_FLAG_H -#include "types_egg.h" +#include namespace EGG { -// NOTE: index is LSB -template struct TBitFlag { - T value; - inline void makeAllZero() { - value = T(); - } +template struct is_flag_type { + static const bool value = false; +}; + +template <> struct is_flag_type { + static const bool value = true; +}; +template <> struct is_flag_type { + static const bool value = true; +}; +template <> struct is_flag_type { + static const bool value = true; +}; +template <> struct is_flag_type { + static const bool value = true; +}; - inline TBitFlag() { +template struct flag_type_chk; +template <> struct flag_type_chk {}; + +template class TBitFlag { +public: + TBitFlag() { makeAllZero(); } - inline T makeMask(u8 bit) const { - return 1 << bit; + TBitFlag(T value) : mValue(value) {} + + operator T() const { + return mValue; } - inline bool on(T mask) const { - return value & mask; + void makeAllZero() { + mValue = static_cast(0); + } + bool isZero() const { + return mValue == 0; } - inline void set(T mask) { - value |= mask; + T getDirect() const { + return mValue; + } + void setDirect(T value) { + mValue = value; } - inline void reset(T mask) { - value &= ~mask; + /****************************************************************************** + * Bit mask operations + ******************************************************************************/ + void set(T mask) { + mValue |= mask; + } + void reset(T mask) { + mValue &= ~mask; } - inline bool onBit(u8 bit) const { - return on(makeMask(bit)); + void change(T mask, bool on) { + if (on) { + set(mask); + } else { + reset(mask); + } } - inline void setBit(u8 bit) { - set(makeMask(bit)); + bool on(T mask) const { + return mValue & mask; + } + bool off(T mask) const { + return !on(mask); } - inline void resetBit(u8 bit) { + /****************************************************************************** + * Bit index operations + ******************************************************************************/ + void setBit(u8 bit) { + set(makeMask(bit)); + } + void resetBit(u8 bit) { reset(makeMask(bit)); } - inline void toggleBit(u8 bit) { - if (!onBit(bit)) - setBit(bit); - else - resetBit(bit); + void changeBit(u8 bit, bool on) { + change(makeMask(bit), on); + } + void toggleBit(u8 bit) { + changeBit(bit, !onBit(bit)); + } + + bool onBit(u8 bit) const { + return on(makeMask(bit)); + } + bool offBit(u8 bit) const { + return off(makeMask(bit)); } + +private: + T makeMask(u8 bit) const { + return 1 << bit; + } + +private: + union { + T mValue; // at 0x0 + flag_type_chk::value> _; + }; }; + } // namespace EGG #endif diff --git a/include/egg/core/eggBuffer.h b/include/egg/core/eggBuffer.h deleted file mode 100644 index 2728525..0000000 --- a/include/egg/core/eggBuffer.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef EGG_CORE_BUFFER_H -#define EGG_CORE_BUFFER_H -#include "eggAssert.h" -#include "eggHeap.h" -#include "types_egg.h" - -namespace EGG { -template class TBuffer { -public: - TBuffer() : mSize(0), mBuffer(NULL) {} - - virtual ~TBuffer() // at 0x8 - { - if (mBuffer != NULL) { - delete[] mBuffer; - mBuffer = NULL; - } - } - - virtual void allocate(int n, int) // at 0xC - { - mSize = n; - mBuffer = new T[n]; - onAllocate(NULL); - } - - virtual void allocate(int n, Heap* heap, int) // at 0x10 - { - mSize = n; - if (heap == NULL) - heap = Heap::getCurrentHeap(); - mBuffer = new (heap, 4) T[mSize]; - onAllocate(heap); - } - - virtual void onAllocate(Heap*) {} // at 0x14 - virtual void errRangeOver() const {} // at 0x18 - - int getSize() const { - return mSize; - } - - T& operator()(int i) { - checkRange(i); - return mBuffer[i]; - } - -private: - void checkRange(int i) const { - if (!isRangeValid(i)) { - errRangeOver(); - EGG_ASSERT_MSG(false, "TBuffer::checkRange %d (0<=x<%d)\n", i, - mSize); - } - } - - bool isRangeValid(int i) const { - return (i >= 0 && i < mSize); - } - -private: - int mSize; // at 0x4 - T* mBuffer; // at 0x8 -}; -} // namespace EGG - -#endif diff --git a/include/egg/core/eggCntFile.h b/include/egg/core/eggCntFile.h index 8261c83..db50e16 100644 --- a/include/egg/core/eggCntFile.h +++ b/include/egg/core/eggCntFile.h @@ -1,56 +1,68 @@ -#ifndef EGG_CORE_CNTFILE_H -#define EGG_CORE_CNTFILE_H -#include "eggAssert.h" -#include "eggFile.h" -#include "types_egg.h" -#include "ut_list.h" - -#include -#include -#include -#include -#include +#ifndef EGG_CORE_CNT_FILE_H +#define EGG_CORE_CNT_FILE_H +#include + +#include + +#include + +#include + +#include +#include namespace EGG { -class CntFile : File { + +class CntFile : public File { public: CntFile(); - virtual ~CntFile(); // at 0x8 - virtual bool open(const char* name) // at 0xC - { + virtual ~CntFile(); // at 0x8 + + virtual bool open(const char* /* pPath */) { #line 57 EGG_ASSERT(false); return false; - } - virtual void close(); // at 0x10 - virtual s32 readData(void*, s32, s32); // at 0x14 - virtual s32 writeData(const void*, s32, s32); // at 0x18 - virtual UNKWORD getFileSize() const { - return contentGetLengthNAND(&mFileInfo); + } // at 0xC + + bool open(const char* pPath, CNTHandle* pHandle); + + virtual void close(); // at 0x10 + + virtual s32 readData(void* pDst, s32 size, s32 offset); // at 0x14 + virtual s32 writeData(const void* pSrc, s32 size, s32 offset); // at 0x18 + + virtual u32 getFileSize() const { + return contentGetLengthNAND(&mAsyncContext.fileInfo); }; // at 0x1C void initiate(); - bool open(const char*, CNTHandle*); private: - bool mIsOpen; // at 0x4 - OSMutex mMutex_0x8; - OSMutex mMutex_0x20; // at 0x20 - UNKWORD WORD_0x38; - CNTFileInfo mFileInfo; // at 0x3C - CNTHandle* mOpenFile; // at 0x4C - CntFile* PTR_0x50; - OSMessageQueue mMesgQueue_0x54; - OSMessage mMesgBuffer_0x74; - OSMessageQueue mMesgQueue_0x78; - OSMessage mMesgBuffer_0x98; - OSThread* mThread; // at 0x9C + struct AsyncContext { + CNTFileInfo fileInfo; // at 0x0 + CNTHandle* pHandle; // at 0x10 + CntFile* pFile; // at 0x14 + }; + +private: + OSMutex mSyncMutex; // at 0x8 + OSMutex mAsyncMutex; // at 0x20 + + OSThread* mAsyncThread; // at 0x38 + AsyncContext mAsyncContext; // at 0x3C + OSMessageQueue mAsyncQueue; // at 0x54 + OSMessage mAsyncBuffer[1]; // at 0x74 + + OSMessageQueue mSyncQueue; // at 0x78 + OSMessage mSyncBuffer[1]; // at 0x98 + OSThread* mSyncThread; // at 0x9C + nw4r::ut::Link mNode; // at 0xA0 - // Unofficial symbol static nw4r::ut::List sCntList; static bool sIsInitialized; }; + } // namespace EGG #endif diff --git a/include/egg/core/eggColorFader.h b/include/egg/core/eggColorFader.h index 25c7d16..8d031ef 100644 --- a/include/egg/core/eggColorFader.h +++ b/include/egg/core/eggColorFader.h @@ -1,42 +1,55 @@ #ifndef EGG_CORE_COLOR_FADER_H #define EGG_CORE_COLOR_FADER_H -#include "eggBitFlag.h" -#include "eggFader.h" -#include "types_egg.h" -#include "ut_Color.h" +#include + +#include +#include + +#include namespace EGG { -struct ColorFader : Fader { - ColorFader(f32, f32, f32, f32, nw4r::ut::Color, EStatus); - void setFrame(u16); - void setColor(nw4r::ut::Color); - virtual void setStatus(EStatus); // at 0x8 - virtual EStatus getStatus() const; // at 0xC - virtual bool fadeIn(); // at 0x10 - virtual bool fadeOut(); // at 0x14 - virtual bool calc(); // at 0x18 - virtual void draw(); // at 0x1C - virtual ~ColorFader(); // at 0x20 - - // Unofficial symbols - f32 getWidth() const { - return mEndX - mStartX; - } - f32 getHeight() const { - return mEndY - mStartY; - } - - EStatus mStatus; // at 0x4 - TBitFlag mFlags; // at 0x8 - u16 mFrame; // Fade length (in frames); at 0xA - u16 mFadeTimer; // at 0xC; Length of current fade - u16 SHORT_0xE; // at 0xE + +class ColorFader : public Fader { +public: + ColorFader(f32 x, f32 y, f32 width, f32 height, + nw4r::ut::Color color = 0x00000000, + EStatus status = STATUS_PREPARE_IN); + + virtual ~ColorFader() {} // at 0x20 + + virtual void setStatus(EStatus status); // at 0x8 + virtual EStatus getStatus() const { + return mStatus; + } // at 0xC + + virtual bool fadeIn(); // at 0x10 + virtual bool fadeOut(); // at 0x14 + + virtual bool calc(); // at 0x18 + virtual void draw(); // at 0x1C + + void setFrame(u16 frame); + void setColor(nw4r::ut::Color color); + +private: + enum { + BIT_FINISH_AFTER_IN, + BIT_FINISH_AFTER_OUT, + BIT_2, + }; + + static const u16 DEFAULT_FRAME = 20; + +private: + EStatus mStatus; // at 0x4 + TBitFlag mFlags; // at 0x8 + u16 mFadeFrame; // at 0xA + u16 mFrame; // at 0xC + u8 UNK_0xE[0x10 - 0xE]; nw4r::ut::Color mColor; // at 0x10 - f32 mStartX; // at 0x14 - f32 mStartY; // at 0x18 - f32 mEndX; // at 0x1C - f32 mEndY; // at 0x20 + nw4r::ut::Rect mSpace; // at 0x14 }; + } // namespace EGG #endif diff --git a/include/egg/core/eggController.h b/include/egg/core/eggController.h index 729cae4..12af3e2 100644 --- a/include/egg/core/eggController.h +++ b/include/egg/core/eggController.h @@ -1,283 +1,420 @@ #ifndef EGG_CORE_CONTROLLER_H #define EGG_CORE_CONTROLLER_H -#include "eggBitFlag.h" -#include "eggBuffer.h" -#include "eggDisposer.h" -#include "eggMatrix.h" -#include "eggVector.h" -#include "types_egg.h" -#include "ut_list.h" +#include + +#include + +#include +#include + +#include #include #include +#include namespace EGG { -enum eCoreDevType { cDEV_0xFD = -3 }; - -enum eButtonType { - cCORE_FSSTICK_NONE = 0x0000, - cCORE_FSSTICK_LEFT = 0x0001, - cCORE_FSSTICK_RIGHT = 0x0002, - cCORE_FSSTICK_DOWN = 0x0004, - cCORE_FSSTICK_UP = 0x0008, - cCORE_FSSTICK_PLUS = 0x0010, - cCORE_FSSTICK_2 = 0x0100, - cCORE_FSSTICK_1 = 0x0200, - cCORE_FSSTICK_B = 0x0400, - cCORE_FSSTICK_A = 0x0800, - cCORE_FSSTICK_MINUS = 0x1000, - cCORE_FSSTICK_HOME = 0x8000, - cCORE_FSSTICK_BUTTONS = 0xF0000 + +// Forward declarations +class CoreController; +class ControllerRumbleMgr; + +enum eCoreDevType { + cDEV_CORE = WPAD_DEV_CORE, + cDEV_FREESTYLE = WPAD_DEV_FREESTYLE, + cDEV_CLASSIC = WPAD_DEV_CLASSIC, + + cDEV_FUTURE = WPAD_DEV_FUTURE, + cDEV_NOT_SUPPORTED = WPAD_DEV_NOT_SUPPORTED, + cDEV_NOT_FOUND = WPAD_DEV_NOT_FOUND, + cDEV_NULL = WPAD_DEV_NULL, + cDEV_UNKNOWN = WPAD_DEV_UNKNOWN, +}; + +enum eCoreButton { + cCORE_BUTTON_UP = 1 << 3, + cCORE_BUTTON_DOWN = 1 << 2, + cCORE_BUTTON_LEFT = 1 << 0, + cCORE_BUTTON_RIGHT = 1 << 1, + + cCORE_BUTTON_PLUS = 1 << 4, + cCORE_BUTTON_MINUS = 1 << 12, + + cCORE_BUTTON_1 = 1 << 9, + cCORE_BUTTON_2 = 1 << 8, + + cCORE_BUTTON_A = 1 << 11, + cCORE_BUTTON_B = 1 << 10, + + cCORE_BUTTON_HOME = 1 << 15, + + cCORE_FSSTICK_UP = 1 << 16, + cCORE_FSSTICK_DOWN = 1 << 17, + cCORE_FSSTICK_LEFT = 1 << 18, + cCORE_FSSTICK_RIGHT = 1 << 19, + + cCORE_FSSTICK_BUTTONS = cCORE_FSSTICK_UP | cCORE_FSSTICK_DOWN | + cCORE_FSSTICK_LEFT | cCORE_FSSTICK_RIGHT }; -struct CoreStatus { +typedef CoreController* (*CoreControllerFactory)(); + +struct CoreControllerConnectArg { + s32 chan; // at 0x0 + s32 result; // at 0x4 +}; + +typedef void (*CoreControllerConnectCallback)( + const CoreControllerConnectArg& rArg); + +struct CoreControllerExtensionArg { + eCoreDevType newDevType; // at 0x0 + eCoreDevType oldDevType; // at 0x4 + s32 chan; // at 0x8 +}; + +class CoreControllerExtensionCallback { +public: + virtual void onConnect(const CoreControllerExtensionArg& rArg); // at 0x8 +}; + +/****************************************************************************** + * + * CoreStatus + * + ******************************************************************************/ +class CoreStatus : public KPADStatus { + friend class CoreController; + +public: CoreStatus() {} - ~CoreStatus() {} - f32 getFSStickX() const { - return mFSStickX; + u32 getHold() const { + return hold; } - f32 getFSStickY() const { - return mFSStickY; + u32 getRelease() const { + return release; } - bool isFreestyle() const { - return CHAR_0x5C == 1; + u32 getTrigger() const { + return trig; + } + + bool down(u32 buttons) const { + return hold & buttons; + } + bool up(u32 buttons) const { + return (hold & buttons) != buttons; + } + + bool downTrigger(u32 buttons) const { + return trig & buttons; + } + bool upTrigger(u32 buttons) const { + return release & buttons; } Vector3f getAccel() const { - return mAccel; + return Vector3f(acc.x, acc.y, acc.z); } - u32 getFSStickButton(); + eCoreDevType getDevType() const { + return static_cast(dev_type); + } + + bool isCore() const { + return getDevType() == WPAD_DEV_CORE || isFreestyle(); + } + bool isFreestyle() const { + return getDevType() == WPAD_DEV_FREESTYLE; + } - u32 hold; // at 0x0 - u32 trig; // at 0x4 - u32 release; // at 0x8 - Vector3f mAccel; // at 0xC - char UNK_0x18[0x5C - 0x18]; - s8 CHAR_0x5C; - f32 mFSStickX; // at 0x60 - f32 mFSStickY; // at 0x64 - char UNK_0x68[0x84 - 0x68]; + s8 getDPDValidFlag() const { + return dpd_valid_fg; + } + + f32 getFSStickX() const { + return ex_status.fs.stick.x; + } + f32 getFSStickY() const { + return ex_status.fs.stick.y; + } + + u32 getFSStickButton(); }; +/****************************************************************************** + * + * CoreController + * + ******************************************************************************/ class CoreController { -public: - virtual void setPosParam(f32 f1, f32 f2); // at 0x8 - virtual void setHoriParam(f32 f1, f32 f2); // at 0xC - virtual void setDistParam(f32 f1, f32 f2); // at 0x10 - virtual void setAccParam(f32 f1, f32 f2); // at 0x14 - virtual void beginFrame(PADStatus*); // at 0x18 - virtual void endFrame(); // at 0x1C + friend class CoreControllerMgr; +public: CoreController(); - ~CoreController() {} - Vector3f getAccel() const { - return mCoreStatus[0].getAccel(); + virtual void setPosParam(f32 playRadius, f32 sensitivity) { + KPADSetPosParam(mChannelID, playRadius, sensitivity); + } // at 0x8 + virtual void setHoriParam(f32 playRadius, f32 sensitivity) { + KPADSetHoriParam(mChannelID, playRadius, sensitivity); + } // at 0xC + virtual void setDistParam(f32 playRadius, f32 sensitivity) { + KPADSetDistParam(mChannelID, playRadius, sensitivity); + } // at 0x10 + virtual void setAccParam(f32 playRadius, f32 sensitivity) { + KPADSetAccParam(mChannelID, playRadius, sensitivity); + } // at 0x14 + + virtual void beginFrame(PADStatus* pStatus = NULL); // at 0x18 + virtual void endFrame(); // at 0x1C + + s32 getChannelID() const { + return mChannelID; } - void setChannel(s32 chan) { - mChannel = chan; - } - s32 getChannel() const { - return mChannel; + + bool down(u32 buttons) const { + return mCoreStatus[0].down(buttons); } - bool isStable(u8 c) const { - return ((mFlags & c) == c); + bool up(u32 buttons) const { + return mCoreStatus[0].up(buttons); } - void sceneReset() { - VEC3_0x858.x = 0.0f; - VEC3_0x858.y = 0.0f; - VEC3_0x858.z = 0.0f; - - mPostureMtx.makeIdentity(); - M34_0x8A8.makeIdentity(); + bool downTrigger(u32 buttons) const { + return mCoreStatus[0].downTrigger(buttons); + } + bool upTrigger(u32 buttons) const { + return mCoreStatus[0].upTrigger(buttons); + } - WORD_0x8DC = 10; - FLOAT_0x8EC = 0.13f; + Vector3f getAccel() const { + return mCoreStatus[0].getAccel(); + } - FLOATS_0x8F0[0] = 0.0f; - FLOATS_0x8F0[1] = 0.0f; - FLOATS_0x8F0[2] = 0.0f; + eCoreDevType getDevType() const { + return mCoreStatus[0].getDevType(); + } - mFlags = 0; - WORDS_0x8E0[0] = 0; - WORDS_0x8E0[1] = 0; - WORDS_0x8E0[2] = 0; - WORD_0x864 = 0; - WORD_0x86C = 0; - BYTE_0x868 = 0; - BYTE_0x870 = 0x20; - BYTE_0x871 = 0x1F; + bool isCore() const { + return mCoreStatus[0].isCore(); + } + bool isFreestyle() const { + return mCoreStatus[0].isFreestyle(); + } - stopRumbleMgr(); + s32 getReadLength() const { + return mKPADReadLength; } - u32 getButtonHold() const { - return mButtonHold; + bool isStable(u8 bits) const { + return (mStableFlags & bits) == bits; } - u32 getButtonTrigger() const { - return mButtonTrigger; + + void setStableFrame(int frame) { + mStableFrame = frame; } - u32 getButtonRelease() const { - return mButtonRelease; + void setStableMag(f32 mag) { + mStableMag = mag; } - int getReadLength() const { - return mKPADReadLength; - } + void sceneReset(); - void createRumbleMgr(u8); - void startPatternRumble(const char*, int, bool); - void startPowerFrameRumble(f32, int, bool); + void startMotor(); + void stopMotor(); + + void createRumbleMgr(u8 overlap_num); + void startPatternRumble(const char* pPattern, int frame, bool force); + void startPowerFrameRumble(f32 power, int frame, bool force); void stopRumbleMgr(); - CoreStatus* getCoreStatus(int = 0) const; - void calc_posture_matrix(Matrix34f&, bool); - void stopMotor(); + CoreStatus* getCoreStatus(int index); + CoreStatus* getCoreStatus() { + return getCoreStatus(0); + } + +private: + enum StableAxis { + STABLE_AXIS_X, + STABLE_AXIS_Y, + STABLE_AXIS_Z, + + STABLE_AXIS_MAX + }; + + enum StableFlag { + STABLE_FLAG_X = 1 << STABLE_AXIS_X, + STABLE_FLAG_Y = 1 << STABLE_AXIS_Y, + STABLE_FLAG_Z = 1 << STABLE_AXIS_Z, + + STABLE_FLAG_XYZ = STABLE_FLAG_X | STABLE_FLAG_Y | STABLE_FLAG_Z + }; + +private: + void calc_posture_matrix(Matrix34f& rPostureMtx, bool checkStable); + +private: + s32 mChannelID; // at 0x4 + + u32 mFSStickHold; // at 0x8 + u32 mFSStickTrig; // at 0xC + u32 mFSStickRelease; // at 0x10 -public: - s32 mChannel; // at 0x4 - u32 mButtonHold; // at 0x8 - u32 mButtonTrigger; // at 0xC - u32 mButtonRelease; // at 0x10 #if defined(PACK_RESORT) char _14[0x4]; #endif - CoreStatus mCoreStatus[16]; + + CoreStatus mCoreStatus[KPAD_MAX_SAMPLES]; // at 0x14 + #if defined(PACK_RESORT) char _858[0xF18 - 0x858]; #endif - int mKPADReadLength; // at 0x854 - Vector3f VEC3_0x858; - UNKWORD WORD_0x864; - u8 BYTE_0x868; - UNKWORD WORD_0x86C; - u8 BYTE_0x870; - u8 BYTE_0x871; - struct ControllerRumbleMgr* mRumbleMgr; // at 0x874 - Matrix34f mPostureMtx; // at 0x878 - Matrix34f M34_0x8A8; - u8 mFlags; // at 0x8D8 - UNKWORD WORD_0x8DC; - UNKWORD WORDS_0x8E0[3]; - f32 FLOAT_0x8EC; - f32 FLOATS_0x8F0[3]; + + s32 mKPADReadLength; // at 0x854 + Vector3f mAccelPrev; // at 0x858 + + u32 mSimpleRumblePattern; // at 0x864 + bool mEnableSimpleRumble; // at 0x868 + int mSimpleRumbleFrame; // at 0x86C + u8 mSimpleRumbleSize; // at 0x870 + u8 mSimpleRumbleIndex; // at 0x871 + ControllerRumbleMgr* mRumbleMgr; // at 0x874 + + Matrix34f mPostureMtx; // at 0x878 + Matrix34f mPostureMtxPrev; // at 0x8A8 + + u8 mStableFlags; // at 0x8D8 + int mStableFrame; // at 0x8DC + int mStableTimer[STABLE_AXIS_MAX]; // at 0x8E0 + f32 mStableMag; // at 0x8EC + Vector3f mStableAccel; // at 0x8F0 }; -class NullController : CoreController { +/****************************************************************************** + * + * NullController + * + ******************************************************************************/ +class NullController : public CoreController { public: - NullController() {} - ~NullController() {} + NullController() : mDevType(cDEV_NULL) {} private: + char UNK_0x8FC[0x958 - 0x8FC]; + u8 mDevType; // at 0x958 + char UNK_0x95C[0x980 - 0x95C]; }; -struct ControllerRumbleUnit { - ControllerRumbleUnit() : PTR_0x4(NULL), PTR_0x8(NULL), WORD_0xC(0) { - FLOAT_0x14 = 0.0f; - FLOAT_0x10 = 0.0f; +/****************************************************************************** + * + * CoreControllerMgr + * + ******************************************************************************/ +class CoreControllerMgr { + EGG_SINGLETON_DECL(CoreControllerMgr); - mFlags.makeAllZero(); - } +public: + virtual void beginFrame(); // at 0x8 + virtual void endFrame(); // at 0xC - virtual ~ControllerRumbleUnit() {} // at 0x8 + CoreController* getNthController(int index); - void startPattern(const char*, int); - void startPowerFrame(f32, int); - f32 calc(); +private: + CoreControllerMgr(); - void setFlags(u8 mask) { - mFlags.set(mask); - } - void clrFlags(u8 mask) { - mFlags.reset(mask); - } - bool tstFlags(u8 mask) { - return mFlags.on(mask); - } + static void connectCallback(s32 chan, s32 result); - const char* PTR_0x4; - const char* PTR_0x8; - UNKWORD WORD_0xC; - f32 FLOAT_0x10; - f32 FLOAT_0x14; - TBitFlag mFlags; // at 0x18 - nw4r::ut::Link mNode; // at 0x1C - char UNK_0x24[0x28 - 0x24]; +private: + TBuffer mControllers; // at 0x14 + CoreControllerExtensionCallback* mExtensionCallback; // at 0x20 + TBuffer mDevTypes; // at 0x24 + + static CoreControllerFactory sCoreControllerFactory; + static CoreControllerConnectCallback sConnectCallback; + static u32 sWPADWorkSize; }; -class ControllerRumbleMgr { +/****************************************************************************** + * + * ControllerRumbleUnit + * + ******************************************************************************/ +class ControllerRumbleUnit { + friend class ControllerRumbleMgr; + public: - ControllerRumbleMgr() : mController(NULL) { - nw4r::ut::List_Init(&LIST_0x4, offsetof(ControllerRumbleUnit, mNode)); - nw4r::ut::List_Init(&LIST_0x10, offsetof(ControllerRumbleUnit, mNode)); + ControllerRumbleUnit() { + init(); } - virtual ~ControllerRumbleMgr() {} // at 0x8 + virtual ~ControllerRumbleUnit() {} // at 0x8 - void createUnit(u8, CoreController*); - void startPattern(const char*, int, bool); - void startPowerFrame(f32, int, bool); - void stop(); - void calc(); + void startPattern(const char* pPattern, int frame); + void startPowerFrame(f32 power, int frame); - ControllerRumbleUnit* getUnitFromList(bool); + f32 calc(); private: - nw4r::ut::List LIST_0x4; - nw4r::ut::List LIST_0x10; - CoreController* mController; // at 0x1C -}; - -class CoreControllerMgr { -public: - // From Wii Fit U - struct CoreControllerConnectArg { - s32 LONG_0x0; - s32 LONG_0x4; + enum { + BIT_USE_PATTERN, + BIT_USE_POWER, + + BIT_POWER_LOOP, + BIT_ENABLED, + BIT_PATTERN_LOOP, + BIT_PATTERN_TIMER, }; - typedef void (*ConnectCallback)(CoreControllerConnectArg*); - typedef CoreController* (*CoreControllerFactory)(); +private: + void init(); - class T__Disposer : Disposer { - public: - T__Disposer() {} - virtual ~T__Disposer(); // at 0x8 - }; + void setFlags(u8 bit) { + mFlags.setBit(bit); + } + void clrFlags(u8 bit) { + mFlags.resetBit(bit); + } + bool tstFlags(u8 bit) { + return mFlags.onBit(bit); + } private: - T__Disposer mDisposer; // at 0x0 + const char* mRumblePattern; // at 0x4 + const char* mRumblePatternPtr; // at 0x8 + int mRumbleFrame; // at 0xC + f32 mRumblePower; // at 0x10 + f32 mRumbleValue; // at 0x14 + TBitFlag mFlags; // at 0x18 + NW4R_UT_LIST_LINK_DECL(); // at 0x1C + char UNK_0x24[0x28 - 0x24]; +}; +/****************************************************************************** + * + * ControllerRumbleMgr + * + ******************************************************************************/ +class ControllerRumbleMgr { public: - static CoreControllerMgr* getInstance() { - return sInstance; - } + ControllerRumbleMgr(); + virtual ~ControllerRumbleMgr() {} // at 0x8 - virtual void beginFrame(); // at 0x8 - virtual void endFrame(); // at 0xC + void createUnit(u8 overlap_num, CoreController* pController); - static void deleteInstance(); - CoreController* getNthController(int i); - static void connectCallback(s32, s32); + void stop(); + void calc(); -private: - CoreControllerMgr(); + void startPattern(const char* pPattern, int frame, bool force); + void startPowerFrame(f32 power, int frame, bool force); private: - TBuffer mControllers; // at 0x14 - struct UnkInterface { - virtual UNKTYPE VF08(UNKTYPE*) = 0; - }* PTR_0x20; - TBuffer mDevTypes; // at 0x24 + ControllerRumbleUnit* getUnitFromList(bool force); - static CoreControllerMgr* sInstance; - static CoreControllerFactory sCoreControllerFactory; - static ConnectCallback sConnectCallback; - static int sWPADWorkSize; +private: + nw4r::ut::List mActiveUnitList; // at 0x0 + nw4r::ut::List mStoppedUnitList; // at 0x10 + CoreController* mController; // at 0x14 }; + } // namespace EGG #endif diff --git a/include/egg/core/eggDecomp.h b/include/egg/core/eggDecomp.h index 4c83e45..31aefb9 100644 --- a/include/egg/core/eggDecomp.h +++ b/include/egg/core/eggDecomp.h @@ -1,37 +1,55 @@ #ifndef EGG_CORE_DECOMP_H #define EGG_CORE_DECOMP_H -#include "types_egg.h" +#include namespace EGG { + class Decomp { public: - enum CompressedType { - TYPE_UNKNOWN = 0, - TYPE_SZS = 1, - TYPE_ASH = 2, - TYPE_ASR = 3 + enum ECompressKind { + cCompress_None, + cCompress_SZS, + cCompress_ASH, + cCompress_ASR }; - static int decode(u8*, u8*); - static int decodeSZS(u8*, u8*); - static int decodeASH(u8*, u8*); - static int decodeASR(u8*, u8*); - static int checkCompressed(u8*); - static int getExpandSize(u8*); - static UNKWORD getBitsCode(u8*, int, int); - static UNKWORD getBit1c(u8*, int); - static UNKWORD readTree9(u8*, u16*, u16*, u16*); - static UNKWORD readTree12(u8*, u16*, u16*, u16*); + static ECompressKind checkCompressed(u8* pData); + static int getExpandSize(u8* pData); + + static int decode(u8* pSrc, u8* pDst); + + static int decodeSZS(u8* pSrc, u8* pDst); + static int decodeASH(u8* pSrc, u8* pDst); + static int decodeASR(u8* pSrc, u8* pDst); private: + enum ETreeKind { cTreeLiteral, cTreeBackRef, cTreeMax }; + + enum ENodeFlag { + cNodeLeft = 1 << 14, + cNodeRight = 1 << 15, + cNodeIndexMask = cNodeLeft - 1 + }; + static const int cTreeStackSize = 256; + static const int cNode9Min = 1 << 9; + static const int cNode12Min = 1 << 11; - static char* sWorkArea; // sizeof = 0x9008 - static UNKWORD lbl_804BED10[2]; - static UNKWORD lbl_804BED18[2]; - static UNKWORD lbl_804BED20[2]; - static UNKWORD lbl_804BED28[2]; +private: + static int getBitsCode(u8* pData, int size, int tree); + static int getBit1c(u8* pData, int tree); + static int readTree9(u8* pData, u16* pLeft, u16* pRight, u16* pStack); + static int readTree12(u8* pData, u16* pLeft, u16* pRight, u16* pStack); + +private: + static u8* sWorkArea; + + static int sStreamBit[cTreeMax]; + static int sNextNodeID[cTreeMax]; + static int sStreamByte[cTreeMax]; + static u32 sStreamData[cTreeMax]; }; + } // namespace EGG #endif diff --git a/include/egg/core/eggDisplay.h b/include/egg/core/eggDisplay.h index 0b8f773..75e761e 100644 --- a/include/egg/core/eggDisplay.h +++ b/include/egg/core/eggDisplay.h @@ -1,31 +1,37 @@ #ifndef EGG_CORE_DISPLAY_H #define EGG_CORE_DISPLAY_H -#include "eggBitFlag.h" -#include "types_egg.h" -#include "ut_Color.h" +#include + +#include +#include +#include + +#include namespace EGG { -struct Display { - TBitFlag FLAG_0x0; - Display(u8); - void copyEFBtoXFB(); - void calcFrequency(); +class Display { +protected: + TBitFlag mEfbFlags; // at 0x0 + +public: + explicit Display(u8 frameRate); + + virtual void beginFrame(); // at 0x8 + virtual void beginRender(); // at 0xC + virtual void endRender(); // at 0x10 + virtual void endFrame(); // at 0x14 - virtual void beginFrame(); // at 0x8 - virtual void beginRender(); // at 0xC - virtual void endRender(); // at 0x10 - virtual void endFrame(); // at 0x14 virtual u32 getTickPerFrame(); // at 0x18 - bool isBlack() { - return BYTE_0x9 & 0x1; - } - void setBlack(bool b) { - if (b) - BYTE_0x9 |= 0x1; - else - BYTE_0x9 &= (u8)~0x1; + void copyEFBtoXFB(); + + void setBlack(bool enable) { + if (!BaseSystem::getVideo()->isBlack() && + !mXfbFlags.onBit(BIT_XFB_CHANGE_BLACK)) { + + mXfbFlags.changeBit(BIT_XFB_CHANGE_BLACK, !enable); + } } nw4r::ut::Color getClearColor() const { @@ -35,16 +41,32 @@ struct Display { mClearColor = color; } - u8 mRetraceWait; // at 0x8 - volatile u8 BYTE_0x9; +protected: + enum EfbFlagBit { + BIT_EFB_COPY_CLEAR, + }; + enum XfbFlagBit { + BIT_XFB_CHANGE_BLACK, + }; + +protected: + void calcFrequency(); + +protected: + u8 mFrameRate; // at 0x8 + TBitFlag mXfbFlags; // at 0x9 u32 mRetraceCount; // at 0xC u32 mFrameCount; // at 0x10 nw4r::ut::Color mClearColor; // at 0x14 u32 mClearZ; // at 0x20 - s32 mBeginTick; // at 0x1C - s32 mDeltaTick; // at 0x20 + s32 mPrevFrameTick; // at 0x1C + s32 mFrameCostTick; // at 0x20 f32 mFrequency; // at 0x24 + +private: + void syncVRetrace(u8 frameRate); }; + } // namespace EGG #endif diff --git a/include/egg/core/eggDisposer.h b/include/egg/core/eggDisposer.h index 56778df..1772395 100644 --- a/include/egg/core/eggDisposer.h +++ b/include/egg/core/eggDisposer.h @@ -1,16 +1,28 @@ #ifndef EGG_CORE_DISPOSER_H #define EGG_CORE_DISPOSER_H -#include "types_egg.h" -#include "ut_list.h" +#include + +#include namespace EGG { -struct Disposer { + +// Forward declarations +class Heap; + +class Disposer { + friend class Heap; + +public: Disposer(); - virtual ~Disposer(); + virtual ~Disposer(); // at 0x8 + +private: + Heap* mContainHeap; // at 0x4 - Heap* mHeap; // at 0x0 - nw4r::ut::Link mNode; // at 0x4 +public: + NW4R_UT_LIST_LINK_DECL(); // at 0x8 }; + } // namespace EGG #endif diff --git a/include/egg/core/eggDvdFile.h b/include/egg/core/eggDvdFile.h index 992fa8d..b1b9a78 100644 --- a/include/egg/core/eggDvdFile.h +++ b/include/egg/core/eggDvdFile.h @@ -1,60 +1,80 @@ -#ifndef EGG_CORE_DVDFILE_H -#define EGG_CORE_DVDFILE_H -#include "eggFile.h" -#include "types_egg.h" -#include "ut_list.h" +#ifndef EGG_CORE_DVD_FILE_H +#define EGG_CORE_DVD_FILE_H +#include + +#include + +#include #include -#include -#include -#include +#include namespace EGG { -class DvdFile : File { - friend class DvdRipper; - - struct FileInfoPair { - DVDFileInfo mFileInfo; // at 0x0 - DvdFile* pDvdFile; // at 0x3C - }; +class DvdFile : public File { public: - DvdFile(); static void initialize(); - void initiate(); - static void doneProcess(s32, DVDFileInfo*); - - virtual ~DvdFile(); // at 0x8 - virtual bool open(const char*); // at 0xC - virtual void close(); // at 0x10 - virtual s32 readData(void*, s32, s32); // at 0x14 - virtual s32 writeData(const void*, s32, s32); // at 0x18 - virtual UNKWORD getFileSize() const { - return mFileInfo.size; + + DvdFile(); + virtual ~DvdFile(); // at 0x8 + + virtual bool open(const char* pPath); // at 0xC + virtual bool open(s32 entryNum); // at 0x20 + virtual bool open(const char* pPath, void* pMultiHandle); // at 0x24 + + virtual void close(); // at 0x10 + + virtual s32 readData(void* pDst, s32 size, s32 offset); // at 0x14 + virtual s32 writeData(const void* pSrc, s32 size, s32 offset); // at 0x18 + + virtual u32 getFileSize() const { + return mAsyncContext.fileInfo.size; }; // at 0x1C - virtual bool open(int); // at 0x20 - virtual bool open(const char*, void*); // at 0x24 + + void initiate(); + + DVDFileInfo* getFileInfo() { + return &mAsyncContext.fileInfo; + } + s32 getStatus() const { + return DVDGetCommandBlockStatus(&mAsyncContext.cmdBlock); + } private: - bool mIsOpen; // at 0x4 - OSMutex mMutex_0x8; - OSMutex mMutex_0x20; - UNKWORD WORD_0x38; - union { - DVDCommandBlock mCmdBlock; // at 0x3C - DVDFileInfo mFileInfo; // at 0x3C + struct AsyncContext { + union { + DVDFileInfo fileInfo; // at 0x0 + DVDCommandBlock cmdBlock; // at 0x0 + }; + DvdFile* pFile; // at 0x3C }; - DvdFile* PTR_0x78; - OSMessageQueue mMesgQueue_0x7C; - OSMessage mMesg_0x9C; - OSMessageQueue mMesgQueue_0xA0; - OSMessage mMesg_0xC0; - OSThread* mThread; // at 0xC4 - nw4r::ut::Link mNode; // at 0xC8 +private: + s32 sync(); + + static void doneProcess(s32 result, DVDFileInfo* pFileInfo); + +private: + OSMutex mSyncMutex; // at 0x8 + OSMutex mAsyncMutex; // at 0x20 + + OSThread* mAsyncThread; // at 0x38 + AsyncContext mAsyncContext; // at 0x3C + OSMessageQueue mAsyncQueue; // at 0x7C + OSMessage mAsyncBuffer[1]; // at 0x9C + + OSMessageQueue mSyncQueue; // at 0xA0 + OSMessage mSyncBuffer[1]; // at 0xC0 + OSThread* mSyncThread; // at 0xC4 + +public: + NW4R_UT_LIST_LINK_DECL(); // at 0xC8 + +private: static nw4r::ut::List sDvdList; static bool sIsInitialized; }; + } // namespace EGG #endif diff --git a/include/egg/core/eggDvdRipper.h b/include/egg/core/eggDvdRipper.h index daa5b24..34bf37d 100644 --- a/include/egg/core/eggDvdRipper.h +++ b/include/egg/core/eggDvdRipper.h @@ -1,21 +1,26 @@ -#ifndef EGG_CORE_DVDRIPPER_H -#define EGG_CORE_DVDRIPPER_H -#include "types_egg.h" +#ifndef EGG_CORE_DVD_RIPPER_H +#define EGG_CORE_DVD_RIPPER_H +#include namespace EGG { -struct DvdRipper { - enum EAllocDirection { - ALLOC_TAIL, - ALLOC_HEAD, - }; - static void* loadToMainRAM(const char*, u8*, Heap*, EAllocDirection, u32, - u32*, u32*); - static void* loadToMainRAM(DvdFile*, u8*, Heap*, EAllocDirection, u32, u32*, - u32*); +class DvdRipper { +public: + enum EAllocDirection { ALLOC_DIR_TAIL, ALLOC_DIR_HEAD }; +public: + static u8* loadToMainRAM(const char* pPath, u8* pBuffer, Heap* pHeap, + EAllocDirection allocDir, u32 offset, u32* pRead, + u32* pSize); + + static u8* loadToMainRAM(DvdFile* pFile, u8* pBuffer, Heap* pHeap, + EAllocDirection allocDir, u32 offset, u32* pRead, + u32* pSize); + +private: static bool sErrorRetry; }; + } // namespace EGG #endif diff --git a/include/egg/core/eggExpHeap.h b/include/egg/core/eggExpHeap.h index da64d4d..0e31894 100644 --- a/include/egg/core/eggExpHeap.h +++ b/include/egg/core/eggExpHeap.h @@ -1,24 +1,40 @@ -#ifndef EGG_CORE_EXPHEAP_H -#define EGG_CORE_EXPHEAP_H -#include "eggDisposer.h" -#include "eggHeap.h" -#include "types_egg.h" +#ifndef EGG_CORE_EXP_HEAP_H +#define EGG_CORE_EXP_HEAP_H +#include + +#include +#include namespace EGG { -struct ExpHeap : Heap { - virtual ~ExpHeap(); // at 0x8 - virtual EHeapKind getHeapKind() const; // at 0xC - virtual void initAllocator(Allocator*, s32); // at 0x10 - virtual void* alloc(u32, s32); // at 0x14 - virtual void free(void*); // at 0x18 - virtual void destroy(); // at 0x1C - virtual u32 resizeForMBlock(void*, u32); // at 0x20 - virtual u32 getAllocatableSize(s32); // at 0x24 - virtual u32 adjust(); // at 0x28 - - static ExpHeap* create(void*, u32, u16 = 0); - static ExpHeap* create(u32, Heap*, u16 = 0); + +// Forward declarations +class Allocator; + +class ExpHeap : public Heap { +public: + static ExpHeap* create(void* pHeapStart, u32 size, u16 opt = 0) + DECOMP_DONT_INLINE; + static ExpHeap* create(u32 size, Heap* pParentHeap, u16 opt = 0); + + explicit ExpHeap(MEMiHeapHead* pHeapHandle); + virtual ~ExpHeap(); // at 0x8 + + virtual EHeapKind getHeapKind() const { + return HEAP_KIND_EXPAND; + } // at 0xC + + virtual void initAllocator(Allocator* pAllocator, + s32 align = 4); // at 0x10 + + virtual void* alloc(u32 size, s32 align = 4); // at 0x14 + virtual void free(void* pBlock); // at 0x18 + virtual void destroy(); // at 0x1C + + virtual u32 resizeForMBlock(void* pBlock, u32 size); // at 0x20 + virtual u32 getAllocatableSize(s32 align = 4); // at 0x24 + virtual u32 adjust(); // at 0x28 }; + } // namespace EGG #endif diff --git a/include/egg/core/eggFader.h b/include/egg/core/eggFader.h index d881f77..82284d0 100644 --- a/include/egg/core/eggFader.h +++ b/include/egg/core/eggFader.h @@ -1,9 +1,11 @@ #ifndef EGG_CORE_FADER_H #define EGG_CORE_FADER_H -#include "types_egg.h" +#include namespace EGG { -struct Fader { + +class Fader { +public: enum EStatus { STATUS_PREPARE_IN, STATUS_PREPARE_OUT, @@ -11,13 +13,17 @@ struct Fader { STATUS_FADE_OUT }; - virtual void setStatus(EStatus) = 0; - virtual EStatus getStatus() const = 0; - virtual bool fadeIn() = 0; - virtual bool fadeOut() = 0; - virtual bool calc() = 0; - virtual void draw() = 0; +public: + virtual void setStatus(EStatus status) = 0; // at 0x8 + virtual EStatus getStatus() const = 0; // at 0xC + + virtual bool fadeIn() = 0; // at 0x10 + virtual bool fadeOut() = 0; // at 0x14 + + virtual bool calc() = 0; // at 0x18 + virtual void draw() = 0; // at 0x1C }; + } // namespace EGG #endif diff --git a/include/egg/core/eggFile.h b/include/egg/core/eggFile.h index 7105ed2..e53e49a 100644 --- a/include/egg/core/eggFile.h +++ b/include/egg/core/eggFile.h @@ -1,16 +1,27 @@ #ifndef EGG_CORE_FILE_H #define EGG_CORE_FILE_H -#include "types_egg.h" +#include namespace EGG { -struct File { - virtual ~File() {} - virtual bool open(const char*) = 0; - virtual void close() = 0; - virtual s32 readData(void*, s32, s32) = 0; - virtual s32 writeData(const void*, s32, s32) = 0; - virtual UNKWORD getFileSize() const = 0; + +class File { +public: + File() : mIsOpen(false) {} + virtual ~File() {} // at 0x8 + + virtual bool open(const char* pPath) = 0; // at 0xC + virtual void close() = 0; // at 0x10 + + virtual s32 readData(void* pDst, s32 size, s32 offset) = 0; // at 0x14 + virtual s32 writeData(const void* pSrc, s32 size, + s32 offset) = 0; // at 0x18 + + virtual u32 getFileSize() const = 0; // at 0x1C + +protected: + bool mIsOpen; // at 0x4 }; + } // namespace EGG #endif diff --git a/include/egg/core/eggFrmHeap.h b/include/egg/core/eggFrmHeap.h index 6d7706e..bd7077d 100644 --- a/include/egg/core/eggFrmHeap.h +++ b/include/egg/core/eggFrmHeap.h @@ -1,25 +1,40 @@ -#ifndef EGG_CORE_FRAMEHEAP_H -#define EGG_CORE_FRAMEHEAP_H -#include "eggDisposer.h" -#include "eggHeap.h" -#include "types_egg.h" +#ifndef EGG_CORE_FRM_HEAP_H +#define EGG_CORE_FRM_HEAP_H +#include + +#include +#include namespace EGG { -struct FrmHeap : Heap { - FrmHeap(MEMiHeapHead*); // inlined - virtual ~FrmHeap(); // at 0x8 - virtual EHeapKind getHeapKind() const; // at 0xC - virtual void initAllocator(Allocator*, s32); // at 0x10 - virtual void* alloc(u32, s32); // at 0x14 - virtual void free(void*); // at 0x18 - virtual void destroy(); // at 0x1C - virtual u32 resizeForMBlock(void*, u32); // at 0x20 - virtual u32 getAllocatableSize(s32); // at 0x24 - virtual u32 adjust(); // at 0x28 - - static FrmHeap* create(void*, u32, u16); - static FrmHeap* create(u32, Heap*, u16); + +// Forward declarations +class Allocator; + +class FrmHeap : public Heap { +public: + static FrmHeap* create(void* pHeapStart, u32 size, u16 opt = 0) + DECOMP_DONT_INLINE; + static FrmHeap* create(u32 size, Heap* pParentHeap, u16 opt = 0); + + explicit FrmHeap(MEMiHeapHead* pHeapHandle); + virtual ~FrmHeap(); // at 0x8 + + virtual EHeapKind getHeapKind() const { + return HEAP_KIND_FRAME; + } // at 0xC + + virtual void initAllocator(Allocator* pAllocator, + s32 align = 4); // at 0x10 + + virtual void* alloc(u32 size, s32 align = 4); // at 0x14 + virtual void free(void* pBlock); // at 0x18 + virtual void destroy(); // at 0x1C + + virtual u32 resizeForMBlock(void* pBlock, u32 size); // at 0x20 + virtual u32 getAllocatableSize(s32 align = 4); // at 0x24 + virtual u32 adjust(); // at 0x28 }; + } // namespace EGG #endif diff --git a/include/egg/core/eggGraphicsFifo.h b/include/egg/core/eggGraphicsFifo.h index 41b7392..74658d4 100644 --- a/include/egg/core/eggGraphicsFifo.h +++ b/include/egg/core/eggGraphicsFifo.h @@ -1,29 +1,51 @@ #ifndef EGG_CORE_GRAPHICS_FIFO_H #define EGG_CORE_GRAPHICS_FIFO_H -#include "types_egg.h" -#include "ut_algorithm.h" +#include + +#include namespace EGG { -struct GraphicsFifo { + +// Forward declarations +class Heap; + +class GraphicsFifo { +public: struct GpStatus { - u8 b0; - u8 b1; - u8 b2; - u8 b3; - u8 b4; + GXBool overhi; // at 0x0 + GXBool underlow; // at 0x1 + GXBool readIdle; // at 0x2 + GXBool cmdIdle; // at 0x3 + GXBool brkpt; // at 0x4 }; - GraphicsFifo(u32, Heap*); - static GraphicsFifo* create(u32, Heap*); - virtual ~GraphicsFifo(); +public: + static GraphicsFifo* create(u32 size, Heap* pHeap); + + GraphicsFifo(u32 size, Heap* pHeap); + virtual ~GraphicsFifo(); // at 0x8 - void* PTR_0x4; - void* mBufBase; // at 0x8 - u32 mBufSize; // at 0xC + static bool isGPActive() { + return !getGpStatus().readIdle; + } + + static const GpStatus& getGpStatus() { + GXGetGPStatus(&sGpStatus.overhi, &sGpStatus.underlow, + &sGpStatus.readIdle, &sGpStatus.cmdIdle, + &sGpStatus.brkpt); + + return sGpStatus; + } + +private: + GXFifoObj* mFifoObj; // at 0x4 + void* mBufBase; // at 0x8 + u32 mBufSize; // at 0xC static GraphicsFifo* sGraphicsFifo; static GpStatus sGpStatus; }; + } // namespace EGG #endif diff --git a/include/egg/core/eggHeap.h b/include/egg/core/eggHeap.h index 8d67fa6..fa5d2f6 100644 --- a/include/egg/core/eggHeap.h +++ b/include/egg/core/eggHeap.h @@ -1,89 +1,156 @@ #ifndef EGG_CORE_HEAP_H #define EGG_CORE_HEAP_H +#include -#include "eggBitFlag.h" -#include "eggDisposer.h" -#include "types_egg.h" -#include "ut_list.h" +#include +#include -#include -#include +#include + +#include +#include namespace EGG { -class Heap : Disposer { -public: - enum EHeapKind { HEAP_EXPANDED = 1, HEAP_FRAME = 2 }; +// Forward declarations +class Allocator; +class ExpHeap; + +class Heap : public Disposer { public: - static void* addOffset(void* p, u32 ofs) { - return (char*)p + ofs; - } - static Heap* getCurrentHeap() { - return sCurrentHeap; - } + enum EHeapKind { + HEAP_KIND_NONE, + HEAP_KIND_EXPAND, + HEAP_KIND_FRAME, + HEAP_KIND_UNIT, + HEAP_KIND_ASSERT + }; +public: static void initialize(); - static Heap* findHeap(MEMiHeapHead*); - static Heap* findContainHeap(const void*); - static void* alloc(u32, int, Heap*); - static void free(void*, Heap*); - - Heap(MEMiHeapHead*); - virtual ~Heap(); // at 0x8 - virtual EHeapKind getHeapKind() const = 0; // at 0xC - virtual void initAllocator(Allocator*, s32) = 0; // at 0x10 - virtual void* alloc(u32, s32) = 0; // at 0x14 - virtual void free(void*) = 0; // at 0x18 - virtual void destroy() = 0; // at 0x1C - virtual u32 resizeForMBlock(void*, u32) = 0; // at 0x20 - virtual u32 getAllocatableSize(s32 align = 4) = 0; // at 0x24 - virtual u32 adjust() = 0; // at 0x28 - - u8* getStartAddress() { - return (u8*)this; + + static void* alloc(u32 size, int align, Heap* pHeap); + static void free(void* pBlock, Heap* pHeap); + + explicit Heap(MEMiHeapHead* pHeapHandle); + virtual ~Heap(); // at 0x8 + + virtual EHeapKind getHeapKind() const = 0; // at 0xC + + virtual void initAllocator(Allocator* pAllocator, + s32 align = 4) = 0; // at 0x10 + + virtual void* alloc(u32 size, s32 align = 4) = 0; // at 0x14 + virtual void free(void* pBlock) = 0; // at 0x18 + virtual void destroy() = 0; // at 0x1C + + virtual u32 resizeForMBlock(void* pBlock, u32 size) = 0; // at 0x20 + virtual u32 getAllocatableSize(s32 align = 4) = 0; // at 0x24 + virtual u32 adjust() = 0; // at 0x28 + + static Heap* findHeap(MEMiHeapHead* pHeapHandle); + Heap* findParentHeap(); + static Heap* findContainHeap(const void* pBlock); + + void dispose(); + Heap* becomeCurrentHeap(); + + void* getStartAddress() { + return this; } - u8* getEndAddress() { - return mHeapHandle->end; + void* getEndAddress() { + return MEMGetHeapEndAddress(mHeapHandle); } - int getTotalSize() { - return getEndAddress() - getStartAddress(); + s32 getTotalSize() { + return static_cast(getEndAddress()) - + static_cast(getStartAddress()); } - bool tstDisableAllocation() { - return mFlags.onBit(0); + bool isHeapPointer(void* pBlock) { + return pBlock >= getStartAddress() && pBlock < getEndAddress(); } + void disableAllocation() { - mFlags.setBit(0); + mFlags.setBit(BIT_DISABLE_ALLOC); } void enableAllocation() { - mFlags.resetBit(0); + mFlags.resetBit(BIT_DISABLE_ALLOC); + } + bool tstDisableAllocation() { + return mFlags.onBit(BIT_DISABLE_ALLOC); } - void appendDisposer(Disposer* disposer) { - nw4r::ut::List_Append(&mChildren, disposer); + void appendDisposer(Disposer* pDisposer) { + nw4r::ut::List_Append(&mDisposerList, pDisposer); } - void removeDisposer(Disposer* disposer) { - nw4r::ut::List_Remove(&mChildren, disposer); + void removeDisposer(Disposer* pDisposer) { + nw4r::ut::List_Remove(&mDisposerList, pDisposer); } - Heap* findParentHeap(); - void dispose(); - Heap* becomeCurrentHeap(); + static const nw4r::ut::List& getHeapList() { + return sHeapList; + } + static Heap* getCurrentHeap() { + return sCurrentHeap; + } + + static ExpHeap* dynamicCastToExp(Heap* pHeap) { + if (pHeap->getHeapKind() == HEAP_KIND_EXPAND) { + return reinterpret_cast(pHeap); + } + + return NULL; + } + + static void disableAllocationAllBut(Heap* pHeap) { + sAllocatableHeap = pHeap; + } + +protected: + static void* addOffset(void* pBase, u32 offset) { + return static_cast(pBase) + offset; + } + + void registerHeapBuffer(void* pBuffer) { + mHeapBuffer = pBuffer; + } protected: MEMiHeapHead* mHeapHandle; // at 0x10 - void* mMemBlock; // at 0x14 + void* mHeapBuffer; // at 0x14 Heap* mParentHeap; // at 0x18 - TBitFlag mFlags; // at 0x1C - nw4r::ut::Link mNode; // at 0x20 - nw4r::ut::List mChildren; // at 0x28 - static nw4r::ut::List sHeapList; - static OSMutex sRootMutex; +private: + enum { + BIT_DISABLE_ALLOC, + }; + +private: + TBitFlag mFlags; // at 0x1C + NW4R_UT_LIST_LINK_DECL(); // at 0x20 + nw4r::ut::List mDisposerList; // at 0x28 + static Heap* sCurrentHeap; + + static nw4r::ut::List sHeapList; static BOOL sIsHeapListInitialized; + static OSMutex sRootMutex; + static Heap* sAllocatableHeap; }; + } // namespace EGG +#if !defined(__KOKESHI__) +void* operator new(size_t size); +void* operator new(size_t size, EGG::Heap* pHeap, int align = 4); + +void* operator new[](size_t size); +void* operator new[](size_t size, int align); +void* operator new[](size_t size, EGG::Heap* pHeap, int align = 4); + +void operator delete(void* pBlock) noexcept; +void operator delete[](void* pBlock) noexcept; +#endif + #endif diff --git a/include/egg/core/eggIBinary.h b/include/egg/core/eggIBinary.h index 9bbde3d..d06a9a0 100644 --- a/include/egg/core/eggIBinary.h +++ b/include/egg/core/eggIBinary.h @@ -1,62 +1,65 @@ #ifndef EGG_CORE_IBINARY_H #define EGG_CORE_IBINARY_H -#include "eggAssert.h" #include "types_egg.h" +#include "eggAssert.h" -namespace EGG { -template class IBinary { -public: - struct Bin { - char magic[4]; // at 0x0 - u32 size; // at 0x4 - u8 UNK_0x5[0x8 - 0x5]; - u8 version; // at 0x8 - u8 UNK_0x09[0x10 - 0x9]; - }; +namespace EGG +{ + template + class IBinary + { + public: + struct Bin + { + char magic[4]; // at 0x0 + u32 size; // at 0x4 + u8 UNK_0x5[0x8 - 0x5]; + u8 version; // at 0x8 + u8 UNK_0x09[0x10 - 0x9]; + }; + + virtual void SetBinaryInner(const Bin&) = 0; // at 0x8 + virtual void GetBinaryInner(Bin *) const = 0; // at 0xC + virtual const char * GetBinaryType() const = 0; // at 0x10 + virtual u32 GetBinarySize() const { return sizeof(T::Bin); }; // at 0x14 + virtual u8 GetVersion() const = 0; // at 0x18 + + void SetBinary(const void *bin) + { + #line 93 + EGG_ASSERT(bin); + Bin *binary = (Bin *)bin; - virtual void SetBinaryInner(const Bin&) = 0; // at 0x8 - virtual void GetBinaryInner(Bin*) const = 0; // at 0xC - virtual const char* GetBinaryType() const = 0; // at 0x10 - virtual u32 GetBinarySize() const { - return sizeof(T::Bin); - }; // at 0x14 - virtual u8 GetVersion() const = 0; // at 0x18 - - void SetBinary(const void* bin) { -#line 93 - EGG_ASSERT(bin); - Bin* binary = (Bin*)bin; - - EGG_ASSERT_MSG(GetBinaryType()[0] == binary->magic[0] && - GetBinaryType()[1] == binary->magic[1] && - GetBinaryType()[2] == binary->magic[2] && - GetBinaryType()[3] == binary->magic[3], - "Not for this class."); - - SetBinaryInner(*bin); - } - - void GetBinary(void* bin) const { -#line 105 - EGG_ASSERT(bin); - Bin* binary = (Bin*)bin; - - binary->version = GetVersion(); - binary->size = GetBinarySize(); - for (int i = 0; i < sizeof(Bin::magic); i++) { - binary->magic[i] = GetBinaryType()[i]; + EGG_ASSERT_MSG(GetBinaryType()[0] == binary->magic[0] + && GetBinaryType()[1] == binary->magic[1] + && GetBinaryType()[2] == binary->magic[2] + && GetBinaryType()[3] == binary->magic[3], + "Not for this class."); + + SetBinaryInner(*bin); } - GetBinaryInner(binary); - } + void GetBinary(void *bin) const + { + #line 105 + EGG_ASSERT(bin); + Bin *binary = (Bin *)bin; + + binary->version = GetVersion(); + binary->size = GetBinarySize(); + for (int i = 0; i < sizeof(Bin::magic); i++) + { + binary->magic[i] = GetBinaryType()[i]; + } - static void SetBinaryExtension(const char* ext) { - sExtension = ext; - } + GetBinaryInner(binary); + } -private: - static const char* sExtension; -}; -} // namespace EGG + static void SetBinaryExtension(const char *ext) { sExtension = ext; } + + private: + static const char *sExtension; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/core/eggPerformanceView.h b/include/egg/core/eggPerformanceView.h index 2fa8abf..b79e21b 100644 --- a/include/egg/core/eggPerformanceView.h +++ b/include/egg/core/eggPerformanceView.h @@ -1,20 +1,23 @@ #ifndef EGG_CORE_PERFORMANCE_VIEW_H #define EGG_CORE_PERFORMANCE_VIEW_H -#include "types_egg.h" +#include namespace EGG { class PerformanceView { public: - virtual void measureBeginFrame() = 0; // at 0x8 - virtual void measureEndFrame() = 0; // at 0xC - virtual void measureBeginRender() = 0; // at 0x10 - virtual void measureEndRender() = 0; // at 0x14 + virtual void measureBeginFrame() = 0; // at 0x8 + virtual void measureEndFrame() = 0; // at 0xC + + virtual void measureBeginRender() = 0; // at 0x10 + virtual void measureEndRender() = 0; // at 0x14 + virtual void callbackDrawSync(u16 token) = 0; // at 0x18 - virtual void VMT_0x1C() = 0; // at 0x1C + virtual void VF_0x1C() {} // at 0x1C virtual void draw() = 0; // at 0x20 - virtual void setVisible(bool visible) = 0; // at 0x24 - virtual bool isVisible() = 0; // at 0x28 + + virtual void setVisible(bool visible) = 0; // at 0x24 + virtual bool isVisible() = 0; // at 0x28 }; } // namespace EGG diff --git a/include/egg/core/eggProcessMeter.h b/include/egg/core/eggProcessMeter.h index c653242..7847893 100644 --- a/include/egg/core/eggProcessMeter.h +++ b/include/egg/core/eggProcessMeter.h @@ -1,11 +1,203 @@ #ifndef EGG_CORE_PROCESS_METER_H #define EGG_CORE_PROCESS_METER_H -#include "eggPerformanceView.h" -#include "types_egg.h" +#include + +#include +#include +#include +#include +#include + +#include + +#include namespace EGG { -class ProcessMeter : public PerformanceView {}; +/****************************************************************************** + * + * ProcessMeter + * + ******************************************************************************/ +class ProcessMeter : public Thread, public PerformanceView { +public: + // Forward declarations + struct CpuGpMonitor; + + /*************************************************************************** + * DrawSync + ***************************************************************************/ + struct DrawSync { + void* pWritePtr; // at 0x0 + u16 token; // at 0x4 + DrawSync* pNext; // at 0x8 + CpuGpMonitor* pGpMonitor; // at 0xC + }; + + /*************************************************************************** + * ProcessBar + ***************************************************************************/ + class ProcessBar { + public: + f32 mPosX; // at 0x0 + f32 mWidth; // at 0x4 + + Stopwatch mStopWatch; // at 0x8 + nw4r::ut::Color mColor; // at 0x10 + + f32 mPosY; // at 0x14 + f32 mHeight; // at 0x18 + + public: + static u16 getLinkOffset() { + return offsetof(ProcessBar, mLink); + } + + ProcessBar(nw4r::ut::Color color, f32 posY, f32 height); + + bool update(s32 measureTick); + bool update(f32 measureTime); + + void draw(); + void draw(f32 posY, f32 height); + + void show() { + mFlags.resetBit(BIT_HIDDEN); + } + void hide() { + mFlags.setBit(BIT_HIDDEN); + } + + bool isVisible() { + return mFlags.offBit(BIT_HIDDEN); + } + + private: + enum { + BIT_HIDDEN, + }; + + private: + TBitFlag mFlags; // at 0x1C + nw4r::ut::Link mLink; // at 0x20 + }; + + /*************************************************************************** + * CpuMonitor + ***************************************************************************/ + class CpuMonitor { + friend class ProcessMeter; + + public: + CpuMonitor(nw4r::ut::Color color, f32 posY); + + virtual void show(); // at 0x8 + virtual void hide(); // at 0xC + + virtual void measureBegin(); // at 0x10 + virtual void measureEnd(); // at 0x14 + + protected: + ProcessBar mCpuProcessBar; // at 0x4 + }; + + /*************************************************************************** + * CpuGpMonitor + ***************************************************************************/ + class CpuGpMonitor : public CpuMonitor { + friend class ProcessMeter; + + public: + enum EDrawSyncState { DRAWSYNC_NONE, DRAWSYNC_BEGIN, DRAWSYNC_END }; + + public: + CpuGpMonitor(nw4r::ut::Color cpuColor, nw4r::ut::Color gpColor, + f32 cpuPosY, f32 gpPosY); + + virtual void show(); // at 0x8 + virtual void hide(); // at 0xC + + virtual void measureBegin(); // at 0x10 + virtual void measureEnd(); // at 0x14 + + protected: + void doToken(u32 tick); + + protected: + ProcessBar mGpProcessBar; // at 0x2C + u16 mDrawSyncState; // at 0x54 + ProcessMeter* mProcessMeter; // at 0x58 + DrawSync mBeginDrawSync; // at 0x5C + DrawSync mEndDrawSync; // at 0x68 + }; + +public: + explicit ProcessMeter(bool showGp); + virtual ~ProcessMeter() {} // at 0x8 + + virtual void* run(void); // at 0xC + + virtual void setVisible(bool visible); // at 0x44 + virtual bool isVisible(); // at 0x48 + + virtual void callbackDrawSync(u16 token); // at 0x4C + + virtual void measureBeginFrame(); // at 0x50 + virtual void measureEndFrame(); // at 0x54 + + virtual void measureBeginRender(); // at 0x58 + virtual void measureEndRender(); // at 0x5C + + virtual void draw(); // at 0x60 + +private: + enum { + BIT_VISIBLE, + }; + + static const u32 THREAD_STACK_SIZE = OS_MEM_KB_TO_B(4); + static const u32 THREAD_MSG_CAPACITY = 4; + + static const u32 GRADUATION_COLOR = 0xCCCCCCFF; + static const u32 BG_COLOR = 0x000032C8; + + static const u32 CPU_BAR_COLOR = 0xFF5050FF; + static const u32 CPU_GP_BAR_COLOR = 0x50FF50FF; + static const u32 GP_BAR_COLOR = 0x5050FFFF; + + static const u32 DRAW_TOKEN_MIN = 0xD000; + static const u32 DRAW_TOKEN_MAX = 0xDFFF; + +private: + static void callbackDrawSyncStatic(u16 token) { + BaseSystem::getPerfView()->callbackDrawSync(token); + } + + void setDrawSync(DrawSync* pDrawSync); + + void append(CpuMonitor* pMonitor); + void append(CpuGpMonitor* pGpMonitor); + + void draw(f32 fbWidth, f32 efbHeight, u32 tickPerFrame); + void drawSetting(f32 fbWidth, f32 efbHeight); + +private: + nw4r::ut::Color mGraduationColor; // at 0x48 + f32 mPosX; // at 0x4C + f32 mPosY; // at 0x50 + f32 mWidth; // at 0x54 + f32 mHeight; // at 0x58 + TNw4rList mProcessBarList; // at 0x5C + DrawSync* mHeadDrawSync; // at 0x68 + DrawSync* mTailDrawSync; // at 0x6C + ProcessBar mBgProcessBar; // at 0x70 + CpuMonitor mCpuMonitor; // at 0x98 + CpuGpMonitor mCpuGpMonitor; // at 0xC4 + f32 mBgBarHeight; // at 0x140 + char UNK_0x144[0x4]; + u16 mNextToken; // at 0x148 + TBitFlag mFlags; // at 0x14A +}; } // namespace EGG diff --git a/include/egg/core/eggScene.h b/include/egg/core/eggScene.h index e4b095d..e8fb05e 100644 --- a/include/egg/core/eggScene.h +++ b/include/egg/core/eggScene.h @@ -1,10 +1,15 @@ #ifndef EGG_CORE_SCENE_H #define EGG_CORE_SCENE_H -#include "types_egg.h" +#include #include namespace EGG { + +// Forward declarations +class Heap; +class SceneManager; + class Scene #if defined(PACK_RESORT) : public Disposer @@ -12,61 +17,68 @@ class Scene { public: Scene(); + virtual ~Scene(); // at 0x8 - virtual ~Scene(); - inline virtual void calc() {} - inline virtual void draw() {} - inline virtual void enter() {} - inline virtual void exit() {} - inline virtual void reinit() {} - inline virtual void incoming_childDestroy() {} - inline virtual void outgoing_childCreate() {} + virtual void calc() {} // at 0xC + virtual void draw() {} // at 0x10 + virtual void enter() {} // at 0x14 + virtual void exit() {} // at 0x18 + virtual void reinit() {} // at 0x1C + virtual void incoming_childDestroy() {} // at 0x20 + virtual void outgoing_childCreate() {} // at 0x24 - inline Heap* getHeap() const { + Heap* getHeap() const { return mHeap; } - inline Heap* getHeap_Mem1() const { + Heap* getHeap_Mem1() const { return mHeap_Mem1; } - inline Heap* getHeap_Mem2() const { + Heap* getHeap_Mem2() const { return mHeap_Mem2; } - inline Heap* getHeap_Debug() const { + Heap* getHeap_Debug() const { return mHeap_Debug; } - inline Scene* getParentScene() const { + + Scene* getParentScene() const { return mParentScene; } - inline Scene* getChildScene() const { + void setParentScene(Scene* pScene) { + mParentScene = pScene; + } + + Scene* getChildScene() const { return mChildScene; } - inline s32 getSceneID() const { - return mSceneID; + void setChildScene(Scene* pScene) { + mChildScene = pScene; } - inline void setParentScene(Scene* pParentScene) { - mParentScene = pParentScene; + s32 getSceneID() const { + return mSceneID; } - inline void setChildScene(Scene* pChildScene) { - mChildScene = pChildScene; + void setSceneID(s32 id) { + mSceneID = id; } - inline void setSceneID(s32 sceneID) { - mSceneID = sceneID; + + SceneManager* getSceneMgr() const { + return mSceneMgr; } - inline void setSceneMgr(SceneManager* pSceneMgr) { + void setSceneMgr(SceneManager* pSceneMgr) { mSceneMgr = pSceneMgr; } private: Heap* mHeap; // at 0x4 Heap* mHeap_Mem1; // at 0x8 - Heap* mHeap_Mem2; // at 0xc + Heap* mHeap_Mem2; // at 0xC Heap* mHeap_Debug; // at 0x10 Scene* mParentScene; // at 0x14 Scene* mChildScene; // at 0x18 - s32 mSceneID; // at 0x1c + s32 mSceneID; // at 0x1C SceneManager* mSceneMgr; // at 0x20 }; + } // namespace EGG #endif diff --git a/include/egg/core/eggSceneCreator.h b/include/egg/core/eggSceneCreator.h index 6f55ef8..f39df9e 100644 --- a/include/egg/core/eggSceneCreator.h +++ b/include/egg/core/eggSceneCreator.h @@ -1,12 +1,18 @@ #ifndef EGG_CORE_SCENE_CREATOR_H #define EGG_CORE_SCENE_CREATOR_H -#include "types_egg.h" +#include namespace EGG { -struct SceneCreator { - virtual Scene* create(s32) = 0; - virtual UNKTYPE destroy(s32) = 0; + +// Forward declarations +class Scene; + +class SceneCreator { +public: + virtual Scene* create(s32 id) = 0; // at 0x8 + virtual void destroy(s32 id) = 0; // at 0xC }; + } // namespace EGG #endif diff --git a/include/egg/core/eggSceneManager.h b/include/egg/core/eggSceneManager.h index 54ff0cc..923d98b 100644 --- a/include/egg/core/eggSceneManager.h +++ b/include/egg/core/eggSceneManager.h @@ -1,92 +1,122 @@ #ifndef EGG_CORE_SCENE_MANAGER_H #define EGG_CORE_SCENE_MANAGER_H -#include "eggFader.h" -#include "eggHeap.h" -#include "eggSceneCreator.h" +#include namespace EGG { + +// Forward declarations +class Fader; +class Heap; +class SceneCreator; + class SceneManager { public: - enum eAfterFadeType { - AFTER_FADE_TYPE_CHANGE, - AFTER_FADE_TYPE_CHANGE_SIBLING, - AFTER_FADE_TYPE_CREATE_CHILD, - AFTER_FADE_TYPE_REINIT, - AFTER_FADE_TYPE_DESTROY_TO_SELECT, - AFTER_FADE_TYPE_NULL = -1 - }; - - virtual void calc(); - virtual void draw(); + explicit SceneManager(SceneCreator* pSceneCreator); + ~SceneManager(); - virtual void calcCurrentScene(); - virtual void calcCurrentFader(); + virtual void calc(); // at 0x8 + virtual void draw(); // at 0xC - virtual void drawCurrentScene(); - virtual void drawCurrentFader(); + virtual void calcCurrentScene(); // at 0x10 + virtual void calcCurrentFader(); // at 0x14 - virtual void createDefaultFader(); + virtual void drawCurrentScene(); // at 0x18 + virtual void drawCurrentFader(); // at 0x1C - SceneManager(SceneCreator*); - ~SceneManager(); + virtual void createDefaultFader(); // at 0x20 - UNKTYPE fadeIn(); - bool fadeOut(); // inlined + bool fadeIn(); + bool fadeOut(); - void reinitCurrentScene(); // inlined + void reinitCurrentScene(); bool reinitCurrentSceneAfterFadeOut(); - void changeScene(s32); - bool changeSceneAfterFadeOut(s32); - - void changeSiblingScene(s32); // inlined - bool changeSiblingSceneAfterFadeOut(s32); - - void createScene(s32, Scene*); - void createChildScene(s32, Scene*); - bool createChildSceneAfterFadeOut(s32, Scene*); + void changeScene(s32 id); + bool changeSceneAfterFadeOut(s32 id); - void destroyToSelectSceneID(s32); // inlined - bool destroyToSelectSceneIDAfterFadeOut(s32); + void changeSiblingScene(s32 id); + bool changeSiblingSceneAfterFadeOut(s32 id); + void changeSiblingScene(); - UNKTYPE destroyScene(Scene*); + void createScene(s32 id, Scene* pParent); + void createChildScene(s32 id, Scene* pParent); + bool createChildSceneAfterFadeOut(s32 id, Scene* pParent); - void incomingCurrentScene(); // inlined + bool destroyCurrentSceneNoIncoming(bool destroyRoot); + bool destroyToSelectSceneID(s32 id); + bool destroyToSelectSceneIDAfterFadeOut(s32 id); + void destroyScene(Scene* pScene); - void setupNextSceneID(); // inlined - - void outgoingParentScene(Scene*); // inlined + void createChildSceneCurrent(s32 id) { + createChildScene(id, getCurrentScene()); + } - Scene* findParentScene(s32); + void setCreator(SceneCreator* pSceneCreator) { + mSceneCreator = pSceneCreator; + } - inline Scene* getCurrentScene() const { + Scene* getCurrentScene() const { return mCurrentScene; } - inline s32 getCurrentSceneID() const { + + void setNextSceneID(s32 id) { + mNextSceneID = id; + } + + s32 getCurrentSceneID() const { return mCurrentSceneID; } - static inline Heap* getHeapForCreateScene_Mem1() { + bool isStoppingAfterFade() { + return mAfterFadeType == AFTER_FADE_TYPE_NONE ? true : false; + } + + static Heap* getHeapForCreateScene_Mem1() { return sHeapMem1_ForCreateScene; } - static inline Heap* getHeapForCreateScene_Mem2() { + static Heap* getHeapForCreateScene_Mem2() { return sHeapMem2_ForCreateScene; } - static inline Heap* getHeapForCreateScene_Debug() { + static Heap* getHeapForCreateScene_Debug() { return sHeapDebug_ForCreateScene; } +protected: + enum eAfterFadeType { + AFTER_FADE_TYPE_CHANGE, + AFTER_FADE_TYPE_CHANGE_SIBLING, + AFTER_FADE_TYPE_CREATE_CHILD, + AFTER_FADE_TYPE_REINIT, + AFTER_FADE_TYPE_DESTROY_TO_SELECT, + AFTER_FADE_TYPE_NONE = -1 + }; + + enum eRootHeapType { ROOT_HEAP_TYPE_MEM1, ROOT_HEAP_TYPE_MEM2 }; + +protected: + void incomingCurrentScene(); + void setupNextSceneID(); + void outgoingParentScene(Scene* pParent); + Scene* findParentScene(s32 id); + + void setAfterFadeType(eAfterFadeType type) { + mAfterFadeType = type; + } + void resetAfterFadeType() { + mAfterFadeType = AFTER_FADE_TYPE_NONE; + } + private: SceneCreator* mSceneCreator; // at 0x4 - UNKWORD WORD_0x8; // at 0x8 - Scene* mCurrentScene; // at 0xc - Scene* PARENT_0x10; // at 0x10 + char UNK_0x8[0xC - 0x8]; // at 0x8 + Scene* mCurrentScene; // at 0xC + Scene* mParentScene; // at 0x10 s32 mNextSceneID; // at 0x14 s32 mCurrentSceneID; // at 0x18 - s32 mPreviousSceneID; // at 0x1c + s32 mPreviousSceneID; // at 0x1C eAfterFadeType mAfterFadeType; // at 0x20 Fader* mCurrentFader; // at 0x24 - UNKWORD INT_0x28; // at 0x28 + eRootHeapType mRootHeapType; // at 0x28 static u16 sHeapOptionFlg; @@ -94,6 +124,7 @@ class SceneManager { static Heap* sHeapMem2_ForCreateScene; static Heap* sHeapDebug_ForCreateScene; }; + } // namespace EGG #endif diff --git a/include/egg/core/eggSingleton.h b/include/egg/core/eggSingleton.h new file mode 100644 index 0000000..f0c1ddc --- /dev/null +++ b/include/egg/core/eggSingleton.h @@ -0,0 +1,57 @@ +#ifndef EGG_CORE_SINGLETON_H +#define EGG_CORE_SINGLETON_H +#include + +#include + +#include + +/** + * @brief Declares functions and data for a disposable singleton class + */ +#define EGG_SINGLETON_DECL(T) \ +protected: \ + class T__Disposer : public EGG::Disposer { \ + public: \ + virtual ~T__Disposer(); /* at 0x8 */ \ + }; \ + \ + T__Disposer mDisposer; \ + \ +public: \ + static T* createInstance(); \ + static void deleteInstance(); \ + \ + static T* instance() { \ + return sInstance; \ + } \ + \ +protected: \ + static T* sInstance; + +/** + * @brief Defines functions and data for a disposable singleton class + */ +#define EGG_SINGLETON_IMPL(T) \ + T::T__Disposer::~T__Disposer() { \ + T::deleteInstance(); \ + } \ + \ + T* T::createInstance() { \ + if (sInstance == NULL) { \ + sInstance = new T(); \ + } else { \ + EGG_ASSERT_MSG(false, "Create Singleton Twice (%s) : addr %x\n", \ + #T, sInstance); \ + } \ + \ + return sInstance; \ + } \ + \ + void T::deleteInstance() { \ + sInstance = NULL; \ + } \ + \ + T* T::sInstance = NULL; + +#endif diff --git a/include/egg/core/eggStopWatch.h b/include/egg/core/eggStopWatch.h new file mode 100644 index 0000000..200a76c --- /dev/null +++ b/include/egg/core/eggStopWatch.h @@ -0,0 +1,47 @@ +#ifndef EGG_CORE_STOP_WATCH_H +#define EGG_CORE_STOP_WATCH_H +#include + +#include + +#include + +namespace EGG { + +class Stopwatch : public Watch { +public: + Stopwatch() : mEndTick(0) {} + + void start() { + Watch::start(); + mEndTick = 0; + } + + void stop() { + if (isStarted()) { + mEndTick = OSGetTick(); + } + } + + u32 getMeasureTick() { + if (isStarted() && mEndTick != 0) { + return mEndTick - getStartTick(); + } + + return 0; + } + + u32 getStopTick() { + return mEndTick; + } + void setStopTick(u32 tick) { + mEndTick = tick; + } + +private: + u32 mEndTick; // at 0x4 +}; + +} // namespace EGG + +#endif diff --git a/include/egg/core/eggStream.h b/include/egg/core/eggStream.h index 6ad6bac..51250e7 100644 --- a/include/egg/core/eggStream.h +++ b/include/egg/core/eggStream.h @@ -1,87 +1,131 @@ #ifndef EGG_CORE_STREAM_H #define EGG_CORE_STREAM_H -#include "eggBitFlag.h" -#include "types_egg.h" +#include + +#include namespace EGG { + +/****************************************************************************** + * + * Stream + * + ******************************************************************************/ + class Stream { public: Stream(); - virtual ~Stream(); // at 0x8 - virtual void read(u8*, u32) = 0; // at 0xC - virtual void write(u8*, u32) = 0; // at 0x10 - virtual bool eof() = 0; // at 0x14 - - u8 read_u8(); - void write_u8(u8); - s8 read_s8(); - void write_s8(s8); - u16 read_u16(); - void write_u16(u16); - s16 read_s16(); - void write_s16(s16); - u32 read_u32(); - void write_u32(u32); - s32 read_s32(); - void write_s32(s32); - f32 read_float(); - void write_float(f32); - const char* readString(char*, int); - void writeString(char*); + virtual ~Stream(); // at 0x8 - void copyToTextBuffer(); - char skipSpace(); - void printf(char*, ...); - void skipUntilCRLF(); - const char* getNextToken(); - bool isSpace(char); - bool isCRLF(char); - bool isUpperSJIS(char); + virtual void read(u8* pDst, u32 size) = 0; // at 0xC + virtual void write(u8* pSrc, u32 size) = 0; // at 0x10 + virtual bool eof() = 0; // at 0x14 + +/** + * @brief Helper for declaring stream functions for primitive types + */ +#define TYPE_FUNC_DECL(T) \ + T read_##T(); \ + void write_##T(T value); \ + void read_##T(T& rValue) { \ + rValue = read_##T(); \ + } + + TYPE_FUNC_DECL(u8); + TYPE_FUNC_DECL(s8); + TYPE_FUNC_DECL(u16); + TYPE_FUNC_DECL(s16); + TYPE_FUNC_DECL(u32); + TYPE_FUNC_DECL(s32); + TYPE_FUNC_DECL(float); + +#undef TYPE_FUNC_DECL + + f32 read_f32() { + return read_float(); + } + void write_f32(f32 value) { + write_float(value); + } + void read_f32(f32& rValue) { + rValue = read_f32(); + } + + const char* readString(char* pDst, int maxlen); + void writeString(char* pStr); + + bool isSpace(char ch); + bool isCRLF(char ch); + bool isUpperSJIS(char ch); void setTextMode() { - mFlags.setBit(0); + mFlags.setBit(BIT_TEXT_MODE); } bool isTextMode() { - return mFlags.onBit(0); + return mFlags.onBit(BIT_TEXT_MODE); } void setBinMode() { - mFlags.resetBit(0); + mFlags.resetBit(BIT_TEXT_MODE); } bool isBinMode() { - return !mFlags.onBit(0); + return !isTextMode(); } -protected: - void _read(void*, u32); - void _write(void*, u32); - u8 _readByte(); - void _writeByte(u8); + s32 getPosition() const { + return mPosition; + } protected: - bool mIsTokenReady; // at 0x4 - u32 mPosition; // at 0x8 - TBitFlag mFlags; // at 0xC - char* mTextBuffer; // at 0x10 - u32 mTextBufferSize; // at 0x14 - UNKWORD WORD_0x18; - bool mAllowComments; // at 0x1C - - static const int sTextBufferSize = 1024; - static char sTextBuffer[sTextBufferSize]; + bool mIsTokenReady; // at 0x4 + s32 mPosition; // at 0x8 + TBitFlag mFlags; // at 0xC + char* mTextBuffer; // at 0x10 + s32 mTextBufferSize; // at 0x14 + u32 mGroupIndentLevel; // at 0x18 + bool mAllowComments; // at 0x1C + + static const int TEXT_BUFFER_SIZE = 1024; + static char sTextBuffer[TEXT_BUFFER_SIZE]; + +private: + enum { + BIT_TEXT_MODE, + }; + +private: + void skipUntilCRLF(); + void copyToTextBuffer(); + const char* getNextToken(); + + char skipSpace(); + void printf(char* pFmt, ...); + + void _read(void* pDst, u32 size); + void _write(void* pSrc, u32 size); + + u8 _readByte(); + void _writeByte(u8 value); }; +/****************************************************************************** + * + * RamStream + * + ******************************************************************************/ + class RamStream : public Stream { public: - RamStream(u8*, u32); - ~RamStream(); // at 0x8 - virtual void read(u8*, u32); // at 0xC - virtual void write(u8*, u32); // at 0x10 - virtual bool eof(); // at 0x14 + RamStream(u8* pBuffer, u32 size); + + virtual void read(u8* pDst, u32 size); // at 0xC + virtual void write(u8* pSrc, u32 size); // at 0x10 + virtual bool eof(); // at 0x14 private: - u8* mDataBlk; // at 0x20 - u32 mDataSize; // at 0x24 + u8* mBuffer; // at 0x20 + u32 mBufferSize; // at 0x24 }; + } // namespace EGG #endif diff --git a/include/egg/core/eggSystem.h b/include/egg/core/eggSystem.h index 9db5db8..6043fe4 100644 --- a/include/egg/core/eggSystem.h +++ b/include/egg/core/eggSystem.h @@ -1,12 +1,22 @@ #ifndef EGG_CORE_SYSTEM_H #define EGG_CORE_SYSTEM_H -#include "eggHeap.h" +#include namespace EGG { +// Forward declarations +class Display; +class Heap; +class IAudioMgr; +class PerformanceView; +class SceneManager; +class Video; +class XfbManager; + class ConfigurationData { public: - ConfigurationData(u32 systemHeapSize) : mSystemHeapSize(systemHeapSize) {} + explicit ConfigurationData(u32 systemHeapSize) + : mSystemHeapSize(systemHeapSize) {} virtual Video* getVideo() = 0; // at 0x8 virtual Heap* getSystemHeap() = 0; // at 0xC @@ -24,21 +34,19 @@ class ConfigurationData { Heap* getRootHeapMem1() { return mRootHeapMem1; } - Heap* getRootHeapMem2() { return mRootHeapMem2; } - Heap* getRootHeapDebug() { return mRootHeapDebug; } private: - void* mMem1ArenaLo; // at 0x4 - void* mMem1ArenaHi; // at 0x8 - void* mMem2ArenaLo; // at 0xC - void* mMem2ArenaHi; // at 0x10 - u32 mMemTotalSize; // at 0x14 + void* mMem1Start; // at 0x4 + void* mMem1End; // at 0x8 + void* mMem2Start; // at 0xC + void* mMem2End; // at 0x10 + u32 mMemorySize; // at 0x14 Heap* mRootHeapMem1; // at 0x18 Heap* mRootHeapMem2; // at 0x1C Heap* mRootHeapDebug; // at 0x20 @@ -46,15 +54,15 @@ class ConfigurationData { protected: Heap* mSystemHeap; // at 0x24 Thread* mParentThread; // at 0x28 - void* PTR_0x2C; - void* PTR_0x30; - u32 mSystemHeapSize; // at 0x34 + void* mCodeStart; // at 0x2C + void* mCodeEnd; // at 0x30 + u32 mSystemHeapSize; // at 0x34 }; class BaseSystem { public: - static void configure(ConfigurationData* data) { - mConfigData = data; + static void configure(ConfigurationData* pConfigData) { + mConfigData = pConfigData; } static Video* getVideo() { @@ -64,11 +72,9 @@ class BaseSystem { static Heap* getRootHeapMem1() { return mConfigData->getRootHeapMem1(); } - static Heap* getRootHeapMem2() { - return mConfigData->getRootHeapMem1(); + return mConfigData->getRootHeapMem2(); } - static Heap* getRootHeapDebug() { return mConfigData->getRootHeapDebug(); } diff --git a/include/egg/core/eggTaskThread.h b/include/egg/core/eggTaskThread.h index ddc78f6..d64c8e7 100644 --- a/include/egg/core/eggTaskThread.h +++ b/include/egg/core/eggTaskThread.h @@ -1,64 +1,83 @@ #ifndef EGG_CORE_TASK_THREAD_H #define EGG_CORE_TASK_THREAD_H -#include "eggHeap.h" -#include "eggThread.h" +#include + +#include namespace EGG { + +// Forward declarations +class Heap; + class TaskThread : public Thread { public: - typedef void (*TFunction)(void*); + typedef void (*TaskFunc)(void* pTaskArg); struct TJob { - TFunction mFunction; // at 0x0 - void* WORD_0x4; - OSMessage MSG_0x8; - TFunction mEnterFunction; // at 0xc - TFunction mExitFunction; // at 0x10 - TFunction TFUNCTION_0x14; - - inline TJob() - : mEnterFunction(NULL), mExitFunction(NULL), TFUNCTION_0x14(NULL) {} - - inline void clearFunctions() { - mFunction = NULL; - mEnterFunction = NULL; - mExitFunction = NULL; - TFUNCTION_0x14 = NULL; + TaskFunc pTask; // at 0x0 + void* pTaskArg; // at 0x4 + OSMessage endMesg; // at 0x8 + + TaskFunc pOnEnter; // at 0xC + TaskFunc pOnExit; // at 0x10 + TaskFunc pOnDone; // at 0x14 + + TJob() : pOnEnter(NULL), pOnExit(NULL), pOnDone(NULL) {} + + void clearFunctions() { + pTask = NULL; + pOnEnter = NULL; + pOnExit = NULL; + pOnDone = NULL; } }; - TaskThread(int, int, u32); +public: + static TaskThread* create(int capacity, int priority, u32 stackSize, + Heap* pHeap); + static OSMessageQueue* createTaskEndMessageQueue(int size, Heap* pHeap); - static TaskThread* create(int, int, u32, Heap*); + TaskThread(int capacity, int priority, u32 stackSize); + virtual ~TaskThread(); // at 0x8 - bool request(TFunction, void*, OSMessage); + virtual void* run(); // at 0xC - static OSMessageQueue* createTaskEndMessageQueue(int, Heap*); + virtual void onEnter(); // at 0x10 + virtual void onExit(); // at 0x14 + bool request(TaskFunc pTask, void* pTaskArg, OSMessage endMesg); bool isTaskExist() const; - ~TaskThread(); + static OSMessage waitQueueMessage(OSMessageQueue* pQueue, BOOL* pSuccess); - void onEnter(); - void onExit(); + bool isTaskWorking() const { + return mCurrentJob != NULL; + } - void* run(); + void setEndMessageQueue(OSMessageQueue* pQueue) { + mEndMesgQueue = pQueue; + } + OSMessage waitTaskEndMessage(BOOL* pSuccess) { + OSMessage msg; + *pSuccess = OSReceiveMessage(mEndMesgQueue, &msg, 0); + return msg; + } +private: TJob* findBlank(); - static OSMessage waitQueueMessage(OSMessageQueue*, BOOL*); - private: - TJob* mCurrentJob; // at 0x44 - TJob* mJobs; // at 0x48 - int mJobCount; // at 0x4c - OSMessageQueue* MSG_QUEUE_0x50; + TJob* mCurrentJob; // at 0x44 + TJob* mJobList; // at 0x48 + int mJobNum; // at 0x4C + OSMessageQueue* mEndMesgQueue; // at 0x50 static OSMessage* sEndMesgBuffer; static int sEndMesgBufSize; static OSMessageQueue sEndMesgQueue; }; + } // namespace EGG #endif diff --git a/include/egg/core/eggThread.h b/include/egg/core/eggThread.h index 5147c86..9100a90 100644 --- a/include/egg/core/eggThread.h +++ b/include/egg/core/eggThread.h @@ -1,57 +1,89 @@ #ifndef EGG_CORE_THREAD_H #define EGG_CORE_THREAD_H -#include "types_egg.h" -#include "ut_list.h" +#include -#include -#include +#include + +#include namespace EGG { +// Forward declarations +class Heap; + class Thread { public: - Thread(u32, int, int, Heap*); - Thread(OSThread*, int); - static Thread* findThread(OSThread*); // inlined - void initialize(); - static UNKTYPE switchThreadCallback(OSThread*, OSThread*); - void setCommonMesgQueue(int, Heap*); // inlined - static void* start(void*); - virtual ~Thread(); // at 0x8 - virtual void* run(); // at 0xC - virtual void onEnter(); // at 0x10 - virtual void onExit(); // at 0x14 - - bool sendMessage(OSMessage message) { - return OSSendMessage(&mMesgQueue, message, 0); - } + static void initialize(); + static Thread* findThread(OSThread* pOSThread); + + Thread(u32 stackSize, int capacity, int priority, Heap* pHeap = NULL); + Thread(OSThread* pOSThread, int capacity); + virtual ~Thread(); // at 0x8 + + virtual void* run() { + return NULL; + } // at 0xC + + virtual void onEnter() {} // at 0x10 + virtual void onExit() {} // at 0x14 void resume() { OSResumeThread(mOSThread); } - OSMessage waitMessageBlock() { - OSMessage message; - OSReceiveMessage(&mMesgQueue, &message, 1); - return message; + bool sendMessage(OSMessage msg) { + return OSSendMessage(&mMesgQueue, msg, 0); + } + bool jamMessage(OSMessage msg) { + return OSJamMessage(&mMesgQueue, msg, 0); } OSMessage waitMessage(BOOL* pSuccess) { - OSMessage message; - *pSuccess = OSReceiveMessage(&mMesgQueue, &message, 0); - return message; + OSMessage msg; + *pSuccess = OSReceiveMessage(&mMesgQueue, &msg, 0); + return msg; + } + OSMessage waitMessageBlock() { + OSMessage msg; + OSReceiveMessage(&mMesgQueue, &msg, OS_MSG_BLOCKING); + return msg; + } + + OSThread* getOSThread() const { + return mOSThread; + } + + void* getStack() const { + return mStackMemory; + } + u32 getStackSize() const { + return mStackSize; + } + + static nw4r::ut::List& getList() { + return sThreadList; } private: - Heap* mHeap; // at 0x4 + void setCommonMesgQueue(int capacity, Heap* pHeap); + + static void switchThreadCallback(OSThread* pCurrOSThread, + OSThread* pNewOSThread); + static void* start(void* pArg); + +private: + Heap* mContainHeap; // at 0x4 OSThread* mOSThread; // at 0x8 OSMessageQueue mMesgQueue; // at 0xC OSMessage* mMesgBuffer; // at 0x2C - UNKWORD mMesgCount; // at 0x30 + int mMesgNum; // at 0x30 void* mStackMemory; // at 0x34 u32 mStackSize; // at 0x38 - nw4r::ut::Link mNode; // at 0x3C +public: + NW4R_UT_LIST_LINK_DECL(); // at 0x3C + +private: static nw4r::ut::List sThreadList; }; diff --git a/include/egg/core/eggVideo.h b/include/egg/core/eggVideo.h index 397bc0d..afe9fb7 100644 --- a/include/egg/core/eggVideo.h +++ b/include/egg/core/eggVideo.h @@ -1,38 +1,60 @@ #ifndef EGG_CORE_VIDEO_H #define EGG_CORE_VIDEO_H -#include "eggBitFlag.h" -#include "types_egg.h" +#include + +#include #include #include -#define FRAMERATE_50HZ 50.0f -#define FRAMERATE_60HZ 59.94f - namespace EGG { -struct Video { - Video(GXRenderModeObj* obj) : mRenderMode(NULL), mFlags(), mOSTick(0) { - (void)initialize(obj); + +class Video { +public: + explicit Video(GXRenderModeObj* pRenderMode) + : mRenderMode(NULL), mConfiguredTime(0) { + + initialize(pRenderMode); } + void initialize(GXRenderModeObj* pRenderMode); + GXRenderModeObj* configure(GXRenderModeObj* pRenderMode); + + static u32 getTickPerVRetrace(u32 tvFormat); + static u32 getTickPerVRetrace(); + + static const GXRenderModeObj* getStandardRenderModeObj(); + bool isBlack() { - return mFlags.onBit(0); + return mFlags.offBit(BIT_VIDEO_SHOW); } void changeBlack() { - VISetBlack(isBlack() ? FALSE : TRUE); - mFlags.toggleBit(0); + VISetBlack(mFlags.offBit(BIT_VIDEO_SHOW)); + mFlags.toggleBit(BIT_VIDEO_SHOW); } - GXRenderModeObj* initialize(GXRenderModeObj*); - GXRenderModeObj* configure(GXRenderModeObj*); - static u32 getTickPerVRetrace(u32); - static u32 getTickPerVRetrace(); - static GXRenderModeObj* getStandardRenderModeObj(); + GXRenderModeObj* getRenderModeObj() { + return mRenderMode; + } + u16 getFbWidth() { + return mRenderMode->fbWidth; + } + u16 getEfbHeight() { + return mRenderMode->efbHeight; + } + +private: + enum { + BIT_VIDEO_SHOW, + }; + +private: GXRenderModeObj* mRenderMode; // at 0x0 - TBitFlag mFlags; - s32 mOSTick; // at 0x8 + TBitFlag mFlags; // at 0x4 + s32 mConfiguredTime; // at 0x8 }; + } // namespace EGG #endif diff --git a/include/egg/core/eggWatch.h b/include/egg/core/eggWatch.h new file mode 100644 index 0000000..9e75fd0 --- /dev/null +++ b/include/egg/core/eggWatch.h @@ -0,0 +1,39 @@ +#ifndef EGG_CORE_WATCH_H +#define EGG_CORE_WATCH_H +#include + +#include + +namespace EGG { + +class Watch { +public: + Watch() { + reset(); + } + + void reset() { + mStartTick = 0; + } + void start() { + mStartTick = OSGetTick(); + } + + bool isStarted() { + return mStartTick != 0; + } + + u32 getStartTick() { + return mStartTick; + } + void setStartTick(u32 tick) { + mStartTick = tick; + } + +private: + u32 mStartTick; // at 0x0 +}; + +} // namespace EGG + +#endif diff --git a/include/egg/core/eggXfb.h b/include/egg/core/eggXfb.h index 096385f..fc0eae8 100644 --- a/include/egg/core/eggXfb.h +++ b/include/egg/core/eggXfb.h @@ -1,39 +1,33 @@ #ifndef EGG_CORE_XFB_H #define EGG_CORE_XFB_H -#include "types_egg.h" +#include namespace EGG { + +// Forward declarations +class XfbManager; + class Xfb { -public: - static u32 calcBufferSize(u16, u16); + friend class XfbManager; - Xfb(Heap*); - void init(u16, u16, Heap*); +public: + explicit Xfb(Heap* pHeap = NULL); - u16 getWidth() const { + u16 getWidth() { return mWidth; } - u16 getHeight() const { + u16 getHeight() { return mHeight; } - u8* getBuffer() const { + u8* getBuffer() { return mBuffer; } - Xfb* getPrev() const { - return mPrev; - } - void setPrev(Xfb* xfb) { - mPrev = xfb; - } +private: + void init(u16 width, u16 height, Heap* pHeap); - Xfb* getNext() const { - return mNext; - } - void setNext(Xfb* xfb) { - mNext = xfb; - } + static u32 calcBufferSize(u16 width, u16 height); private: u16 mWidth; // at 0x0 @@ -43,6 +37,7 @@ class Xfb { Xfb* mPrev; // at 0x8 Xfb* mNext; // at 0xC }; + } // namespace EGG #endif diff --git a/include/egg/core/eggXfbManager.h b/include/egg/core/eggXfbManager.h index fc12ee9..002e4d2 100644 --- a/include/egg/core/eggXfbManager.h +++ b/include/egg/core/eggXfbManager.h @@ -1,29 +1,44 @@ -#ifndef EGG_CORE_XFBMANAGER_H -#define EGG_CORE_XFBMANAGER_H -#include "eggXfb.h" -#include "types_egg.h" +#ifndef EGG_CORE_XFB_MANAGER_H +#define EGG_CORE_XFB_MANAGER_H +#include namespace EGG { + +// Forward declarations +class Xfb; + class XfbManager { public: - XfbManager(Heap* heap) {} - ~XfbManager() {} - - bool isReadytoCopy() const { - return mListTail != mShowXfb && mListTail != mListHead; - } + XfbManager() + : mQueueFront(NULL), + mQueueEnd(NULL), + mCopiedXfb(NULL), + mShowXfb(NULL) {} - bool attach(Xfb*); - void copyEFB(bool); + bool attach(Xfb* pXfb); + void copyEFB(bool clearEfb); void setNextFrameBuffer(); void postVRetrace(); + bool isReadytoCopy() { + return mQueueEnd != mCopiedXfb && mQueueEnd != mQueueFront; + } + + Xfb* getShowXfb() { + return mShowXfb; + } + Xfb* getCopiedXfb() { + return mCopiedXfb; + } + private: - Xfb* mListHead; // at 0x0 - Xfb* mListTail; // at 0x4 - Xfb* mCopiedXfb; // at 0x8 - Xfb* mShowXfb; // at 0xC + Xfb* mQueueFront; // at 0x0 + Xfb* mQueueEnd; // at 0x4 + + Xfb* mShowXfb; // at 0x8 + Xfb* mCopiedXfb; // at 0xC }; + } // namespace EGG #endif diff --git a/include/egg/gfx.h b/include/egg/gfx.h index 62ee78d..63f511a 100644 --- a/include/egg/gfx.h +++ b/include/egg/gfx.h @@ -1,7 +1,16 @@ #ifndef EGG_PUBLIC_GFX_H #define EGG_PUBLIC_GFX_H -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #endif diff --git a/include/egg/gfx/eggAnalizeDL.h b/include/egg/gfx/eggAnalizeDL.h index 2fc069f..074b822 100644 --- a/include/egg/gfx/eggAnalizeDL.h +++ b/include/egg/gfx/eggAnalizeDL.h @@ -1,57 +1,85 @@ #ifndef EGG_GFX_ANALIZE_DL_H #define EGG_GFX_ANALIZE_DL_H -#include "eggAssert.h" -#include "g3d_resshp.h" -#include "types_egg.h" +#include + +#include + +#include +#include + +#include namespace EGG { + class AnalizeDL { public: - enum EResultType { TYPE_0, TYPE_1, TYPE_2, TYPE_3, TYPE_VERTEX }; - - struct Result { - int m_type; // at 0x0 - u16 SHORT_0x4; - u16 SHORT_0x6; - u16 SHORT_0x8; - u16 SHORT_0xA; - u16 SHORT_0xC; - u16 SHORT_0xE; - u16 SHORT_0x10; - u16 SHORT_0x12; - u16 SHORT_0x14; - u16 SHORT_0x16; - u16 SHORT_0x18; - u16 SHORT_0x1A; - u16 SHORT_0x1C; - u16 SHORT_0x1E; - u16 SHORT_0x20; - u16 SHORT_0x22; - u16 SHORT_0x24; - u16 SHORT_0x26; - u16 SHORT_0x28; - u16 SHORT_0x2A; + enum CmdType { + TYPE_NONE, + TYPE_POSMTXINDX, + TYPE_NRMMTXINDX, + TYPE_PRIMITIVE, + TYPE_VERTEX, + TYPE_NOOP + }; + + struct VtxResult { + static const int PNMTX_NUM = (GX_TEXMTX0 - GX_PNMTX0) / 3; + + CmdType m_type; // at 0x0 + s16 m_posMtxIdx[PNMTX_NUM]; // at 0x4 + s16 m_nrmMtxIdx[PNMTX_NUM]; // at 0x18 u32 WORD_0x2C; - u32 WORD_0x30; - u32 WORD_0x34; - int WORD_0x38; - int WORD_0x3C; - nw4r::math::VEC3 VEC3_0x40; + u8 m_primitive; // at 0x30 + u16 m_vtxNum; // at 0x32 + u16 m_vtxRemain; // at 0x34 + s32 m_mtxIdx; // at 0x38 + s32 m_vtxIdx; // at 0x3C + nw4r::math::VEC3 m_vtxPos; // at 0x40 }; public: - static void FUN_800854f8(const void*, nw4r::g3d::ResShp); - static int FUN_80085670(const void*); + AnalizeDL(const nw4r::g3d::ResShp shp); + + CmdType advance(); - static Result* getVtxResult() { + const VtxResult& getVtxResult() const { #line 115 EGG_ASSERT(s_result.m_type == TYPE_VERTEX); - return &s_result; + return s_result; } private: - static Result s_result; + struct VtxPosArray { + u8 m_stride; // at 0x0 + const void* m_base; // at 0x4 + }; + +private: + void configure(); + +private: + const u8* m_DL; // at 0x0 + const u8* m_DLPtr; // at 0x4 + + u8 BYTE_0x8; + u8 BYTE_0x9; + + u8 m_vtxDescSize; // at 0xA + u8 m_vtxAttrSize; // at 0xB + u16 m_vtxAttrSend; // at 0xC + + static const s8 s_attrTypeSize[]; + static const u8 s_compTypeSize[]; + + static GXVtxDescList s_vtxDesc[nw4r::g3d::ResPrePrimDL::SIZE_GXVTXDESCLIST]; + + static GXVtxAttrFmtList + s_vtxAttr[nw4r::g3d::ResPrePrimDL::SIZE_GXVTXATTRFMTLIST]; + + static VtxPosArray s_vtxPos; + static VtxResult s_result; }; + } // namespace EGG #endif diff --git a/include/egg/gfx/eggCapTexture.h b/include/egg/gfx/eggCapTexture.h index 91311a7..4a1226f 100644 --- a/include/egg/gfx/eggCapTexture.h +++ b/include/egg/gfx/eggCapTexture.h @@ -1,40 +1,125 @@ #ifndef EGG_GFX_CAP_TEXTURE_H #define EGG_GFX_CAP_TEXTURE_H -#include "eggCpuTexture.h" -#include "types_egg.h" +#include + +#include #include namespace EGG { + class CapTexture : public CpuTexture { public: CapTexture() {} CapTexture(u16 w, u16 h, GXTexFmt fmt) : CpuTexture(w, h, fmt) {} - virtual ~CapTexture() {} // at 0x8 - virtual void configure(); // at 0xC - virtual void load(GXTexMapID) const; // at 0x14 + virtual ~CapTexture() {} // at 0x8 + virtual void configure(); // at 0xC + virtual void load(GXTexMapID map); // at 0x14 - void capture(u16, u16, bool, int); + void capture(u16 x, u16 y, bool mipmap = false, int format = -1); GXTexMapID getLoadMap() const { return mLoadMap; } - void setClearColor(const GXColor& c) { - mClearColor = c; + void setClearColor(const GXColor& rColor) { + mClearColor = rColor; + } + void setClearZ(u32 clearZ) { + mClearZ = clearZ; + } + + void setVFilter(const u8* const pFilter) { + enableVFilter(); + setVFilterInternal(pFilter); + } + void setSmoothVFilter() { + enableVFilter(); + setVFilterInternal(scVFilterSmooth); + } + void setSharpVFilter() { + setVFilterInternal(scVFilterSharp); + } + + bool checkColorUpdate() const { + return testFlag(FLAG_COLOR_UPDATE); + } + void enableColorUpdate() { + setFlag(FLAG_COLOR_UPDATE); + } + void disableColorUpdate() { + clearFlag(FLAG_COLOR_UPDATE); + } + + bool checkAlphaUpdate() const { + return testFlag(FLAG_ALPHA_UPDATE); + } + void enableAlphaUpdate() { + setFlag(FLAG_ALPHA_UPDATE); + } + void disableAlphaUpdate() { + clearFlag(FLAG_ALPHA_UPDATE); + } + + bool checkZBufferUpdate() const { + return testFlag(FLAG_ZBUFFER_UPDATE); + } + void enableZBufferUpdate() { + setFlag(FLAG_ZBUFFER_UPDATE); + } + void disableZBufferUpdate() { + clearFlag(FLAG_ZBUFFER_UPDATE); + } + + bool checkVFilterEnable() const { + return testFlag(FLAG_VFILTER_ENABLE); + } + void enableVFilter() { + setFlag(FLAG_VFILTER_ENABLE); + } + void disableVFilter() { + clearFlag(FLAG_VFILTER_ENABLE); + } + + bool checkPixModeSync() const { + return testFlag(FLAG_PIXMODE_SYNC); + } + void enablePixModeSync() { + setFlag(FLAG_PIXMODE_SYNC); + } + void disablePixModeSync() { + clearFlag(FLAG_PIXMODE_SYNC); } private: - mutable GXTexMapID mLoadMap; // at 0x18 - GXColor mClearColor; // at 0x1C - u32 mClearZ; // at 0x20 - u8 mCopyFilterArg1[7]; // at 0x24 - - static const u8 scCopyFilterArg0[24]; - static u8 sCopyFilterArg1_0[7]; - static u8 sCopyFilterArg1_1[7]; + enum { + FLAG_COLOR_UPDATE = 1 << 3, + FLAG_ALPHA_UPDATE = 1 << 4, + FLAG_ZBUFFER_UPDATE = 1 << 5, + FLAG_VFILTER_ENABLE = 1 << 6, + FLAG_PIXMODE_SYNC = 1 << 7, + }; + +private: + void setVFilterInternal(const u8* const pFilter) { + for (int i = 0; i < GX_VFILTER_SZ; i++) { + mVerticalFilter[i] = pFilter[i]; + } + } + +private: + GXTexMapID mLoadMap; // at 0x18 + GXColor mClearColor; // at 0x1C + u32 mClearZ; // at 0x20 + u8 mVerticalFilter[GX_VFILTER_SZ]; // at 0x24 + + static const u8 scSamplePattern[12][2]; + + static const u8 scVFilterSmooth[GX_VFILTER_SZ]; + static const u8 scVFilterSharp[GX_VFILTER_SZ]; }; + } // namespace EGG #endif diff --git a/include/egg/gfx/eggCpuTexture.h b/include/egg/gfx/eggCpuTexture.h index c52a989..f0d28de 100644 --- a/include/egg/gfx/eggCpuTexture.h +++ b/include/egg/gfx/eggCpuTexture.h @@ -1,79 +1,70 @@ #ifndef EGG_GFX_CPU_TEXTURE_H #define EGG_GFX_CPU_TEXTURE_H -#include "eggAssert.h" -#include "types_egg.h" +#include + +#include + +#include #include namespace EGG { + class CpuTexture { -protected: - u16 mFlags; // at 0x0 private: + u16 mFlags; // at 0x0 u16 mWidth; // at 0x2 u16 mHeight; // at 0x4 - u8 mTexFormat; // at 0x6 + u8 mFormat; // at 0x6 u8 mWrapS; // at 0x7 u8 mWrapT; // at 0x8 - u8 mMinFilt; // at 0x9 - u8 mMagFilt; // at 0xA + u8 mMinFilter; // at 0x9 + u8 mMagFilter; // at 0xA char UNK_0xB[0x10 - 0xB]; void* mpBuffer; // at 0x10 - void makeGradient(UNKTYPE); - public: - struct Header { - u8 mTexFormat; - u8 BYTE_0x1; - u16 mWidth; - u16 mHeight; - u8 BYTE_0x5; - u8 mWrapS; - u8 mWrapT; - u8 BYTE_0x8; - u16 SHORT_0x9; - u32 WORD_0xC; - u8 BYTE_0xD; - u8 BYTE_0xE; - u8 BYTE_0xF; - u8 BYTE_0x10; - u8 mMinFilt; - u8 mMagFilt; - u8 BYTE_0x13; - u8 BYTE_0x14; - u8 BYTE_0x15; - u16 SHORT_0x16; - u32 WORD_0x18; + enum EGradationKind { + GRADATION_LINEAR, // y=x + GRADATION_QUADRATIC, // y=x^2 + GRADATION_CUBIC, // y=x^3 + GRADATION_QUARTIC, // y=x^4 + GRADATION_QUINTIC, // y=x^5 + GRADATION_QUADRATIC_EASEOUT, // y=1-(1-x)^2 + GRADATION_QUARTIC_EASEOUT, // y=1-(1-x)^4 }; - enum TexFlag { CONFIGURED = 0x1, HAS_HEADER }; - - virtual ~CpuTexture() {} // at 0x8 - virtual void configure(); // at 0xC - virtual void getTexObj(GXTexObj*) const; // at 0x10 - virtual void load(GXTexMapID) const; // at 0x14 +public: + // @bug Texture buffer is leaked + virtual ~CpuTexture() {} // at 0x8 + virtual void configure(); // at 0xC + virtual void getTexObj(GXTexObj* pObj) const; // at 0x10 + virtual void load(GXTexMapID map); // at 0x14 CpuTexture(); - CpuTexture(u16, u16, GXTexFmt); + CpuTexture(u16 width, u16 height, GXTexFmt format); - void checkTexBuffer() const; - void invalidate() const; - void flush() const; + void alloc(); + void allocWithHeaderDebug(); + + ResTIMG* getResTIMG() const; u32 getTexBufferSize() const; - void buildHeader() const; - Header* initHeader(); + void fillNormalMapSphere(); - UNKTYPE func_80086C8C(UNKTYPE); - void allocTexBuffer(); - void allocTexBufferAndHeader(); - void setColor(u16, u16, GXColor); + void fillGradationTable(EGradationKind kind, int dir, u16 tableStart, + u16 tableGoal, const GXColor& c1, const GXColor& c2, + bool wrap, bool setAll); + + void setColor(u16 x, u16 y, GXColor color); + + void invalidate() const; + void flush() const; bool checkIsConfigure() const { - return mFlags & CONFIGURED; + return testFlag(FLAG_CONFIGURED); } bool checkHasHeader() const { - return mFlags & HAS_HEADER; + return testFlag(FLAG_HAS_HEADER); } void setFlag(u8 flag) { @@ -82,6 +73,9 @@ class CpuTexture { void clearFlag(u8 flag) { mFlags &= ~flag; } + bool testFlag(u8 flag) const { + return (mFlags & flag) ? true : false; + } u16 getWidth() const { return mWidth; @@ -98,41 +92,70 @@ class CpuTexture { } GXTexFmt getFormat() const { - return (GXTexFmt)mTexFormat; + return static_cast(mFormat); } - void setFormat(GXTexFmt fmt) { - mTexFormat = fmt; + void setFormat(GXTexFmt format) { + mFormat = format; } + GXTexWrapMode getWrapS() const { + return static_cast(mWrapS); + } void setWrapS(u8 wrap) { mWrapS = wrap; } + + GXTexWrapMode getWrapT() const { + return static_cast(mWrapT); + } void setWrapT(u8 wrap) { mWrapT = wrap; } - void setMinFilt(u8 filt) { - mMinFilt = filt; + + GXTexFilter getMinFilter() const { + return static_cast(mMinFilter); } - void setMagFilt(u8 filt) { - mMagFilt = filt; + void setMinFilter(u8 filter) { + mMinFilter = filter; } - Header* getHeader() const { - return (Header*)((u8*)mpBuffer - sizeof(Header)); + GXTexFilter getMagFilter() const { + return static_cast(mMagFilter); + } + void setMagFilter(u8 filter) { + mMagFilter = filter; } - UNKTYPE* getBuffer() const { + void* getBuffer() const { return mpBuffer; } void setBuffer(void* pBuffer) { #line 180 EGG_ASSERT(pBuffer); - EGG_ASSERT((u32)pBuffer % 32 == 0); +#line 180 + EGG_ASSERT(( u32 )pBuffer % 32 == 0); mpBuffer = pBuffer; - mFlags &= ~HAS_HEADER; + clearFlag(FLAG_HAS_HEADER); + } + +private: + enum { + FLAG_CONFIGURED = 1 << 0, + FLAG_HAS_HEADER = 1 << 1, + }; + +private: + void initResTIMG() const; + + ResTIMG* getHeader() const { + // clang-format off + return reinterpret_cast( + reinterpret_cast(mpBuffer) - sizeof(ResTIMG)); + // clang-format on } }; + } // namespace EGG #endif diff --git a/include/egg/gfx/eggDrawGX.h b/include/egg/gfx/eggDrawGX.h index f37c214..db2c27f 100644 --- a/include/egg/gfx/eggDrawGX.h +++ b/include/egg/gfx/eggDrawGX.h @@ -1,176 +1,233 @@ -#ifndef EGG_GFX_DRAWGX_H -#define EGG_GFX_DRAWGX_H -#include "types_egg.h" -#include "types_nw4r.h" +#ifndef EGG_GFX_DRAW_GX_H +#define EGG_GFX_DRAW_GX_H +#include + +#include #include namespace EGG { + +// Forward declarations +class Heap; + class DrawGX { public: enum Blend { - BLEND_0, - BLEND_1, - BLEND_2, - BLEND_3, - BLEND_4, - BLEND_5, - BLEND_6, - BLEND_7, - BLEND_8, - BLEND_9, + BLEND_NORMAL, // Sc*Sa + Dc*(1-Sa) + BLEND_INVERSE, // Sc*(1-Sa) + Dc*Sa + BLEND_ADD, // Sc+Dc + BLEND_ADD_ALPHA, // Sc*Sa + Dc + BLEND_MUL_ADD, // Sc*Dc + Dc + BLEND_SUB, // Sc - Dc + BLEND_MUL, // Dc*Sc + BLEND_MUL_INV, // Dc*(1-Sc) + BLEND_REPLACE, // Sc + BLEND_NONE, // 1 BLEND_MAX }; - enum Circle { CIRCLE_0 }; + enum Circle { + CIRCLE_16, // Low detail (16 segments) + CIRCLE_32, // High detail (32 segments) + + CIRCLE_MAX, + }; enum ColorChannel { - COLOR_CHANNEL_0, - COLOR_CHANNEL_1, + COLORCHAN_LIGHT, + COLORCHAN_COLOR, }; enum DL { - DL_0, - DL_1, - DL_2, - DL_3, - DL_4, - DL_5, - DL_6, - DL_7, - DL_8, - DL_9, - DL_10, - DL_11, - DL_12, - DL_13, - DL_14, - DL_15, - DL_16, - DL_17, + DL_LINE_AXIS, + DL_CUBE, + DL_CUBE_WIRE, + DL_SPHERE_4X8, + DL_SPHERE_8X16, + DL_LINE_CIRCLE_16, + DL_LINE_CIRCLE_32, + DL_CIRCLE_16, + DL_CIRCLE_32, + DL_CYLINDER_16, + DL_CYLINDER_32, + DL_CONE_16, + DL_CONE_32, + DL_QUAD_TEXTURE, + DL_QUAD, + DL_BOUNDBOX, + DL_SCREEN_TEXTURE, + DL_SCREEN, DL_MAX }; - enum DrawGXFlag { FLAG_INITIALIZE_DISPLAY_LIST = (1 << 0) }; - enum TevSetting { - TEV_SETTING_0, - TEV_SETTING_1, + TEVSETTING_COLOR, + TEVSETTING_TEXTURE, }; enum TexGen { - TEX_GEN_0, - TEX_GEN_1, + TEXGEN_DISABLE, + TEXGEN_ENABLE, }; enum VtxType { - VTX_TYPE_0, - VTX_TYPE_1, - VTX_TYPE_2, - VTX_TYPE_3, - VTX_TYPE_4, - VTX_TYPE_5, - VTX_TYPE_6, - VTX_TYPE_7, - VTX_TYPE_8, - VTX_TYPE_9, - VTX_TYPE_10, - VTX_TYPE_11, - VTX_TYPE_12, - VTX_TYPE_13 + VTXTYPE_CUBE, + VTXTYPE_LINE, + VTXTYPE_SPHERE, + VTXTYPE_CYLINDER, + VTXTYPE_CIRCLE, + VTXTYPE_CONE, + VTXTYPE_POLYGON, + VTXTYPE_QUAD_TEXTURE, + VTXTYPE_QUAD, + VTXTYPE_QUAD_SHADOW, + VTX_TYPE_SCREEN_TEXTURE, + VTX_TYPE_SCREEN_TEXTURE_FLIP, + VTX_TYPE_SCREEN, + VTX_TYPE_SCREEN_FLIP }; enum ZMode { - ZMODE_0, - ZMODE_1, - ZMODE_2, - ZMODE_3, + ZMODE_ALWAYS, // Always draw without updating the Z-buffer + ZMODE_OPA, // For opaque draw + ZMODE_XLU, // For translucent draw + ZMODE_CLEAR, // Always draw and update the Z-buffer ZMODE_MAX }; - struct DisplayList { +public: + static void Initialize(Heap* pHeap = NULL); + static GXLightID GetLightMaskDefault(); + static GXTexMapID GetTexMapDefault(); + + static void BeginDrawCube(); + static void BeginDrawSphere(); + static void BeginDrawLine(ColorChannel chan, ZMode zMode); + static void BeginDrawCornY(); + static void BeginDrawCircleZ(ColorChannel chan, ZMode zMode); + static void BeginDrawPolygon(ColorChannel chan); + static void BeginDrawQuad(ColorChannel chan, ZMode zMode, Blend blendMode, + bool texture, bool alpha); + static void BeginDrawScreen(bool flip, bool texture, bool alpha); + static void BeginDrawShadowVolume(u8 alpha); + + static void DrawLine(const nw4r::math::VEC3* pPoints, u16 num, + GXColor color, u8 width); + static void DrawLineStrip(const nw4r::math::VEC3* pPoints, u16 num, + GXColor color, u8 width); + static void DrawCircle2D(Circle circle, f32 x, f32 y, f32 radius, + GXColor color); + static void DrawCornY(Circle circle, const nw4r::math::MTX34& rMtx, + GXColor color); + static void DrawPolygon(const nw4r::math::VEC3& rP0, + const nw4r::math::VEC3& rP1, + const nw4r::math::VEC3& rP2, GXColor color); + + static void DrawScreenTexture(const nw4r::math::MTX34& rMtx) { + GXLoadPosMtxImm(rMtx, GX_PNMTX0); + GXCallDisplayList(s_DL[DL_SCREEN_TEXTURE].m_list, + s_DL[DL_SCREEN_TEXTURE].m_size); + } + static void DrawScreenTexture(const nw4r::math::MTX34& rMtx, + GXColor color) { + DrawDL(DL_SCREEN_TEXTURE, rMtx, color); + } + + static void BeginDrawShadowVolumeTexture(bool flip, GXColor color, + Blend blendMode); + + static void ClearEfb(const nw4r::math::MTX34& rMtx, bool colorUpdate, + bool alphaUpdate, bool texture, GXColor color, + bool flip); + + static void ResetMaterial(ColorChannel chan); + + static void SetMat_ColorChannel(ColorChannel chan); + static void SetMat_TexGen(TexGen texGen); + static void SetMat_Ind(); + static void SetMat_Tev(GXTevStageID stage, TevSetting setting); + static void SetMat_PE(ZMode zMode, Blend blendMode); + + static void LoadTexture(const ResTIMG* pRes, GXTexMapID map); + static void SetVtxState(VtxType vtxType); + + static void DrawDL(DL dl, const nw4r::math::MTX34& rMtx); + static void DrawDL(DL dl, const nw4r::math::MTX34& rMtx, GXColor color); + + static void DrawDLWorld(DL dl, const nw4r::math::MTX34& rMtx) { + nw4r::math::MTX34 mtx; + nw4r::math::MTX34Mult(&mtx, &s_cameraMtx, &rMtx); + + DrawDL(dl, mtx); + } + static void DrawDLWorld(DL dl, const nw4r::math::MTX34& rMtx, + GXColor color) { + nw4r::math::MTX34 mtx; + nw4r::math::MTX34Mult(&mtx, &s_cameraMtx, &rMtx); + + DrawDL(dl, mtx, color); + } + + static void SetZMode(ZMode zMode); + static void SetBlendMode(Blend blendMode); + + static void SetCameraMtx(const nw4r::math::MTX34& rMtx) { + s_cameraMtx = rMtx; + } + +public: + static const GXColor BLACK; + static const GXColor WHITE; + static const GXColor RED; + static const GXColor GREEN; + static const GXColor BLUE; + static const GXColor ORANGE; + +private: + struct DLEntry { u8* m_list; // at 0x0 u32 m_size; // at 0x4 }; struct ZModeEntry { - u8 BYTE_0x0; - UNKWORD WORD_0x4; - u8 BYTE_0x8; + GXBool m_enableTest; // at 0x0 + GXCompare m_func; // at 0x4 + GXBool m_enableUpdate; // at 0x8 }; struct BlendEntry { - UNKWORD WORD_0x0; - UNKWORD WORD_0x4; - UNKWORD WORD_0x8; - UNKWORD WORD_0xC; + GXBlendMode m_blendMode; // at 0x0 + GXBlendFactor m_srcFactor; // at 0x4 + GXBlendFactor m_dstFactor; // at 0x8 + GXLogicOp m_op; // at 0xC }; -public: - static void Initialize(Heap*); - static void InitTexObj(); - static GXTexMapID GetTexMapDefault(); - static void BeginDrawVtxType0(); - static void BeginDrawVtxType2(); - static void BeginDrawLine(ColorChannel, ZMode); - static void BeginDrawVtxType5(); - static void BeginDrawCircleZ(ColorChannel, ZMode); - static void BeginDrawPolygon(ColorChannel); - static void BeginDrawQuad(ColorChannel, ZMode, Blend, bool, bool); - static void BeginDrawScreen(bool, bool, bool); - static void FUN_80087cd4(bool); - static void DrawLineStrip(const nw4r::math::VEC3*, u16, GXColor, u8); - static void DrawLine(const nw4r::math::VEC3*, u16, GXColor, u8); - static void DrawCircle2D(Circle, f32, f32, f32, GXColor, u8); - static void DrawPoint(const nw4r::math::VEC3*, u16, GXColor, u8); - static void DrawPolygon(const nw4r::math::VEC3&, const nw4r::math::VEC3&, - const nw4r::math::VEC3&, GXColor); - static void BeginDrawShadowVolumeTexture(bool, GXColor, Blend); - static void ClearEfb(const nw4r::math::MTX34&, bool, bool, bool, GXColor, - bool); - static void ResetMaterial(ColorChannel); - static void SetMat_ColorChannel(ColorChannel); - static void SetMat_TexGen(TexGen); - static void SetMat_Ind(); - static void SetMat_Tev(int, TevSetting); - static void SetMat_PE(ZMode, Blend); - static void LoadTexture(const ResTIMG*, int); - static void SetVtxState(VtxType); - static void CreateDisplayList(Heap*); - static void DrawDL(DL, const nw4r::math::MTX34&); - static void DrawDL(DL, const nw4r::math::MTX34&, GXColor); - static void SetZMode(ZMode); - static void SetBlendMode(Blend); - - static DisplayList* GetDisplayList(u32 i) { - return &s_DL[i]; - } + enum { FLAG_INITIALIZE_DISPLAY_LIST = 1 << 0 }; -public: - static const GXColor scColorBlack; - static const GXColor scColorWhite; - static const GXColor scColorRed; - static const GXColor scColorGreen; - static const GXColor scColorBlue; - static const GXColor scColorOrange; - - static nw4r::math::MTX34 s_cameraMtx; +private: + static void InitClearTexObj(); + static void CreateDisplayList(Heap* pHeap); private: - static DisplayList s_DL[DL_MAX]; - static GXTexObj sTexObj; - static u8 sClearTex[] __attribute__((aligned(32))); + static DLEntry s_DL[DL_MAX]; + static const DL s_circleDLTbl[CIRCLE_MAX]; + static nw4r::math::MTX34 s_cameraMtx; static u32 s_flag; - static GXTexMapID sTexMapDefault; - static const VtxType sVtxTypeMap[3][3]; - static const ZModeEntry sZModeMap[]; - static const BlendEntry sBlendMap[]; + static GXLightID s_lightMaskDefault; + static GXTexMapID s_texMapDefault; + + static f32 s_quadScale; + + static GXTexObj s_clearTexObj; + static u32 s_clearTex[4 * 4] ALIGN(32); }; + } // namespace EGG #endif diff --git a/include/egg/gfx/eggDrawPathBase.h b/include/egg/gfx/eggDrawPathBase.h index 015e888..a9aaa51 100644 --- a/include/egg/gfx/eggDrawPathBase.h +++ b/include/egg/gfx/eggDrawPathBase.h @@ -1,24 +1,26 @@ #ifndef EGG_GFX_DRAW_PATH_BASE_H #define EGG_GFX_DRAW_PATH_BASE_H +#include "types_egg.h" #include "eggAssert.h" -#include "eggIDrawGX.h" -#include "eggIScnProc.h" #include "eggScreenEffectBase.h" -#include "types_egg.h" +#include "eggIScnProc.h" +#include "eggIDrawGX.h" -namespace EGG { -class DrawPathBase : public ScreenEffectBase, public IScnProc { -public: - DrawPathBase(); - virtual ~DrawPathBase() {} // at 0x8 - virtual int getNumScnProc() const = 0; // at 0x1C - virtual void calc_after_CalcWorld(); // at 0x20 - virtual void calc(); // at 0x24 - virtual void draw(u16) = 0; // at 0x28 - virtual void doDraw(u16); // at 0x2C +namespace EGG +{ + class DrawPathBase : public ScreenEffectBase, public IScnProc + { + public: + DrawPathBase(); + virtual ~DrawPathBase() {} // at 0x8 + virtual int getNumScnProc() const = 0; // at 0x1C + virtual void calc_after_CalcWorld(); // at 0x20 + virtual void calc(); // at 0x24 + virtual void draw(u16) = 0; // at 0x28 + virtual void scnProcDraw(u16); // at 0x2C - void CopyGlobalScreen(); -}; -} // namespace EGG + void CopyGlobalScreen(); + }; +} #endif diff --git a/include/egg/gfx/eggDrawPathBloom.h b/include/egg/gfx/eggDrawPathBloom.h index d2b3074..bc64b49 100644 --- a/include/egg/gfx/eggDrawPathBloom.h +++ b/include/egg/gfx/eggDrawPathBloom.h @@ -1,34 +1,32 @@ #ifndef EGG_GFX_DRAW_PATH_BLOOM_H #define EGG_GFX_DRAW_PATH_BLOOM_H +#include "types_egg.h" #include "eggDrawPathBase.h" #include "eggIBinary.h" -#include "types_egg.h" -namespace EGG { -class DrawPathBloom : public DrawPathBase, public IBinary { -public: - DrawPathBloom(); - virtual int getNumScnProc() const; // at 0x1C - virtual void calc(); // at 0x24 - virtual void draw(u16); // at 0x28 - virtual ~DrawPathBloom(); // at 0x8 +namespace EGG +{ + class DrawPathBloom : public DrawPathBase, public IBinary + { + public: + DrawPathBloom(); + virtual int getNumScnProc() const; // at 0x1C + virtual void calc(); // at 0x24 + virtual void draw(u16); // at 0x28 + virtual ~DrawPathBloom(); // at 0x8 - virtual void SetBinaryInner(const Bin&); // at 0x8 - virtual void GetBinaryInner(Bin*) const; // at 0xC - virtual const char* GetBinaryType() const; // at 0x10 - virtual u8 GetVersion() const; // at 0x18 + virtual void SetBinaryInner(const Bin&); // at 0x8 + virtual void GetBinaryInner(Bin *) const; // at 0xC + virtual const char * GetBinaryType() const; // at 0x10 + virtual u8 GetVersion() const; // at 0x18 - void setFlag(u8 f) { - mFlags |= f; - } - void clearFlag(u8 f) { - mFlags &= ~f; - } + void setFlag(u8 f) { mFlags |= f; } + void clearFlag(u8 f) { mFlags &= ~f; } -private: - u8 mFlags; // at 0x80 - char UNK_0x81[0x134 - 0x81]; -}; -} // namespace EGG + private: + u8 mFlags; // at 0x80 + char UNK_0x81[0x134 - 0x81]; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggDrawPathDOF.h b/include/egg/gfx/eggDrawPathDOF.h index c5e6dd8..bb99b80 100644 --- a/include/egg/gfx/eggDrawPathDOF.h +++ b/include/egg/gfx/eggDrawPathDOF.h @@ -1,20 +1,22 @@ #ifndef EGG_GFX_DRAW_PATH_DOF_H #define EGG_GFX_DRAW_PATH_DOF_H -#include "eggDrawPathBase.h" #include "types_egg.h" +#include "eggDrawPathBase.h" -namespace EGG { -class DrawPathDOF : public DrawPathBase { -public: - DrawPathDOF(); - virtual int getNumScnProc() const; // at 0x1C - virtual void calc(); // at 0x24 - virtual void draw(u16); // at 0x28 - virtual ~DrawPathDOF(); // at 0x8 +namespace EGG +{ + class DrawPathDOF : public DrawPathBase + { + public: + DrawPathDOF(); + virtual int getNumScnProc() const; // at 0x1C + virtual void calc(); // at 0x24 + virtual void draw(u16); // at 0x28 + virtual ~DrawPathDOF(); // at 0x8 -private: - char UNK_0x7C[0xB4 - 0x7C]; -}; -} // namespace EGG + private: + char UNK_0x7C[0xB4 - 0x7C]; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggDrawPathHDR.h b/include/egg/gfx/eggDrawPathHDR.h index 2ac011e..9b0a1cc 100644 --- a/include/egg/gfx/eggDrawPathHDR.h +++ b/include/egg/gfx/eggDrawPathHDR.h @@ -1,22 +1,24 @@ #ifndef EGG_GFX_DRAW_PATH_HDR_H #define EGG_GFX_DRAW_PATH_HDR_H -#include "eggDrawPathBase.h" #include "types_egg.h" +#include "eggDrawPathBase.h" -namespace EGG { -class DrawPathHDR : public DrawPathBase { -public: - DrawPathHDR(); - virtual ~DrawPathHDR(); // at 0x8 - virtual int getNumScnProc() const; // at 0x1C - virtual void calc(); // at 0x24 - virtual void draw(u16); // at 0x28 +namespace EGG +{ + class DrawPathHDR : public DrawPathBase + { + public: + DrawPathHDR(); + virtual ~DrawPathHDR(); // at 0x8 + virtual int getNumScnProc() const; // at 0x1C + virtual void calc(); // at 0x24 + virtual void draw(u16); // at 0x28 -private: - PostEffectHDR* mPostEffect; // at 0x7C + private: + PostEffectHDR *mPostEffect; // at 0x7C - static const int NUM_SCNPROC = 2; -}; -} // namespace EGG + static const int NUM_SCNPROC = 2; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggDrawPathLightMap.h b/include/egg/gfx/eggDrawPathLightMap.h index 905f87d..966199a 100644 --- a/include/egg/gfx/eggDrawPathLightMap.h +++ b/include/egg/gfx/eggDrawPathLightMap.h @@ -1,29 +1,31 @@ #ifndef EGG_GFX_DRAW_PATH_LIGHT_MAP_H #define EGG_GFX_DRAW_PATH_LIGHT_MAP_H -#include "eggDrawPathBase.h" #include "types_egg.h" +#include "eggDrawPathBase.h" -namespace EGG { -class DrawPathLightMap : public DrawPathBase { -public: - DrawPathLightMap(); - virtual int getNumScnProc() const; // at 0x1C - virtual void calc(); // at 0x24 - virtual void draw(u16); // at 0x28 - virtual ~DrawPathLightMap(); // at 0x8 +namespace EGG +{ + class DrawPathLightMap : public DrawPathBase + { + public: + DrawPathLightMap(); + virtual int getNumScnProc() const; // at 0x1C + virtual void calc(); // at 0x24 + virtual void draw(u16); // at 0x28 + virtual ~DrawPathLightMap(); // at 0x8 -private: - u8 BYTE_0x7A; - u8 BYTE_0x7B; - u8 BYTE_0x7C; - u8 BYTE_0x7D; - int WORD_0x80; - TextureBuffer* BUF_0x84; - TextureBuffer* BUF_0x88; - TextureBuffer* BUF_0x8C; + private: + u8 BYTE_0x7A; + u8 BYTE_0x7B; + u8 BYTE_0x7C; + u8 BYTE_0x7D; + int WORD_0x80; + TextureBuffer *BUF_0x84; + TextureBuffer *BUF_0x88; + TextureBuffer *BUF_0x8C; - static const int NUM_SCNPROC = 4; -}; -} // namespace EGG + static const int NUM_SCNPROC = 4; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggDrawPathShadowVolume.h b/include/egg/gfx/eggDrawPathShadowVolume.h index 563a023..91cff0f 100644 --- a/include/egg/gfx/eggDrawPathShadowVolume.h +++ b/include/egg/gfx/eggDrawPathShadowVolume.h @@ -1,20 +1,22 @@ #ifndef EGG_GFX_DRAW_PATH_SHADOW_VOLUME_H #define EGG_GFX_DRAW_PATH_SHADOW_VOLUME_H -#include "eggDrawPathBase.h" #include "types_egg.h" +#include "eggDrawPathBase.h" -namespace EGG { -class DrawPathShadowVolume : public DrawPathBase { -public: - DrawPathShadowVolume(); - virtual int getNumScnProc() const; // at 0x1C - virtual void calc(); // at 0x24 - virtual void draw(u16); // at 0x28 - virtual ~DrawPathShadowVolume(); // at 0x8 +namespace EGG +{ + class DrawPathShadowVolume : public DrawPathBase + { + public: + DrawPathShadowVolume(); + virtual int getNumScnProc() const; // at 0x1C + virtual void calc(); // at 0x24 + virtual void draw(u16); // at 0x28 + virtual ~DrawPathShadowVolume(); // at 0x8 -private: - char UNK_0x7C[0x98 - 0x7C]; -}; -} // namespace EGG + private: + char UNK_0x7C[0x98 - 0x7C]; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggFog.h b/include/egg/gfx/eggFog.h index b95e646..da1fe9b 100644 --- a/include/egg/gfx/eggFog.h +++ b/include/egg/gfx/eggFog.h @@ -1,38 +1,42 @@ #ifndef EGG_GFX_FOG_H #define EGG_GFX_FOG_H -#include "g3d_fog.h" #include "types_egg.h" +#include -namespace EGG { -class Fog { -public: - GXColor mColor; // at 0x0 - f32 mStartZ; // at 0x4 - f32 mEndZ; // at 0x8 - f32 mNearZ; // at 0xC - f32 mFarZ; // at 0x10 - GXFogType mFogType; // at 0x14 - u8 mFlags; // at 0x18 +namespace EGG +{ + class Fog + { + public: + GXColor mColor; // at 0x0 + f32 mStartZ; // at 0x4 + f32 mEndZ; // at 0x8 + f32 mNearZ; // at 0xC + f32 mFarZ; // at 0x10 + GXFogType mFogType; // at 0x14 + u8 mFlags; // at 0x18 -public: - enum FogFlag { - BOUND = 0x1, - }; - -public: - Fog(); - virtual ~Fog(); // at 0x8 - virtual void Reset(); // at 0xC - virtual UNKTYPE Calc(UNKTYPE); // at 0x10 - virtual void SetGX() const; // at 0x14 + public: + enum FogFlag + { + BOUND = 0x1, + }; - void Bind(const nw4r::g3d::ResAnmFog&, f32); - void CopyToG3D(nw4r::g3d::Fog) const; + public: + Fog(); + virtual ~Fog(); // at 0x8 + virtual void Reset(); // at 0xC + virtual UNKTYPE Calc(UNKTYPE); // at 0x10 + virtual void SetGX() const; // at 0x14 + + void Bind(const nw4r::g3d::ResAnmFog&, f32); + void CopyToG3D(nw4r::g3d::Fog) const; - void Unbind() { - mFlags |= ~BOUND; - } -}; -} // namespace EGG + void Unbind() + { + mFlags |= ~BOUND; + } + }; +} #endif diff --git a/include/egg/gfx/eggFogManager.h b/include/egg/gfx/eggFogManager.h index 16e5279..baf00dc 100644 --- a/include/egg/gfx/eggFogManager.h +++ b/include/egg/gfx/eggFogManager.h @@ -1,31 +1,34 @@ #ifndef EGG_GFX_FOG_MANAGER_H #define EGG_GFX_FOG_MANAGER_H #include "types_egg.h" -#include "types_nw4r.h" +#include -namespace EGG { -class FogManager { -private: - static const int cNumFog = 32; +namespace EGG +{ + class FogManager + { + private: + static const int cNumFog = 32; - u8 mFlags; // at 0x0 - Fog* mFog[cNumFog]; // at 0x4 + u8 mFlags; // at 0x0 + Fog *mFog[cNumFog]; // at 0x4 + + enum + { + DRAW_READY = 4, + }; - enum { - DRAW_READY = 4, - }; - -public: - FogManager(); - virtual ~FogManager(); // at 0x8 + public: + FogManager(); + virtual ~FogManager(); // at 0x8 - void Reset(); - void Calc(); - void UseScreenZ(Screen&); - void CopyToG3D(nw4r::g3d::ScnRoot*) const; - void LoadScnFog(nw4r::g3d::ResAnmScn*, f32); - void DoneDraw(); -}; -} // namespace EGG + void Reset(); + void Calc(); + void UseScreenZ(Screen&); + void CopyToG3D(nw4r::g3d::ScnRoot *) const; + void LoadScnFog(nw4r::g3d::ResAnmScn *, f32); + void DoneDraw(); + }; +} #endif diff --git a/include/egg/gfx/eggFrustum.h b/include/egg/gfx/eggFrustum.h index 514dc0c..fd36a44 100644 --- a/include/egg/gfx/eggFrustum.h +++ b/include/egg/gfx/eggFrustum.h @@ -1,25 +1,30 @@ #ifndef EGG_GFX_FRUSTUM_H #define EGG_GFX_FRUSTUM_H -#include "eggAssert.h" -#include "eggMatrix.h" -#include "eggVector.h" -#include "g3d_camera.h" -#include "g3d_resanmscn.h" -#include "math_triangular.h" -#include "types_egg.h" +#include + +#include +#include + +#include +#include #include namespace EGG { + class Frustum { public: - enum Flag { FLAG_DIRTY = (1 << 0) }; - - enum ProjectionType { PROJ_ORTHO, PROJ_PERSP }; + enum ProjectionType { PROJTYPE_ORTHO, PROJTYPE_PERSP }; enum CanvasMode { - CANVASMODE_CC, - CANVASMODE_LU, + CANVASMODE_CC, // Center-canvas origin + CANVASMODE_LU, // Left-upper origin + }; + + enum LoadScnFlag { + LOADSCN_KEEP_FOVY = 1 << 0, + LOADSCN_KEEP_CANVAS = 1 << 1, + LOADSCN_KEEP_Z = 1 << 2, }; protected: @@ -35,73 +40,87 @@ class Frustum { mutable u16 mFlags; // at 0x34 public: - static void GetGlobalScaleOffset(f32* sx, f32* sy, f32* ox, f32* oy) { - *sx = sGlobalScale.x; - *sy = sGlobalScale.y; - *ox = sGlobalOffset.x; - *oy = sGlobalOffset.y; - } - - static void SetGlobalScaleOffset(f32 sx, f32 sy, f32 ox, f32 oy) { - sGlobalScale.x = sx; - sGlobalScale.y = sy; - sGlobalOffset.x = ox; - sGlobalOffset.y = oy; - } - - Frustum(ProjectionType, const nw4r::math::VEC2&, f32, f32, CanvasMode); - Frustum(const Frustum&); + Frustum(ProjectionType projType, const nw4r::math::VEC2& rSize, f32 nearZ, + f32 farZ, CanvasMode canvasMode); + Frustum(const Frustum& rOther); - virtual ~Frustum() {} // at 0x8 - virtual void SetProjectionGX() const; // at 0xC - virtual void CopyToG3D(nw4r::g3d::Camera) const; // at 0x10 + virtual ~Frustum() {} // at 0x8 + virtual void SetProjectionGX() const; // at 0xC + virtual void CopyToG3D(nw4r::g3d::Camera camera) const; // at 0x10 - void CopyFromAnother(const Frustum&); + void LoadScnCamera(const nw4r::g3d::ResAnmScn anmScn, u8 refNumber, + f32 frame, u32 flags); - void GetViewToScreen(nw4r::math::VEC3*, const nw4r::math::VEC3&) const; - void GetScreenToView(nw4r::math::VEC3*, const nw4r::math::VEC3&) const; - void GetScreenToView(nw4r::math::VEC3*, const nw4r::math::VEC2&) const; + void CopyFromAnother(const Frustum& rOther); - void LoadScnCamera(nw4r::g3d::ResAnmScn, u8, f32, u32); + void GetViewToScreen(nw4r::math::VEC3* pScreenPos, + const nw4r::math::VEC3& rViewPos) const; + void GetScreenToView(nw4r::math::VEC3* pViewPos, + const nw4r::math::VEC3& rScreenPos) const; + void GetScreenToView(nw4r::math::VEC3* pPosView, + const nw4r::math::VEC2& rPosScreen) const; - void SetDirty(bool dirty) const { - if (dirty) - mFlags |= FLAG_DIRTY; - else - mFlags &= ~FLAG_DIRTY; + void ConvertToCanvasLU(f32 x, f32 y, f32* pX, f32* pY) const { + if (mCanvasMode == CANVASMODE_LU) { + *pX = x; + *pY = y; + } else if (mCanvasMode == CANVASMODE_CC) { + ConvertFromCanvasCC(x, y, pX, pY); + } } - - void ConvertToCanvasLU(f32 ix, f32 iy, f32* ox, f32* oy) const { + void ConvertToCanvasCC(f32 x, f32 y, f32* pX, f32* pY) const { if (mCanvasMode == CANVASMODE_LU) { - *ox = ix; - *oy = iy; + ConvertFromCanvasLU(x, y, pX, pY); } else if (mCanvasMode == CANVASMODE_CC) { - ConvertToCanvasLU_Inline_0(ix, iy, ox, oy); + *pX = x; + *pY = y; } } - void ConvertToCanvasLU_Inline_0(f32 ix, f32 iy, f32* ox, f32* oy) const { - const f32 sx = GetSize().x; - *ox = ix + (sx / 2.0f); + void ConvertToNormalLU(f32 x, f32 y, f32* pX, f32* pY) const { + if (mCanvasMode == CANVASMODE_LU) { + *pX = x / (GetSize().x / 2.0f); + *pY = y / (GetSize().y / 2.0f); + } else if (mCanvasMode == CANVASMODE_CC) { + ConvertFromCanvasCC(x, y, pX, pY); + *pX /= GetSize().x / 2.0f; + *pY /= GetSize().y / 2.0f; + } + } + void ConvertToNormalCC(f32 x, f32 y, f32* pX, f32* pY) const { + if (mCanvasMode == CANVASMODE_LU) { + ConvertFromCanvasLU(x, y, pX, pY); + *pX /= GetSize().x / 2.0f; + *pY /= GetSize().y / 2.0f; + } else if (mCanvasMode == CANVASMODE_CC) { + *pX = x / (GetSize().x / 2.0f); + *pY = y / (GetSize().y / 2.0f); + } + } - const f32 sy = GetSize().y; - *oy = -(iy - (sy / 2.0f)); + void ConvertFromCanvasLU(f32 x, f32 y, f32* pX, f32* pY) const { + *pX = -(GetSize().x / 2.0f - x); + *pY = -(-(GetSize().y / 2.0f - y)); + } + void ConvertFromCanvasCC(f32 x, f32 y, f32* pX, f32* pY) const { + *pX = x + GetSize().x / 2.0f; + *pY = -(y - GetSize().y / 2.0f); } ProjectionType GetProjectionType() const { return mProjType; } - void SetProjectionType(ProjectionType type) { - mProjType = type; + void SetProjectionType(ProjectionType projType) { + mProjType = projType; } CanvasMode GetCanvasMode() const { return mCanvasMode; } - void SetCanvasMode(CanvasMode mode) { - if (mCanvasMode != mode) { - SetDirty(true); - mCanvasMode = mode; + void SetCanvasMode(CanvasMode canvasMode) { + if (mCanvasMode != canvasMode) { + mFlags |= FLAG_DIRTY; + mCanvasMode = canvasMode; } } @@ -110,32 +129,33 @@ class Frustum { } u16 GetWidth() const { - return mSize.x; - } - f32 GetSizeX() const { - return mSize.x; + return static_cast(GetSize().x); } void SetSizeX(f32 sizeX) { #line 117 EGG_ASSERT(sizeX >= 0.f); - SetDirty(true); + mFlags |= FLAG_DIRTY; mSize.x = sizeX; } u16 GetHeight() const { - return mSize.y; - } - f32 GetSizeY() const { - return mSize.y; + return static_cast(GetSize().y); } void SetSizeY(f32 sizeY) { #line 123 EGG_ASSERT(sizeY >= 0.f); - SetDirty(true); + mFlags |= FLAG_DIRTY; mSize.y = sizeY; } - void SetFovY(f32 fovy) { + f32 GetAspect() const { + return GetSize().x / GetSize().y; + } + + f32 GetFovy() const { + return mFovY; + } + void SetFovy(f32 fovy) { if (mFovY == fovy) return; @@ -148,49 +168,70 @@ class Frustum { mTanFovY = sin / cos; } - void SetNearZ(f32 nearZ) { - mNearZ = nearZ; - } f32 GetNearZ() const { return mNearZ; } + void SetNearZ(f32 nearZ) { + mNearZ = nearZ; + } + f32 GetFarZ() const { + return mFarZ; + } void SetFarZ(f32 farZ) { mFarZ = farZ; } - f32 GetFarZ() const { - return mFarZ; + + const nw4r::math::VEC2& GetOffset() const { + return mOffset; + } + void SetOffset(const nw4r::math::VEC2& rOffset) { + mOffset = rOffset; } - void SetScale(const nw4r::math::VEC3& scale) { - mScale = scale; + const nw4r::math::VEC3& GetScale() const { + return mScale; } - void SetOffset(const nw4r::math::VEC2& offset) { - mOffset = offset; + void SetScale(const nw4r::math::VEC3& rScale) { + mScale = rScale; } - void SetFlag(u32 flag) { - mFlags |= flag; + static void GetGlobalScaleOffset(f32* pSX, f32* pSY, f32* pOX, f32* pOY) { + *pSX = sGlobalScale.x; + *pSY = sGlobalScale.y; + *pOX = sGlobalOffset.x; + *pOY = sGlobalOffset.y; + } + static void SetGlobalScaleOffset(f32 sx, f32 sy, f32 ox, f32 oy) { + sGlobalScale.x = sx; + sGlobalScale.y = sy; + sGlobalOffset.x = ox; + sGlobalOffset.y = oy; } +protected: + enum { + FLAG_DIRTY = 1 << 0, + }; + private: void SetProjectionPerspectiveGX_() const; void SetProjectionOrthographicGX_() const; - void CopyToG3D_Perspective_(nw4r::g3d::Camera) const; - void CopyToG3D_Orthographic_(nw4r::g3d::Camera) const; + void CopyToG3D_Perspective_(nw4r::g3d::Camera camera) const; + void CopyToG3D_Orthographic_(nw4r::g3d::Camera camera) const; - void CalcMtxPerspective_(nw4r::math::MTX44*) const; + void CalcMtxPerspective_(nw4r::math::MTX44* pMtx) const; - void GetOrthographicParam_(nw4r::math::MTX44*) const; - void GetOrthographicParam_(f32*) const; - void GetPerspectiveParam_(f32*) const; - void GetOrthographicParam_(f32*, f32*, f32*, f32*) const; + void GetOrthographicParam_(nw4r::math::MTX44* pMtx) const; + void GetPerspectiveParam_(f32* p) const; + void GetOrthographicParam_(f32* pT, f32* pB, f32* pL, f32* pR) const; private: static nw4r::math::VEC2 sGlobalScale; static nw4r::math::VEC2 sGlobalOffset; }; + } // namespace EGG #endif diff --git a/include/egg/gfx/eggG3DUtility.h b/include/egg/gfx/eggG3DUtility.h index 07302bf..d8f5332 100644 --- a/include/egg/gfx/eggG3DUtility.h +++ b/include/egg/gfx/eggG3DUtility.h @@ -1,51 +1,47 @@ #ifndef EGG_GFX_G3D_UTILITY_H #define EGG_GFX_G3D_UTILITY_H +#include "types_egg.h" #include "eggAssert.h" +#include "types_nw4r.h" #include "g3d_resmat.h" #include "g3d_scnmdl.h" -#include "types_egg.h" -#include "types_nw4r.h" -namespace EGG { -class G3DUtility { -public: - static MEMAllocator* getAllocator() { - return sAllocator; - } +namespace EGG +{ + class G3DUtility + { + public: + static MEMAllocator * getAllocator() { return sAllocator; } - static void initialize(u32, Heap*); - static bool setManualMapMode(nw4r::g3d::ResTexSrt, u32); - static void texCamMtxFunc(nw4r::math::MTX34*, s8, s8); - static bool light_func_8008F59C(nw4r::g3d::LightSetting*, - nw4r::g3d::ResAnmScn, u32); - static int searchStringResNode(nw4r::g3d::ResMdl, const char*, u16*, u32); - static void searchStringResMat(nw4r::g3d::ResMdl, const char*, u16*, u32); - static void searchStringResTexPlttInfo(nw4r::g3d::ResMdl, const char*, u16*, - u32); - static int replaceTexture(nw4r::g3d::ResMat, - nw4r::g3d::ScnMdl::CopiedMatAccess*, const char*, - const int&, bool, u16); + static void initialize(u32, Heap *); + static bool setManualMapMode(nw4r::g3d::ResTexSrt, u32); + static void texCamMtxFunc(nw4r::math::MTX34 *, s8, s8); + static bool light_func_8008F59C(nw4r::g3d::LightSetting *, nw4r::g3d::ResAnmScn, u32); + static int searchStringResNode(nw4r::g3d::ResMdl, const char *, u16 *, u32); + static void searchStringResMat(nw4r::g3d::ResMdl, const char *, u16 *, u32); + static void searchStringResTexPlttInfo(nw4r::g3d::ResMdl, const char *, u16 *, u32); + static int replaceTexture(nw4r::g3d::ResMat, nw4r::g3d::ScnMdl::CopiedMatAccess *, + const char *, const int&, bool, u16); - static void clearTempMem() { - sTempMemIndex = 0; - } - static void* allocTempMem(size_t size) { - int blockEnd = sTempMemIndex + size; - void* block = &sTempMem[sTempMemIndex]; - sTempMemIndex = blockEnd; + static void clearTempMem() { sTempMemIndex = 0; } + static void * allocTempMem(size_t size) + { + int blockEnd = sTempMemIndex + size; + void *block = &sTempMem[sTempMemIndex]; + sTempMemIndex = blockEnd; -#line 170 - EGG_ASSERT_MSG(sTempMemIndex < sTempMemSize, "Size over."); - return block; - } + #line 170 + EGG_ASSERT_MSG(sTempMemIndex < sTempMemSize, "Size over."); + return block; + } -private: - static u8 sManualProjectionMapMode; - static MEMAllocator* sAllocator; - static char* sTempMem; - static u32 sTempMemIndex; - static u32 sTempMemSize; -}; -} // namespace EGG + private: + static u8 sManualProjectionMapMode; + static MEMAllocator *sAllocator; + static char *sTempMem; + static u32 sTempMemIndex; + static u32 sTempMemSize; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggGXUtility.h b/include/egg/gfx/eggGXUtility.h index 43f0234..fb3abde 100644 --- a/include/egg/gfx/eggGXUtility.h +++ b/include/egg/gfx/eggGXUtility.h @@ -1,44 +1,27 @@ #ifndef EGG_GFX_GX_UTILITY_H #define EGG_GFX_GX_UTILITY_H -#include "eggIDrawGX.h" -#include "math_types.h" -#include "types_egg.h" +#include + +#include #include -#include namespace EGG { -class GXUtility : public IDrawGX { + +class GXUtility { public: - typedef UNKTYPE (*ProjectionCallback)(UNKWORD, bool); + static u8 getTexMtxID(int no); - enum DrawSetting { - ENABLE_COLOR_UPDATE = 0x1, - ENABLE_ALPHA_UPDATE = 0x2, - ENABLE_DITHER = 0x4, - }; + static void setScaleOffsetPerspective(f32* p, f32 sx, f32 sy, f32 ox, + f32 oy); -public: - static u8 getTexMtxID(int); - static void setScaleOffsetPerspective(f32*, f32, f32, f32, f32); - static void getTexObj(GXTexObj*, const ResTIMG&); - static void getTexObj(GXTexObj*, nw4r::g3d::ResTex, GXTexWrapMode, - GXTexWrapMode, GXTexFilter, GXTexFilter); - static void set(u16, const nw4r::math::MTX34&, Screen&); - static void setScreenProjection(bool); - - static void setDrawSetting(u32 setting) { - sDrawSettings = setting; - } - -private: - static const u8 sTexMtxIDs[]; - static ProjectionCallback sProjectionCallback; - static UNKWORD sProjectionCallbackArg; - static u16 lbl_804BEC7C; - static u32 sDrawSettings; - static nw4r::math::MTX34 sCameraMtx; + static void getTexObj(GXTexObj* pObj, const ResTIMG& rRes); + + static void getTexObj(GXTexObj* pObj, const nw4r::g3d::ResTex tex, + GXTexWrapMode wrapS, GXTexWrapMode wrapT, + GXTexFilter minFilter, GXTexFilter magFilter); }; + } // namespace EGG #endif diff --git a/include/egg/gfx/eggGfxEngine.h b/include/egg/gfx/eggGfxEngine.h index 59a7f2a..71bdc18 100644 --- a/include/egg/gfx/eggGfxEngine.h +++ b/include/egg/gfx/eggGfxEngine.h @@ -2,22 +2,24 @@ #define EGG_GFX_GFX_ENGINE_H #include "types_egg.h" -namespace EGG { -class GfxEngine { -private: - char* PTR_0x4; - char UNK_0x8[0x4]; +namespace EGG +{ + class GfxEngine + { + private: + char *PTR_0x4; + char UNK_0x8[0x4]; -public: - static void initialize(u16, u16, Heap*); - static void beginDraw(); + public: + static void initialize(u16, u16, Heap *); + static void beginDraw(); - GfxEngine(); - virtual ~GfxEngine(); // at 0x8 + GfxEngine(); + virtual ~GfxEngine(); // at 0x8 -private: - static GfxEngine* spInstance; -}; -} // namespace EGG + private: + static GfxEngine *spInstance; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggIDrawGX.h b/include/egg/gfx/eggIDrawGX.h index a2301be..fa4ef60 100644 --- a/include/egg/gfx/eggIDrawGX.h +++ b/include/egg/gfx/eggIDrawGX.h @@ -1,24 +1,85 @@ #ifndef EGG_GFX_I_DRAWGX_H #define EGG_GFX_I_DRAWGX_H -#include "eggAssert.h" -#include "types_egg.h" +#include + +#include + +#include namespace EGG { + +// Forward declarations +class Screen; + class IDrawGX { public: - static Screen& getScreen() { + enum DrawFlag { + DRAWFLAG_COLORUPDATE = 1 << 0, + DRAWFLAG_ALPHAUPDATE = 1 << 1, + DRAWFLAG_DITHER = 1 << 2, + }; + +public: + static const Screen& getScreen() { #line 59 EGG_ASSERT(spScreen); return *spScreen; } - static void setScreen(Screen& screen) { - spScreen = &screen; + static void beginDrawView(u16 cameraId, const nw4r::math::MTX34& rCameraMtx, + const Screen& rScreen); + + static void setDrawSettingGX(bool opa); + + static bool isEnableColorUpdate() { + return sDrawFlag & DRAWFLAG_COLORUPDATE; + } + static void enableColorUpdate() { + sDrawFlag |= DRAWFLAG_COLORUPDATE; + } + static void disableColorUpdate() { + sDrawFlag &= ~DRAWFLAG_COLORUPDATE; + } + + static bool isEnableAlphaUpdate() { + return sDrawFlag & DRAWFLAG_ALPHAUPDATE; + } + static void enableAlphaUpdate() { + sDrawFlag |= DRAWFLAG_ALPHAUPDATE; + } + static void disableAlphaUpdate() { + sDrawFlag &= ~DRAWFLAG_ALPHAUPDATE; + } + + static bool isEnableDither() { + return sDrawFlag & DRAWFLAG_DITHER; + } + static void enableDither() { + sDrawFlag |= DRAWFLAG_DITHER; + } + static void disableDither() { + sDrawFlag &= ~DRAWFLAG_DITHER; + } + + static void setDrawFlag(u32 flag) { + sDrawFlag = flag; } private: - static Screen* spScreen; + typedef void (*SetDrawSettingCallback)(void* pArg, bool opa); + +private: + static const Screen* spScreen; + + static SetDrawSettingCallback spSetDrawSetttingCallback; + static void* spSetDrawSetttingCallbackArg; + + static u16 sCameraID; + static nw4r::math::MTX34 sCameraMatrix; + + static u32 sDrawFlag; }; + } // namespace EGG #endif diff --git a/include/egg/gfx/eggIScnProc.h b/include/egg/gfx/eggIScnProc.h index dc297d4..e566055 100644 --- a/include/egg/gfx/eggIScnProc.h +++ b/include/egg/gfx/eggIScnProc.h @@ -1,46 +1,54 @@ #ifndef EGG_GFX_I_SCN_PROC_H #define EGG_GFX_I_SCN_PROC_H -#include "eggAssert.h" -#include "types_egg.h" -#include "types_nw4r.h" +#include -#include +#include + +#include + +#include + +#include namespace EGG { -class IScnProc { + +class IScnProc : public IDrawGX { public: - // Unofficial name struct ProcData { IScnProc* mpThis; // at 0x0 nw4r::g3d::ScnProc* mpScnProc; // at 0x4 u16 mIndex; // at 0x8 - bool bUseOpa; // at 0xA + bool mOpa; // at 0xA }; public: IScnProc(); - virtual ~IScnProc(); // at 0x8 - virtual void doDraw(u16) = 0; // at 0xC + virtual ~IScnProc(); // at 0x8 + virtual void scnProcDraw(u16 idx) = 0; // at 0xC - void createScnProc(u16 procNum, MEMAllocator* allocator); - void setPriorityScnProc(u16, u8, bool); - void pushBackToScnGroup(nw4r::g3d::ScnGroup*); - void removeFromScnGroup(nw4r::g3d::ScnGroup*); - static void drawProcFunc(nw4r::g3d::ScnProc*, bool); + void createScnProc(u16 procNum, MEMAllocator* pAllocator); + void setPriorityScnProc(u16 procIndex, u8 priority, bool opa); + + void pushBackToScnGroup(nw4r::g3d::ScnGroup* pScnGroup); + void removeFromScnGroup(nw4r::g3d::ScnGroup* pScnGroup); - u16 getNumScnProc() { - return mNumScnProc; - } ProcData* getData(u16 procIndex) { #line 86 EGG_ASSERT(procIndex < getNumScnProc()); return &mpDataSet[procIndex]; } + u16 getNumScnProc() const { + return mNumScnProc; + } + +private: + static void drawProcFunc(nw4r::g3d::ScnProc* pScnProc, bool opa); private: ProcData* mpDataSet; // at 0x4 u16 mNumScnProc; // at 0x8 }; + } // namespace EGG #endif diff --git a/include/egg/gfx/eggIScnProcModel.h b/include/egg/gfx/eggIScnProcModel.h index a18cc15..65d6722 100644 --- a/include/egg/gfx/eggIScnProcModel.h +++ b/include/egg/gfx/eggIScnProcModel.h @@ -3,16 +3,18 @@ #include "types_egg.h" #include "types_nw4r.h" -namespace EGG { -class IScnProcModel { -public: - IScnProcModel() {} - virtual ~IScnProcModel() {} // at 0x8 - virtual void draw(bool, u32) = 0; // at 0xC - virtual UNKTYPE VF_0x10(UNKTYPE) = 0; // at 0x10 - virtual void getMinMaxScnProcModel(nw4r::math::VEC3*, - nw4r::math::VEC3*) const = 0; // at 0x14 -}; -} // namespace EGG +namespace EGG +{ + class IScnProcModel + { + public: + IScnProcModel() {} + virtual ~IScnProcModel() {} // at 0x8 + virtual void draw(bool, u32) = 0; // at 0xC + virtual UNKTYPE VF_0x10(UNKTYPE) = 0; // at 0x10 + virtual void getMinMaxScnProcModel( + nw4r::math::VEC3 *, nw4r::math::VEC3 *) const = 0; // at 0x14 + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggLightManager.h b/include/egg/gfx/eggLightManager.h index 7330477..7842cec 100644 --- a/include/egg/gfx/eggLightManager.h +++ b/include/egg/gfx/eggLightManager.h @@ -1,55 +1,54 @@ #ifndef EGG_GFX_LIGHT_MANAGER_H #define EGG_GFX_LIGHT_MANAGER_H -#include "eggIBinary.h" #include "types_egg.h" -#include "types_nw4r.h" - -namespace EGG { -class LightManager : IBinary { -public: - struct Bin : IBinary::Bin {}; - -public: - LightManager(u32, u32, u8); - virtual void SetBinaryInner(const Bin&); // at 0x8 - virtual void GetBinaryInner(Bin*) const; // at 0xC - virtual const char* GetBinaryType() const; // at 0x10 - virtual u32 GetBinarySize() const; // at 0x14 - virtual u8 GetVersion() const = 0; // at 0x18 - virtual ~LightManager(); // at 0x1C - - void Reset(); - void Calc(nw4r::g3d::ScnRoot*); - void CalcView(const nw4r::math::MTX34&, u8, nw4r::g3d::ScnRoot*); - - void DoneDraw(); - - LightObj* GetLightObj(u16 index) const { -#line 157 - EGG_ASSERT(index < GetNum()); - return m_ppLightSet[index]; - } - - u16 GetNum() const { - return m_numLight; - } - u8 GetCurrentView() const { - return m_currentView; - } - LightTextureManager* GetLightTextureManager() const { - return m_pLightTextureManager; - } - -private: - u16 m_numLight; // at 0x4 - char UNK_0x8[0xC - 0x8]; - LightObj** m_ppLightSet; // at 0xC - char UNK_0X10[0x18 - 0x10]; - u8 m_viewNum; // at 0x18 - u8 m_currentView; // at 0x19 - char UNK_0x1A[0x20 - 0x1A]; - LightTextureManager* m_pLightTextureManager; // at 0x20 -}; -} // namespace EGG +#include "eggIBinary.h" +#include + +namespace EGG +{ + class LightManager : IBinary + { + public: + struct Bin : IBinary::Bin + { + }; + + public: + LightManager(u32, u32, u8); + virtual void SetBinaryInner(const Bin&); // at 0x8 + virtual void GetBinaryInner(Bin *) const; // at 0xC + virtual const char * GetBinaryType() const; // at 0x10 + virtual u32 GetBinarySize() const; // at 0x14 + virtual u8 GetVersion() const = 0; // at 0x18 + virtual ~LightManager(); // at 0x1C + + void Reset(); + void Calc(nw4r::g3d::ScnRoot *); + void CalcView(const nw4r::math::MTX34&, u8, nw4r::g3d::ScnRoot *); + + void DoneDraw(); + + LightObj * GetLightObj(u16 index) const + { + #line 157 + EGG_ASSERT(index < GetNum()); + return m_ppLightSet[index]; + } + + u16 GetNum() const { return m_numLight; } + u8 GetCurrentView() const { return m_currentView; } + LightTextureManager * GetLightTextureManager() const { return m_pLightTextureManager; } + + private: + u16 m_numLight; // at 0x4 + char UNK_0x8[0xC - 0x8]; + LightObj **m_ppLightSet; // at 0xC + char UNK_0X10[0x18 - 0x10]; + u8 m_viewNum; // at 0x18 + u8 m_currentView; // at 0x19 + char UNK_0x1A[0x20 - 0x1A]; + LightTextureManager *m_pLightTextureManager; // at 0x20 + }; +} #endif diff --git a/include/egg/gfx/eggLightObject.h b/include/egg/gfx/eggLightObject.h index eb729d6..98910d1 100644 --- a/include/egg/gfx/eggLightObject.h +++ b/include/egg/gfx/eggLightObject.h @@ -2,69 +2,69 @@ #define EGG_GFX_LIGHT_OBJECT_H #include "eggIBinary.h" #include "eggVector.h" - #include -namespace EGG { -class LightObj : IBinary { -public: - struct Bin : IBinary::Bin { - u8 spotFn; // at 0x10 - u8 distAttnFn; // at 0x11 - u8 BYTE_0x12; - u8 BYTE_0x13; - u16 ambLightIdx; // at 0x14 - u16 flags; // at 0x16 - Vector3f pos; // at 0x18 - Vector3f target; // at 0x24 - f32 intensity; // at 0x30 - GXColor color; // at 0x34 - GXColor COLOR_0x38; - f32 spotArg; // at 0x3C - f32 distAttnArg0; // at 0x40 - f32 distAttnArg1; // at 0x44 - char UNK_0x48[0x8]; - }; +namespace EGG +{ + class LightObj : IBinary + { + public: + struct Bin : IBinary::Bin + { + u8 spotFn; // at 0x10 + u8 distAttnFn; // at 0x11 + u8 BYTE_0x12; + u8 BYTE_0x13; + u16 ambLightIdx; // at 0x14 + u16 flags; // at 0x16 + Vector3f pos; // at 0x18 + Vector3f target; // at 0x24 + f32 intensity; // at 0x30 + GXColor color; // at 0x34 + GXColor COLOR_0x38; + f32 spotArg; // at 0x3C + f32 distAttnArg0; // at 0x40 + f32 distAttnArg1; // at 0x44 + char UNK_0x48[0x8]; + }; -public: - LightObj(); - virtual void SetBinaryInner(const Bin&); // at 0x8 - virtual void GetBinaryInner(Bin*) const; // at 0xC - virtual const char* GetBinaryType() const; // 0x10 - virtual u32 GetBinarySize() const; // 0x14 - virtual u8 GetVersion() const; // 0x18 + public: + LightObj(); + virtual void SetBinaryInner(const Bin&); // at 0x8 + virtual void GetBinaryInner(Bin *) const; // at 0xC + virtual const char * GetBinaryType() const; // 0x10 + virtual u32 GetBinarySize() const; // 0x14 + virtual u8 GetVersion() const; // 0x18 - // TO-DO: Document flags and remove accessor - u16 getFlags() { - return mFlags; - } + // TO-DO: Document flags and remove accessor + u16 getFlags() { return mFlags; } -private: - u16 mAmbLightIdx; // at 0x4 - Vector3f mTarget; // at 0x8 - Vector3f mPos; // at 0x14 - Vector3f mDirection; // at 0x20 - GXColor mColor; // at 0x2C - f32 mIntensity; // at 0x30 - UNKWORD WORD_0x34; - f32 FLOAT_0x38; - GXColor COLOR_0x3C; - UNKWORD WORD_0x40; - f32 mSpotArg; // at 0x44 - f32 mDistAttn_Arg0; // at 0x48 - f32 mDistAttn_Arg1; // at 0x4C - f32 mAttnA_Arg0; // at 0x50 - f32 mAttnA_Arg1; // at 0x54 - f32 mAttnA_Arg2; // at 0x58 - f32 mAttnK_Arg0; // at 0x5C - f32 mAttnK_Arg1; // at 0x60 - f32 mAttnK_Arg2; // at 0x64 - GXSpotFn mSpotFn; // at 0x68 - GXDistAttnFn mDistAttnFn; // at 0x6C - f32 FLOAT_0x70; - u16 SHORT_0x74; - u16 mFlags; // at 0x76 -}; -} // namespace EGG + private: + u16 mAmbLightIdx; // at 0x4 + Vector3f mTarget; // at 0x8 + Vector3f mPos; // at 0x14 + Vector3f mDirection; // at 0x20 + GXColor mColor; // at 0x2C + f32 mIntensity; // at 0x30 + UNKWORD WORD_0x34; + f32 FLOAT_0x38; + GXColor COLOR_0x3C; + UNKWORD WORD_0x40; + f32 mSpotArg; // at 0x44 + f32 mDistAttn_Arg0; // at 0x48 + f32 mDistAttn_Arg1; // at 0x4C + f32 mAttnA_Arg0; // at 0x50 + f32 mAttnA_Arg1; // at 0x54 + f32 mAttnA_Arg2; // at 0x58 + f32 mAttnK_Arg0; // at 0x5C + f32 mAttnK_Arg1; // at 0x60 + f32 mAttnK_Arg2; // at 0x64 + GXSpotFn mSpotFn; // at 0x68 + GXDistAttnFn mDistAttnFn; // at 0x6C + f32 FLOAT_0x70; + u16 SHORT_0x74; + u16 mFlags; // at 0x76 + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggLightTexture.h b/include/egg/gfx/eggLightTexture.h index 0d541dd..e9023c9 100644 --- a/include/egg/gfx/eggLightTexture.h +++ b/include/egg/gfx/eggLightTexture.h @@ -1,40 +1,42 @@ #ifndef EGG_GFX_LIGHT_TEXTURE_H #define EGG_GFX_LIGHT_TEXTURE_H -#include "eggCapTexture.h" +#include "types_egg.h" #include "eggIBinary.h" #include "eggScreen.h" -#include "types_egg.h" - -namespace EGG { -class LightTexture : public CapTexture, public IBinary { -public: - struct Bin : IBinary::Bin {}; - -public: - static void initialize(u16, Heap*); - static void initDrawSetting(u16, u16, u16, u16); - static void getDrawSetting(u16*, u16*, u16*, u16*, u16); - - LightTexture(u16, const char*, LightTextureManager*); - virtual void SetBinaryInner(const IBinary::Bin&); // at 0x8 - virtual void GetBinaryInner(IBinary::Bin*) const; // at 0xC - virtual const char* GetBinaryType() const; // at 0x10 - virtual u8 GetVersion() const; // at 0x18 - - void draw(); - void capture(const GXColor&, bool); - - const char* getName() const { - return mName; - } - -private: - static const int MAX_NAME_LEN = 32; - - char UNK_0x2C[0x54 - 0x2C]; - char mName[MAX_NAME_LEN]; // at 0x54 - char UNK_0x74[0x84 - 0x74]; -}; -} // namespace EGG +#include "eggCapTexture.h" -#endif +namespace EGG +{ + class LightTexture : public CapTexture, public IBinary + { + public: + struct Bin : IBinary::Bin + { + }; + + public: + static void initialize(u16, Heap *); + static void initDrawSetting(u16, u16, u16, u16); + static void getDrawSetting(u16 *, u16 *, u16 *, u16 *, u16); + + LightTexture(u16, const char *, LightTextureManager *); + virtual void SetBinaryInner(const IBinary::Bin&); // at 0x8 + virtual void GetBinaryInner(IBinary::Bin *) const; // at 0xC + virtual const char * GetBinaryType() const; // at 0x10 + virtual u8 GetVersion() const; // at 0x18 + + void draw(); + void capture(const GXColor&, bool); + + const char * getName() const { return mName; } + + private: + static const int MAX_NAME_LEN = 32; + + char UNK_0x2C[0x54 - 0x2C]; + char mName[MAX_NAME_LEN]; // at 0x54 + char UNK_0x74[0x84 - 0x74]; + }; +} + +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggLightTextureManager.h b/include/egg/gfx/eggLightTextureManager.h index 1efb0b9..dcc8023 100644 --- a/include/egg/gfx/eggLightTextureManager.h +++ b/include/egg/gfx/eggLightTextureManager.h @@ -1,52 +1,54 @@ #ifndef EGG_GFX_LIGHT_TEXTURE_MANAGER_H #define EGG_GFX_LIGHT_TEXTURE_MANAGER_H +#include "types_egg.h" #include "eggIBinary.h" #include "eggScreen.h" -#include "types_egg.h" -namespace EGG { -class LightTextureManager : IBinary { -public: - struct Bin : IBinary::Bin { - char UNK_0x10[0x20 - 0x10]; +namespace EGG +{ + class LightTextureManager : IBinary + { + public: + struct Bin : IBinary::Bin + { + char UNK_0x10[0x20 - 0x10]; + }; + + enum LightTexMgrFlag + { + CLEAR_WORKSPACE = (1 << 3) + }; + + public: + LightTextureManager(LightManager *); + virtual void SetBinaryInner(const IBinary::Bin&); // at 0x8 + virtual void GetBinaryInner(IBinary::Bin *) const; // at 0xC + virtual const char * GetBinaryType() const; // at 0x10 + virtual u8 GetVersion() const = 0; // at 0x18 + + u16 createTexture(const char *); + int replaceModelTexture(int, ModelEx *) const; + int getTextureIndex(const char *) const; + void correctLightObject(); + void frameReset(); + void draw(LightManager *, const Screen::DataEfb&, f32, f32, f32, f32); + + bool isEnableClearWorkSpace() const { return mFlags & CLEAR_WORKSPACE; } + + u32 getMax() const { return LIGHT_TEX_MAX; } + + private: + u8 mFlags; // at 0x4 + u16 mTexNum; // at 0x6 + LightTexture **mppLightTextures; // at 0x8 + LightManager *mpLightManager; // at 0xC + u32 mDrawFlags; // at 0x10 + u16 mLightObjNum; // at 0x14 + LightObj **mppLightObjs; // at 0x18 + + static const int LIGHT_TEX_MAX = 32; + static const int LIGHT_OBJ_MAX = 32; }; +} - enum LightTexMgrFlag { CLEAR_WORKSPACE = (1 << 3) }; - -public: - LightTextureManager(LightManager*); - virtual void SetBinaryInner(const IBinary::Bin&); // at 0x8 - virtual void GetBinaryInner(IBinary::Bin*) const; // at 0xC - virtual const char* GetBinaryType() const; // at 0x10 - virtual u8 GetVersion() const = 0; // at 0x18 - - u16 createTexture(const char*); - int replaceModelTexture(int, ModelEx*) const; - int getTextureIndex(const char*) const; - void correctLightObject(); - void frameReset(); - void draw(LightManager*, const Screen::DataEfb&, f32, f32, f32, f32); - - bool isEnableClearWorkSpace() const { - return mFlags & CLEAR_WORKSPACE; - } - - u32 getMax() const { - return LIGHT_TEX_MAX; - } - -private: - u8 mFlags; // at 0x4 - u16 mTexNum; // at 0x6 - LightTexture** mppLightTextures; // at 0x8 - LightManager* mpLightManager; // at 0xC - u32 mDrawFlags; // at 0x10 - u16 mLightObjNum; // at 0x14 - LightObj** mppLightObjs; // at 0x18 - - static const int LIGHT_TEX_MAX = 32; - static const int LIGHT_OBJ_MAX = 32; -}; -} // namespace EGG - -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggModelBoundingInfo.h b/include/egg/gfx/eggModelBoundingInfo.h index f51898a..cb0ded2 100644 --- a/include/egg/gfx/eggModelBoundingInfo.h +++ b/include/egg/gfx/eggModelBoundingInfo.h @@ -1,71 +1,81 @@ #ifndef EGG_GFX_MODEL_BOUNDING_INFO_H #define EGG_GFX_MODEL_BOUNDING_INFO_H -#include "eggAssert.h" #include "types_egg.h" +#include "eggAssert.h" -namespace EGG { -class ModelBoundingInfo { -public: - enum ModelBoundType { - MODEL_HAS_AABB_0xC = (1 << 0), - MODEL_HAS_SPHERE = (1 << 2), - }; - - struct AABBData { - struct AABBShape { - f32 FLOAT_0x0; - f32 FLOAT_0x4; - f32 FLOAT_0x8; - f32 FLOAT_0xC; - f32 FLOAT_0x10; - f32 FLOAT_0x14; +namespace EGG +{ + class ModelBoundingInfo + { + public: + enum ModelBoundType + { + MODEL_HAS_AABB_0xC = (1 << 0), + MODEL_HAS_SPHERE = (1 << 2), }; - AABBShape m_shape; // at 0x0 - AABBShape* m_pShapeSet; // at 0x18 - }; + struct AABBData + { + struct AABBShape + { + f32 FLOAT_0x0; + f32 FLOAT_0x4; + f32 FLOAT_0x8; + f32 FLOAT_0xC; + f32 FLOAT_0x10; + f32 FLOAT_0x14; + }; - struct SphereData { - struct SphereShape { - f32 FLOAT_0x0; - f32 FLOAT_0x4; - f32 FLOAT_0x8; - f32 FLOAT_0xC; + AABBShape m_shape; // at 0x0 + AABBShape *m_pShapeSet; // at 0x18 }; - SphereShape m_shape; // at 0x0 - SphereShape* m_pShapeSet; // at 0x10 - }; + struct SphereData + { + struct SphereShape + { + f32 FLOAT_0x0; + f32 FLOAT_0x4; + f32 FLOAT_0x8; + f32 FLOAT_0xC; + }; + + SphereShape m_shape; // at 0x0 + SphereShape *m_pShapeSet; // at 0x10 + }; -protected: - ModelEx* m_pMdl; // at 0x0 - f32 FLOAT_0x4; - AABBData* m_pAABB; // at 0x8 - AABBData* AABB_0xC; - SphereData* m_pSphere; // at 0x10 + protected: + ModelEx *m_pMdl; // at 0x0 + f32 FLOAT_0x4; + AABBData *m_pAABB; // at 0x8 + AABBData *AABB_0xC; + SphereData *m_pSphere; // at 0x10 -public: - ModelBoundingInfo(u32, ModelEx*); - virtual ~ModelBoundingInfo(); + public: + ModelBoundingInfo(u32, ModelEx *); + virtual ~ModelBoundingInfo(); - SphereData* getSphere() const { -#line 99 - EGG_ASSERT(m_pSphere); - return m_pSphere; - } + SphereData * getSphere() const + { + #line 99 + EGG_ASSERT(m_pSphere); + return m_pSphere; + } - // 80094b64, stub inline for weak data in eggModelEx.o - UNKTYPE UNKNOWN_INLINE_1(SphereData* pSphere) { -#line 191 - EGG_ASSERT(pSphere); - } + // 80094b64, stub inline for weak data in eggModelEx.o + UNKTYPE UNKNOWN_INLINE_1(SphereData *pSphere) + { + #line 191 + EGG_ASSERT(pSphere); + } - // 80093db8, stub inline for weak data in eggModelEx.o - UNKTYPE UNKNOWN_INLINE_0(AABBData* pAABB) { -#line 214 - EGG_ASSERT(pAABB); - } -}; -} // namespace EGG + // 80093db8, stub inline for weak data in eggModelEx.o + UNKTYPE UNKNOWN_INLINE_0(AABBData *pAABB) + { + #line 214 + EGG_ASSERT(pAABB); + } + }; +} #endif diff --git a/include/egg/gfx/eggModelEx.h b/include/egg/gfx/eggModelEx.h index 4c51f8b..56d589f 100644 --- a/include/egg/gfx/eggModelEx.h +++ b/include/egg/gfx/eggModelEx.h @@ -1,13 +1,9 @@ #ifndef EGG_GFX_MODEL_EX_H #define EGG_GFX_MODEL_EX_H #include "eggAssert.h" -#include "g3d_resmat.h" -#include "g3d_resmdl.h" -#include "g3d_resshp.h" -#include "g3d_scnobj.h" -#include "g3d_scnproc.h" #include "math_types.h" #include "types_egg.h" +#include namespace EGG { struct TextureReplaceResult { union Data { diff --git a/include/egg/gfx/eggModelSnapshot.h b/include/egg/gfx/eggModelSnapshot.h index eee31b2..4c6ca2c 100644 --- a/include/egg/gfx/eggModelSnapshot.h +++ b/include/egg/gfx/eggModelSnapshot.h @@ -1,49 +1,55 @@ #ifndef EGG_GFX_MODEL_SNAPSHOT_H #define EGG_GFX_MODEL_SNAPSHOT_H -#include "eggCapTexture.h" #include "types_egg.h" +#include "eggCapTexture.h" -namespace EGG { -class ModelSnapshot : public CapTexture { -public: - enum SnapshotFlag { SNAPSHOT_0x2 = (1 << 1) }; +namespace EGG +{ + class ModelSnapshot : public CapTexture + { + public: + enum SnapshotFlag + { + SNAPSHOT_0x2 = (1 << 1) + }; - struct ModelBind { - ModelEx* model; // at 0x0 - f32 FLOAT_0x4; - u8 BYTE_0x8; - }; + struct ModelBind + { + ModelEx *model; // at 0x0 + f32 FLOAT_0x4; + u8 BYTE_0x8; + }; -public: - ModelSnapshot(u16, u16, GXTexFmt, u16); - virtual ~ModelSnapshot(); // at 0x8 - virtual void DoResetList(); // at 0x18 - virtual void ResetList(); // at 0x1C + public: + ModelSnapshot(u16, u16, GXTexFmt, u16); + virtual ~ModelSnapshot(); // at 0x8 + virtual void DoResetList(); // at 0x18 + virtual void ResetList(); // at 0x1C + + void AddModelEx(ModelEx *, f32); + void GatherModel(f32); - void AddModelEx(ModelEx*, f32); - void GatherModel(f32); - -private: - u16 m_mdlMax; // at 0x2C - u16 m_width; // at 0x2E - u16 m_height; // at 0x30 - u16 m_mdlNum; // at 0x32 - u8 m_flags; // at 0x34 - UNKWORD WORD_0x38; - ModelBind* m_mdlList; // at 0x3C - f32 FLOAT_0x40; - f32 FLOAT_0x44; - f32 FLOAT_0x48; - f32 FLOAT_0x4C; - f32 FLOAT_0x50; - f32 FLOAT_0x54; - f32 FLOAT_0x58; - f32 FLOAT_0x5C; - f32 FLOAT_0x60; - f32 FLOAT_0x64; - f32 FLOAT_0x68; - f32 FLOAT_0x6C; -}; -} // namespace EGG + private: + u16 m_mdlMax; // at 0x2C + u16 m_width; // at 0x2E + u16 m_height; // at 0x30 + u16 m_mdlNum; // at 0x32 + u8 m_flags; // at 0x34 + UNKWORD WORD_0x38; + ModelBind *m_mdlList; // at 0x3C + f32 FLOAT_0x40; + f32 FLOAT_0x44; + f32 FLOAT_0x48; + f32 FLOAT_0x4C; + f32 FLOAT_0x50; + f32 FLOAT_0x54; + f32 FLOAT_0x58; + f32 FLOAT_0x5C; + f32 FLOAT_0x60; + f32 FLOAT_0x64; + f32 FLOAT_0x68; + f32 FLOAT_0x6C; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggPostEffectBase.h b/include/egg/gfx/eggPostEffectBase.h index e66055b..e3a4c61 100644 --- a/include/egg/gfx/eggPostEffectBase.h +++ b/include/egg/gfx/eggPostEffectBase.h @@ -1,61 +1,60 @@ #ifndef EGG_GFX_POST_EFFECT_BASE_H #define EGG_GFX_POST_EFFECT_BASE_H -#include "eggAssert.h" #include "types_egg.h" - #include +#include "eggAssert.h" -namespace EGG { -class PostEffectBase { -public: - enum PostEffectFlags { POSTEFFECT_HIDDEN = 0x1 }; - -protected: - u16 mFlags; // at 0x0 - u32 mBlendMode; // at 0x4 - CapTexture* mpCapTexture; // at 0x8 - f32 mOffsetX; // at 0xC - f32 mOffsetY; // at 0x10 - f32 mScaleX; // at 0x14 - f32 mScaleY; // at 0x18 - -public: - PostEffectBase(); - virtual ~PostEffectBase() {} // at 0x8 - virtual void onReset(); // at 0xC - virtual void draw(f32, f32); // at 0x10 - virtual void reset(); // at 0x14 - virtual void preDraw(); // at 0x18 - virtual void drawDL(f32, f32, f32, f32); // at 0x1C - virtual void loadTexObj(); // at 0x20 - - bool isVisible() const { - return ((mFlags & POSTEFFECT_HIDDEN) == 0); - } - - void setBlendMode(u32 mode) { - mBlendMode = mode; - } - - CapTexture* getCapTexture() const { - return mpCapTexture; - } - void setCapTexture(CapTexture* pCapTexture) { -#line 95 - EGG_ASSERT(pCapTexture); - mpCapTexture = pCapTexture; - } - - void drawTexture(); - void setVtxState(); - void setMatColorChannel(); - void setMatInd(); - void setMatPE(); - void setBlendModeInternal(); - - static void scaleColor(GXColor&, const GXColor&, f32, bool); - static void setProjection(const Screen&); -}; -} // namespace EGG - -#endif +namespace EGG +{ + class PostEffectBase + { + public: + enum PostEffectFlags + { + POSTEFFECT_HIDDEN = 0x1 + }; + + protected: + u16 mFlags; // at 0x0 + u32 mBlendMode; // at 0x4 + CapTexture *mpCapTexture; // at 0x8 + f32 mOffsetX; // at 0xC + f32 mOffsetY; // at 0x10 + f32 mScaleX; // at 0x14 + f32 mScaleY; // at 0x18 + + public: + PostEffectBase(); + virtual ~PostEffectBase() {} // at 0x8 + virtual void onReset(); // at 0xC + virtual void draw(f32, f32); // at 0x10 + virtual void reset(); // at 0x14 + virtual void preDraw(); // at 0x18 + virtual void drawDL(f32, f32, f32, f32); // at 0x1C + virtual void loadTexObj(); // at 0x20 + + bool isVisible() const { return ((mFlags & POSTEFFECT_HIDDEN) == 0); } + + void setBlendMode(u32 mode) { mBlendMode = mode; } + + CapTexture * getCapTexture() const { return mpCapTexture; } + void setCapTexture(CapTexture *pCapTexture) + { + #line 95 + EGG_ASSERT(pCapTexture); + mpCapTexture = pCapTexture; + } + + void drawTexture(); + void setVtxState(); + void setMatColorChannel(); + void setMatInd(); + void setMatPE(); + void setBlendModeInternal(); + + static void scaleColor(GXColor&, const GXColor&, f32, bool); + static void setProjection(const Screen&); + }; +} + +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggPostEffectBlur.h b/include/egg/gfx/eggPostEffectBlur.h index e44d885..fb08a22 100644 --- a/include/egg/gfx/eggPostEffectBlur.h +++ b/include/egg/gfx/eggPostEffectBlur.h @@ -1,51 +1,56 @@ #ifndef EGG_GFX_POST_EFFECT_BLUR_H #define EGG_GFX_POST_EFFECT_BLUR_H -#include "eggAssert.h" -#include "eggPostEffectBase.h" #include "types_egg.h" +#include "eggPostEffectBase.h" +#include "eggAssert.h" -namespace EGG { -class PostEffectBlur : public PostEffectBase { -public: - struct BlurData { - void reset() { - BYTE_0x0 = 0x10; - mColor = (GXColor){215, 215, 215, 215}; - FLOAT_0x8 = 0.0f; - mRadius = 1.0f; - WORD_0x10 = 0; +namespace EGG +{ + class PostEffectBlur : public PostEffectBase + { + public: + struct BlurData + { + void reset() + { + BYTE_0x0 = 0x10; + mColor = (GXColor){215, 215, 215, 215}; + FLOAT_0x8 = 0.0f; + mRadius = 1.0f; + WORD_0x10 = 0; + } + + u8 BYTE_0x0; + GXColor mColor; // at 0x1 + f32 FLOAT_0x8; + f32 mRadius; // at 0xC + u32 WORD_0x10; + }; + + public: + PostEffectBlur(); + virtual ~PostEffectBlur() {} // at 0x8 + virtual void draw(f32, f32); // at 0x10 + virtual void reset(); // at 0x14 + + void drawBlurPass(u8, u8); + + BlurData * getBlurData(int dataNum) + { + #line 102 + EGG_ASSERT(dataNum < CIRCLE_MAX); + return &mBlurData[dataNum]; } - u8 BYTE_0x0; - GXColor mColor; // at 0x1 - f32 FLOAT_0x8; - f32 mRadius; // at 0xC - u32 WORD_0x10; - }; - -public: - PostEffectBlur(); - virtual ~PostEffectBlur() {} // at 0x8 - virtual void draw(f32, f32); // at 0x10 - virtual void reset(); // at 0x14 - - void drawBlurPass(u8, u8); - - BlurData* getBlurData(int dataNum) { -#line 102 - EGG_ASSERT(dataNum < CIRCLE_MAX); - return &mBlurData[dataNum]; - } + private: + static const u32 CIRCLE_MAX = 4; -private: - static const u32 CIRCLE_MAX = 4; - - u8 mNumBlurData; // at 0x20 - u32 WORD_0x24; - char UNK_0x28[0x2C - 0x28]; - f32 mColorScale; // at 0x2C - BlurData mBlurData[CIRCLE_MAX]; // at 0x30 -}; -} // namespace EGG + u8 mNumBlurData; // at 0x20 + u32 WORD_0x24; + char UNK_0x28[0x2C - 0x28]; + f32 mColorScale; // at 0x2C + BlurData mBlurData[CIRCLE_MAX]; // at 0x30 + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggPostEffectBlurGather.h b/include/egg/gfx/eggPostEffectBlurGather.h index 22496c8..18ced80 100644 --- a/include/egg/gfx/eggPostEffectBlurGather.h +++ b/include/egg/gfx/eggPostEffectBlurGather.h @@ -1,51 +1,57 @@ #ifndef EGG_GFX_POST_EFFECT_BLUR_GATHER_H #define EGG_GFX_POST_EFFECT_BLUR_GATHER_H +#include "types_egg.h" +#include "eggPostEffectBase.h" #include "eggAssert.h" #include "eggDrawGX.h" -#include "eggPostEffectBase.h" -#include "types_egg.h" -namespace EGG { -class PostEffectBlurGather : public PostEffectBase { -public: - enum Constants { eCnstBlurGather_Max = 3 }; - - struct BlurGatherData { - void reset() { - mpCapTexture = NULL; - mColor = DrawGX::scColorWhite; - mColorScale = 1.0f; - BYTE_0xC = 0; +namespace EGG +{ + class PostEffectBlurGather : public PostEffectBase + { + public: + enum Constants + { + eCnstBlurGather_Max = 3 + }; + + struct BlurGatherData + { + void reset() + { + mpCapTexture = NULL; + mColor = DrawGX::WHITE; + mColorScale = 1.0f; + BYTE_0xC = 0; + } + + CapTexture *mpCapTexture; // at 0x0 + GXColor mColor; // at 0x4 + f32 mColorScale; // at 0x8 + u8 BYTE_0xC; + }; + + public: + PostEffectBlurGather(); + virtual ~PostEffectBlurGather() {} // at 0x8 + virtual void reset(); // at 0x14 + virtual void preDraw(); // at 0x18 + + void setNumBlurGather(u8 num) + { + #line 58 + EGG_ASSERT(num <= eCnstBlurGather_Max); + mNumBlurGatherData = num; } - CapTexture* mpCapTexture; // at 0x0 - GXColor mColor; // at 0x4 - f32 mColorScale; // at 0x8 - u8 BYTE_0xC; - }; + bool textureReady() const { return mpCapTexture != NULL && (mFlags & 0x1) == 0; } -public: - PostEffectBlurGather(); - virtual ~PostEffectBlurGather() {} // at 0x8 - virtual void reset(); // at 0x14 - virtual void preDraw(); // at 0x18 - - void setNumBlurGather(u8 num) { -#line 58 - EGG_ASSERT(num <= eCnstBlurGather_Max); - mNumBlurGatherData = num; - } - - bool textureReady() const { - return mpCapTexture != NULL && (mFlags & 0x1) == 0; - } - -private: - u8 mNumBlurGatherData; // at 0x20 - u8 mFlags; // at 0x21 - f32 FLOAT_0x24; - BlurGatherData mBlurGatherData[eCnstBlurGather_Max]; // at 0x28 -}; -} // namespace EGG + private: + u8 mNumBlurGatherData; // at 0x20 + u8 mFlags; // at 0x21 + f32 FLOAT_0x24; + BlurGatherData mBlurGatherData[eCnstBlurGather_Max]; // at 0x28 + }; +} #endif diff --git a/include/egg/gfx/eggPostEffectHDR.h b/include/egg/gfx/eggPostEffectHDR.h index 3ebc9a3..bc2c4cf 100644 --- a/include/egg/gfx/eggPostEffectHDR.h +++ b/include/egg/gfx/eggPostEffectHDR.h @@ -1,31 +1,33 @@ #ifndef EGG_GFX_POST_EFFECT_HDR_H #define EGG_GFX_POST_EFFECT_HDR_H -#include "eggPostEffectBase.h" #include "types_egg.h" +#include "eggPostEffectBase.h" -namespace EGG { -class PostEffectHDR : public PostEffectBase { -public: - PostEffectHDR(); - virtual ~PostEffectHDR() {} // at 0x8 - virtual void reset(); // at 0x14 - virtual void preDraw(); // at 0x18 +namespace EGG +{ + class PostEffectHDR : public PostEffectBase + { + public: + PostEffectHDR(); + virtual ~PostEffectHDR() {} // at 0x8 + virtual void reset(); // at 0x14 + virtual void preDraw(); // at 0x18 - void setupRange(); + void setupRange(); -private: - GXColor COLOR_0x20; - GXColor COLOR_0x24; - f32 FLOAT_0x28; - f32 FLOAT_0x2C; - GXColor COLOR_0x30; - GXColor COLOR_0x34; - GXColor COLOR_0x38; - u32 WORD_0x3C; - u32 WORD_0x40; - u8 BYTE_0x44; - u8 BYTE_0x45; -}; -} // namespace EGG + private: + GXColor COLOR_0x20; + GXColor COLOR_0x24; + f32 FLOAT_0x28; + f32 FLOAT_0x2C; + GXColor COLOR_0x30; + GXColor COLOR_0x34; + GXColor COLOR_0x38; + u32 WORD_0x3C; + u32 WORD_0x40; + u8 BYTE_0x44; + u8 BYTE_0x45; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggPostEffectSimple.h b/include/egg/gfx/eggPostEffectSimple.h index c15a1fb..b8722d5 100644 --- a/include/egg/gfx/eggPostEffectSimple.h +++ b/include/egg/gfx/eggPostEffectSimple.h @@ -1,22 +1,24 @@ #ifndef EGG_GFX_POST_EFFECT_SIMPLE_H #define EGG_GFX_POST_EFFECT_SIMPLE_H -#include "eggPostEffectBase.h" #include "types_egg.h" +#include "eggPostEffectBase.h" -namespace EGG { -class PostEffectSimple : public PostEffectBase { -public: - PostEffectSimple(); - virtual ~PostEffectSimple() {} // at 0x8 - virtual void reset(); // at 0x14 - virtual void preDraw(); // at 0x18 +namespace EGG +{ + class PostEffectSimple : public PostEffectBase + { + public: + PostEffectSimple(); + virtual ~PostEffectSimple() {} // at 0x8 + virtual void reset(); // at 0x14 + virtual void preDraw(); // at 0x18 -private: - GXColor mColor; // at 0x20 - f32 FLOAT_0x24; - char UNK_0x28[0x4]; - UNKWORD WORD_0x2C; -}; -} // namespace EGG + private: + GXColor mColor; // at 0x20 + f32 FLOAT_0x24; + char UNK_0x28[0x4]; + UNKWORD WORD_0x2C; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggResTIMG.h b/include/egg/gfx/eggResTIMG.h index 9d39e41..f3cf75b 100644 --- a/include/egg/gfx/eggResTIMG.h +++ b/include/egg/gfx/eggResTIMG.h @@ -1,27 +1,39 @@ #ifndef EGG_GFX_RES_TIMG_H #define EGG_GFX_RES_TIMG_H -#include "types_egg.h" +#include namespace EGG { + +enum JUTTransparency { + JUT_TRANSPARENCY_DISABLE, + JUT_TRANSPARENCY_ENABLE, +}; + struct ResTIMG { - u8 mTexFormat; // at 0x0 - u16 mWidth; // at 0x2 - u16 mHeight; // at 0x4 - u8 mWrapS; // at 0x6 - u8 mWrapT; // at 0x7 - char UNK_0x8[0x10 - 0x8]; - bool mMipmap; // at 0x10 - u8 mEdgeLodEnable; // at 0x11 - u8 mBiasClampEnable; // at 0x12 - u8 mAnisotropy; // at 0x13 - u8 mMinFilt; // at 0x14 - u8 mMagFilt; // at 0x15 - s8 mMinLod; // at 0x16 - s8 mMaxLod; // at 0x17 - char UNK_0x18[0x1A - 0x18]; - s16 mLodBias; // at 0x1A - UNKWORD mImageOfs; // at 0x1C + u8 format; // at 0x0 + u8 transparency; // at 0x1 + u16 width; // at 0x2 + u16 height; // at 0x4 + u8 wrapS; // at 0x6 + u8 wrapT; // at 0x7 + u8 tlutName; // at 0x8 + u8 tlutFormat; // at 0x9 + u16 paletteEntryNum; // at 0xA + s32 paletteOffset; // at 0xC + u8 mipMap; // at 0x10 + u8 edgeLODEnable; // at 0x11 + u8 biasClampEnable; // at 0x12 + u8 anisotropy; // at 0x13 + u8 minFilter; // at 0x14 + u8 magFilter; // at 0x15 + s8 minLOD; // at 0x16 + s8 maxLOD; // at 0x17 + u8 mipMapLevel; // at 0x18 + u8 BYTE_0x19; + s16 LODBias; // at 0x1A + s32 imageOffset; // at 0x1C }; + } // namespace EGG #endif diff --git a/include/egg/gfx/eggScnRenderer.h b/include/egg/gfx/eggScnRenderer.h index cfef41d..61e5bfb 100644 --- a/include/egg/gfx/eggScnRenderer.h +++ b/include/egg/gfx/eggScnRenderer.h @@ -1,77 +1,81 @@ #ifndef EGG_GFX_SCN_RENDERER_H #define EGG_GFX_SCN_RENDERER_H -#include "eggScnRootEx.h" #include "types_egg.h" +#include "eggScnRootEx.h" #include "types_nw4r.h" +#include -#include - -namespace EGG { -class ScnRenderer : ScnRootEx { -public: - enum DrawPathType { - DRAW_PATH_LMAP, - DRAW_PATH_SV, - DRAW_PATH_HDR, - DRAW_PATH_BLOOM, - DRAW_PATH_DOF, +namespace EGG +{ + class ScnRenderer : ScnRootEx + { + public: + enum DrawPathType + { + DRAW_PATH_LMAP, + DRAW_PATH_SV, + DRAW_PATH_HDR, + DRAW_PATH_BLOOM, + DRAW_PATH_DOF, - DRAW_PATH_MAX - }; + DRAW_PATH_MAX + }; - enum ScnRendererFlag { RENDERER_VISIBLE = (1 << 0) }; + enum ScnRendererFlag + { + RENDERER_VISIBLE = (1 << 0) + }; - struct TimingPriority { - u8 localPrio; // at 0x0 - u8 prioMax; // at 0x1 - bool opa; // at 0x2 - }; + struct TimingPriority + { + u8 localPrio; // at 0x0 + u8 prioMax; // at 0x1 + bool opa; // at 0x2 + }; -public: - ScnRenderer(nw4r::g3d::ScnRoot*); - virtual ~ScnRenderer(); // at 0x8 - virtual void configure(); // at 0xC - virtual void changeScnRoot(nw4r::g3d::ScnRoot*); // at 0x14 - virtual void calc_after_CalcWorld(); // at 0x1C - virtual void draw_before_CalcView(); // at 0x24 - virtual u16 getLocalPriorityMax() const; // at 0x30 - virtual u16 getNumDrawPath() const; // at 0x34 - virtual u16 getNumTiming() const; // at 0x38 + public: + ScnRenderer(nw4r::g3d::ScnRoot *); + virtual ~ScnRenderer(); // at 0x8 + virtual void configure(); // at 0xC + virtual void changeScnRoot(nw4r::g3d::ScnRoot *); // at 0x14 + virtual void calc_after_CalcWorld(); // at 0x1C + virtual void draw_before_CalcView(); // at 0x24 + virtual u16 getLocalPriorityMax() const; // at 0x30 + virtual u16 getNumDrawPath() const; // at 0x34 + virtual u16 getNumTiming() const; // at 0x38 - void createPath(u32, MEMAllocator*); - void pushBackDrawPath(); - void setLocalPriorityScnProc(IScnProc*, u32, u8, u16) const; + void createPath(u32, MEMAllocator *); + void pushBackDrawPath(); + void setLocalPriorityScnProc(IScnProc *, u32, u8, u16) const; - bool isVisible() const { - return mFlags & RENDERER_VISIBLE; - } + bool isVisible() const { return mFlags & RENDERER_VISIBLE; } - bool getTimingPriority(u32 timing, u8* localPrioOut, u8* prioMaxOut) const { -#line 193 - EGG_ASSERT(timing < getNumTiming()); - EGG_ASSERT(mpTimingPrioritySet != NULL); + bool getTimingPriority(u32 timing, u8 *localPrioOut, u8 *prioMaxOut) const + { + #line 193 + EGG_ASSERT(timing < getNumTiming()); + EGG_ASSERT(mpTimingPrioritySet != NULL); - if (localPrioOut != NULL) - *localPrioOut = mpTimingPrioritySet[timing].localPrio; - if (prioMaxOut != NULL) - *prioMaxOut = mpTimingPrioritySet[timing].prioMax; - return mpTimingPrioritySet[timing].opa; - } + if (localPrioOut != NULL) *localPrioOut = mpTimingPrioritySet[timing].localPrio; + if (prioMaxOut != NULL) *prioMaxOut = mpTimingPrioritySet[timing].prioMax; + return mpTimingPrioritySet[timing].opa; + } - DrawPathBase* getDrawPathBase(u16 path) const { -#line 119 - EGG_ASSERT(path < getNumDrawPath()); - return mppPathSet[path]; - } + DrawPathBase * getDrawPathBase(u16 path) const + { + #line 119 + EGG_ASSERT(path < getNumDrawPath()); + return mppPathSet[path]; + } -private: - DrawPathBase** mppPathSet; // at 0x54 - TimingPriority* mpTimingPrioritySet; // at 0x58 - u16 mFlags; // at 0x5C + private: + DrawPathBase **mppPathSet; // at 0x54 + TimingPriority *mpTimingPrioritySet; // at 0x58 + u16 mFlags; // at 0x5C - static const u16 LOCAL_PRIO_MAX = 23; - static const u16 NUM_TIMING = 7; -}; -} // namespace EGG + static const u16 LOCAL_PRIO_MAX = 23; + static const u16 NUM_TIMING = 7; + }; +} #endif diff --git a/include/egg/gfx/eggScnRootEx.h b/include/egg/gfx/eggScnRootEx.h index a543f5b..9f2925c 100644 --- a/include/egg/gfx/eggScnRootEx.h +++ b/include/egg/gfx/eggScnRootEx.h @@ -1,95 +1,101 @@ #ifndef EGG_GFX_SCN_ROOT_EX_H #define EGG_GFX_SCN_ROOT_EX_H -#include "eggAssert.h" -#include "eggMatrix.h" -#include "math_types.h" #include "types_egg.h" -#include "types_nw4r.h" +#include "eggMatrix.h" +#include "eggAssert.h" +#include "eggIDrawGX.h" +#include +#include #define CALC_BEFORE_FUNC(x) void calc_before_##x() #define CALC_AFTER_FUNC(x) void calc_after_##x() #define DRAW_BEFORE_FUNC(x) void draw_before_##x() #define DRAW_AFTER_FUNC(x) void draw_after_##x() -namespace EGG { -class ScnRootEx { -public: - enum SceneSetting { - SCENE_SETTING_0x1 = (1 << 0), - SCENE_SETTING_0x2 = (1 << 1), - SCENE_UPDATE_FRAME = (1 << 2), - SCENE_CALC_WORLD = (1 << 3), - SCENE_CALC_MATERIAL = (1 << 4), - SCENE_CALC_VTX = (1 << 5), - SCENE_SETTING_0x40 = (1 << 6), - SCENE_GATHER_DRAW_SCN_OBJ = (1 << 7), - SCENE_Z_SORT = (1 << 8), - SCENE_DRAW_OPA = (1 << 9), - SCENE_DRAW_XLU = (1 << 10), +namespace EGG +{ + class ScnRootEx : public IDrawGX + { + public: + enum SceneSetting + { + SCENE_SETTING_0x1 = (1 << 0), + SCENE_SETTING_0x2 = (1 << 1), + SCENE_UPDATE_FRAME = (1 << 2), + SCENE_CALC_WORLD = (1 << 3), + SCENE_CALC_MATERIAL = (1 << 4), + SCENE_CALC_VTX = (1 << 5), + SCENE_SETTING_0x40 = (1 << 6), + SCENE_GATHER_DRAW_SCN_OBJ = (1 << 7), + SCENE_Z_SORT = (1 << 8), + SCENE_DRAW_OPA = (1 << 9), + SCENE_DRAW_XLU = (1 << 10), - SCENE_SETTING_MAX = (1 << 11), - SCENE_SETTING_ALL = SCENE_SETTING_MAX - 1 - }; + SCENE_SETTING_MAX = (1 << 11), + SCENE_SETTING_ALL = SCENE_SETTING_MAX - 1 + }; - enum DrawSetting { - DRAW_COLOR_UPDATE_OPA = (1 << 0), - DRAW_ALPHA_UPDATE_OPA = (1 << 1), - DRAW_DITHER_OPA = (1 << 2), - DRAW_COLOR_UPDATE_XLU = (1 << 3), - DRAW_ALPHA_UPDATE_XLU = (1 << 4), - DRAW_DITHER_XLU = (1 << 5), + enum DrawSetting + { + DRAW_COLOR_UPDATE_OPA = (1 << 0), + DRAW_ALPHA_UPDATE_OPA = (1 << 1), + DRAW_DITHER_OPA = (1 << 2), + DRAW_COLOR_UPDATE_XLU = (1 << 3), + DRAW_ALPHA_UPDATE_XLU = (1 << 4), + DRAW_DITHER_XLU = (1 << 5), - DRAW_SETTING_MAX = (1 << 6), - DRAW_SETTING_ALL = DRAW_SETTING_MAX - 1 - }; + DRAW_SETTING_MAX = (1 << 6), + DRAW_SETTING_ALL = DRAW_SETTING_MAX - 1 + }; -protected: - nw4r::g3d::ScnRoot* mBase; // at 0x0 - LightManager* mpLightManager; // at 0x4 - FogManager* mpFogManager; // at 0x8 - ShadowTextureManager* mpShadowTextureManager; // at 0xC - u16 mSceneSettings; // at 0x10 - u16 SHORT_0x12; - u16 mDrawSettings; // at 0x14 - nw4r::math::MTX34 mCamMtx; // 0x18 - Screen* mpScreen; // at 0x48 - UNKWORD WORD_0x4C; + protected: + nw4r::g3d::ScnRoot *mBase; // at 0x0 + LightManager *mpLightManager; // at 0x4 + FogManager *mpFogManager; // at 0x8 + ShadowTextureManager *mpShadowTextureManager; // at 0xC + u16 mSceneSettings; // at 0x10 + u16 SHORT_0x12; + u16 mDrawSettings; // at 0x14 + nw4r::math::MTX34 mCamMtx; // 0x18 + Screen *mpScreen; // at 0x48 + UNKWORD WORD_0x4C; -public: - ScnRootEx(nw4r::g3d::ScnRoot*); - virtual ~ScnRootEx(); // at 0x8 - virtual void configure(); // at 0xC - virtual void finishDraw(); // at 0x10 - virtual void changeScnRoot(nw4r::g3d::ScnRoot*); // at 0x14 - virtual CALC_BEFORE_FUNC(CalcWorld); // at 0x18 - virtual CALC_AFTER_FUNC(CalcWorld); // at 0x1C - virtual void SetCurrentCamera(u8, const Screen&); // at 0x20 - virtual DRAW_BEFORE_FUNC(CalcView); // at 0x24 - virtual DRAW_AFTER_FUNC(DrawOpa); // at 0x28 - virtual DRAW_AFTER_FUNC(DrawOpaXlu); // at 0x2C + public: + ScnRootEx(nw4r::g3d::ScnRoot *); + virtual ~ScnRootEx(); // at 0x8 + virtual void configure(); // at 0xC + virtual void finishDraw(); // at 0x10 + virtual void changeScnRoot(nw4r::g3d::ScnRoot *); // at 0x14 + virtual CALC_BEFORE_FUNC(CalcWorld); // at 0x18 + virtual CALC_AFTER_FUNC(CalcWorld); // at 0x1C + virtual void SetCurrentCamera(u8, const Screen&); // at 0x20 + virtual DRAW_BEFORE_FUNC(CalcView); // at 0x24 + virtual DRAW_AFTER_FUNC(DrawOpa); // at 0x28 + virtual DRAW_AFTER_FUNC(DrawOpaXlu); // at 0x2C - void setLightManager(LightManager*); - void setFogManager(FogManager*); + void setLightManager(LightManager *); + void setFogManager(FogManager *); - void UpdateFrame(); - void CalcMaterial(); - void CalcVtx(); - void CalcWorld(); - void SetCurrentCamera(int, const nw4r::math::MTX34&, const Screen&); - void CalcView(); - void GatherDrawScnObj(); - void ZSort(); - void DrawOpa(); - void DrawXlu(); + void UpdateFrame(); + void CalcMaterial(); + void CalcVtx(); + void CalcWorld(); + void SetCurrentCamera(int, const nw4r::math::MTX34&, const Screen&); + void CalcView(); + void GatherDrawScnObj(); + void ZSort(); + void DrawOpa(); + void DrawXlu(); - void setDrawSettingGX(bool) const; + void setDrawSettingGX(bool) const; - Screen& getScreen() const { -#line 171 - EGG_ASSERT(mpScreen); - return *mpScreen; - } -}; -} // namespace EGG + Screen& getScreen() const + { + #line 171 + EGG_ASSERT(mpScreen); + return *mpScreen; + } + }; +} #endif diff --git a/include/egg/gfx/eggScreen.h b/include/egg/gfx/eggScreen.h index 8d3fb8d..5e92078 100644 --- a/include/egg/gfx/eggScreen.h +++ b/include/egg/gfx/eggScreen.h @@ -1,98 +1,142 @@ #ifndef EGG_GFX_SCREEN_H #define EGG_GFX_SCREEN_H -#include "eggFrustum.h" -#include "types_egg.h" +#include + +#include +#include + +#include namespace EGG { class Screen : public Frustum { public: - enum TVMode { TV_MODE_4_3, TV_MODE_16_9, TV_MODE_MAX }; + typedef void (*ChangeTVModeFunc)(void* pArg); - typedef void (*ChangeTVModeFunc)(void*); + enum TVMode { TV_MODE_STD, TV_MODE_WIDE, TV_MODE_MAX }; - struct TVModeRatio { - // Required for static init - TVModeRatio() {} - f32 w_ratio; - f32 h_ratio; + enum FillBufferFlag { + FILLBUFFER_COLOR = 1 << 0, + FILLBUFFER_ALPHA = 1 << 1, + FILLBUFFER_TEXTURE = 1 << 2, }; struct DataEfb { - // Required for struct copy struct Viewport { - f32 x1; // at 0x0 - f32 y1; // at 0x4 - f32 x2; // at 0x8 - f32 y2; // at 0xC - f32 z1; // at 0x10 - f32 z2; // at 0x14 + f32 x; // at 0x0 + f32 y; // at 0x4 + f32 width; // at 0x8 + f32 height; // at 0xC + f32 near; // at 0x10 + f32 far; // at 0x14 } vp; - s32 sc_ox; // at 0x18 - s32 sc_oy; // at 0x1C + s32 ox; // at 0x18 + s32 oy; // at 0x1C }; public: - static void Initialize(const u16*, const u16*, Screen*); - static void CalcRatio(); + static void Initialize(const u16* maxX, const u16* maxY, + Screen* pUserRoot = NULL); - static void SetTVMode(TVMode); - static void SetTVModeDefault(); + Screen(); + Screen(f32 x, f32 y, f32 width, f32 height, const Screen* pParent = NULL, + CanvasMode canvasMode = CANVASMODE_LU); + Screen(const Screen& rOther); + + virtual ~Screen() {} // at 0x8 + virtual void SetProjectionGX() const; // at 0xC + virtual void CopyToG3D(nw4r::g3d::Camera camera) const; // at 0x10 + + void CopyFromAnother(const Screen& rOther); + + void GetPosSizeInEfb() const; + const DataEfb& GetDataEfb() const; + bool IsChangeEfb() const; + + void CalcMatrixForDrawQuad(nw4r::math::MTX34* pMtx, f32 x, f32 y, f32 width, + f32 height) const; + void FillBufferGX(u32 flags, GXColor color, u32 arg2) const; + void GetGlobalPos(f32* pX, f32* pY) const; + + const Screen* GetParent() const { + return mParent; + } + void SetParent(const Screen* pParent) { + mFlags |= FLAG_DIRTY; + + if (spRoot == this) { + mParent = NULL; + } else { + mParent = pParent != NULL ? pParent : spRoot; + } + } + + void SetProjectionAbsolute() const { + mFlags |= FLAG_PROJ_ABSOLUTE; + } static TVMode GetTVMode() { return sTVMode; } - static u16 GetSizeXMax() { + static void SetTVMode(TVMode tvMode); + static void SetTVModeDefault(); + + const nw4r::math::VEC2& GetPosition() const { + return mPosition; + } + void SetPosition(const nw4r::math::VEC2& rPos) { + mPosition = rPos; + } + #if defined(PACK_SPORTS) || defined(PACK_PLAY) + static u16 GetSizeXMax() { return sTVModeWidths[sTVMode]; -#elif defined(PACK_RESORT) - return sTVInfo[sTVMode].width; -#endif } - static u16 GetSizeYMax() { -#if defined(PACK_SPORTS) || defined(PACK_PLAY) return sTVModeHeights[sTVMode]; + } #elif defined(PACK_RESORT) - return sTVInfo[sTVMode].height; -#endif + static u16 GetSizeXMax() { + return sTVModeInfo[sTVMode].width; } + static u16 GetSizeYMax() { + return sTVModeInfo[sTVMode].height; + } +#endif - Screen(); - Screen(f32, f32, f32, f32, const Screen*, CanvasMode); - Screen(const Screen&); - - virtual ~Screen() {} // at 0x8 - virtual void SetProjectionGX() const; // at 0xC - virtual void CopyToG3D(nw4r::g3d::Camera) const; // at 0x10 +private: + enum { + FLAG_ALIGN_EFB_POS = 1 << 1, + FLAG_ALIGN_EFB_SIZE = 1 << 2, + FLAG_VPSIZE_ABSOLUTE = 1 << 3, + FLAG_FORCE_STD_ASPECT = 1 << 5, + FLAG_PROJ_ABSOLUTE = 1 << 7, + }; - const Screen* GetParent() const { - return mParent; - } - void SetParent(const Screen* parent) { - SetDirty(true); + struct TVModeRatio { + TVModeRatio() {} - if (spRoot == this) - mParent = NULL; - else - mParent = (parent != NULL) ? parent : spRoot; - } + f32 widthRatio; // at 0x0 + f32 heightRatio; // at 0x4 + }; - void CopyFromAnother(const Screen& other); - void GetPosSizeInEfb() const; - const DataEfb& GetDataEfb() const; - bool IsChangeEfb() const; - void CalcMatrixForDrawQuad(nw4r::math::MTX34*, f32, f32, f32, f32) const; - void FillBufferGX(u32, GXColor, u32) const; - void GetGlobalPos(f32*, f32*) const; +#if defined(PACK_RESORT) + struct TVModeInfo { + u16 width; + u16 height; + nw4r::math::VEC2 ratios; + }; +#endif private: - void NullSub_0(); + void Configure(); void SetViewGX() const; - void SetViewG3D(nw4r::g3d::Camera) const; + void SetViewG3D(nw4r::g3d::Camera camera) const; + + static void CalcRatio(); private: const Screen* mParent; // at 0x3C @@ -100,30 +144,24 @@ class Screen : public Frustum { mutable DataEfb mDataEfb; // at 0x48 static TVMode sTVMode; + static TVModeRatio sTVModeRatios[Screen::TV_MODE_MAX]; #if defined(PACK_SPORTS) || defined(PACK_PLAY) static u16 sTVModeWidths[TV_MODE_MAX]; static u16 sTVModeHeights[TV_MODE_MAX]; #elif defined(PACK_RESORT) - struct TVInfo { - u16 width; - u16 height; - f32 _08; - f32 _0C; - }; - - static TVInfo sTVInfo[TV_MODE_MAX]; + static TVModeInfo sTVModeInfo[TV_MODE_MAX]; #endif static Screen* spRoot; static ChangeTVModeFunc sChangeTVModeFunc; static void* spChangeTVModeFuncInfo; - static TVModeRatio sTVModeRatios[Screen::TV_MODE_MAX]; static nw4r::math::VEC2 sCanvasScale; static nw4r::math::VEC2 sCanvasOffset; }; + } // namespace EGG #endif diff --git a/include/egg/gfx/eggScreenEffectBase.h b/include/egg/gfx/eggScreenEffectBase.h index d02acbe..8232fb5 100644 --- a/include/egg/gfx/eggScreenEffectBase.h +++ b/include/egg/gfx/eggScreenEffectBase.h @@ -1,116 +1,119 @@ #ifndef EGG_GFX_SCREEN_EFFECT_BASE_H #define EGG_GFX_SCREEN_EFFECT_BASE_H +#include "types_egg.h" #include "eggAssert.h" #include "eggScreen.h" -#include "types_egg.h" - -namespace EGG { -class ScreenEffectBase { -public: - enum ScreenEffectFlags { EFFECT_VISIBLE = (1 << 0), EFFECT_0x2 = (1 << 1) }; - - enum BufferType { - cBufferType_Hide_1_16, - cBufferType_1, - cBufferType_2, - cBufferType_3, - cBufferType_Max - }; - - struct EffectBuffer { - TextureBuffer* mpTexBuffer; // at 0x0 - const ScreenEffectBase* mpAllocBase; // at 0x4 - UNKWORD WORD_0x8; // at 0x8 - }; - - // Workspace viewport - struct WorkView { - f32 x1; // at 0x0 - f32 y1; // at 0x4 - f32 x2; // at 0x8 - f32 y2; // at 0xC - f32 FLOAT_0x10; - f32 FLOAT_0x14; - }; - // For constructing full viewport - struct FullView { - f32 x2; // at 0x0 - f32 y2; // at 0x4 - f32 x1; // at 0x8 - f32 y1; // at 0xC - f32 cx; // at 0x10 - f32 cy; // at 0x14 - f32 z1; // at 0x18 - f32 z2; // at 0x1C +namespace EGG +{ + class ScreenEffectBase + { + public: + enum ScreenEffectFlags + { + EFFECT_VISIBLE = (1 << 0), + EFFECT_0x2 = (1 << 1) + }; + + enum BufferType + { + cBufferType_Hide_1_16, + cBufferType_1, + cBufferType_2, + cBufferType_3, + cBufferType_Max + }; + + struct EffectBuffer + { + TextureBuffer* mpTexBuffer; // at 0x0 + const ScreenEffectBase* mpAllocBase; // at 0x4 + UNKWORD WORD_0x8; // at 0x8 + }; + + // Workspace viewport + struct WorkView + { + f32 x1; // at 0x0 + f32 y1; // at 0x4 + f32 x2; // at 0x8 + f32 y2; // at 0xC + f32 FLOAT_0x10; + f32 FLOAT_0x14; + }; + + // For constructing full viewport + struct FullView + { + f32 x2; // at 0x0 + f32 y2; // at 0x4 + f32 x1; // at 0x8 + f32 y1; // at 0xC + f32 cx; // at 0x10 + f32 cy; // at 0x14 + f32 z1; // at 0x18 + f32 z2; // at 0x1C + }; + + private: + u8 mFlags; // at 0x0 + Screen mScreen; // at 0x4 + + public: + static void clean(); + + static void setBuffer(BufferType type, TextureBuffer* buffer) + { + #line 163 + EGG_ASSERT(type < cBufferType_Max); + spBufferSet[type].mpTexBuffer = buffer; + } + + static void clearBuffer(BufferType type) + { + #line 174 + EGG_ASSERT(type < cBufferType_Max); + spBufferSet[type].mpTexBuffer = NULL; + spBufferSet[type].mpAllocBase = NULL; + spBufferSet[type].WORD_0x8 = 0; + } + + static TextureBuffer* getBuffer(BufferType type) + { + return spBufferSet[type].mpTexBuffer; + } + + ScreenEffectBase(); + virtual ~ScreenEffectBase() {} // at 0x8 + + Screen& GetScreen() { return mScreen; } + const Screen& GetScreen() const { return mScreen; } + + bool isVisible() const { return mFlags & EFFECT_VISIBLE; } + bool isFlag0x2() const { return mFlags & EFFECT_0x2; } + + void copyFromAnother(const Screen&); + TextureBuffer* capture(BufferType, bool) const; + bool release(BufferType) const; + void doCapture(int) const; + void setupGX(bool) const; + const WorkView& setupView() const; + + private: + static EffectBuffer spBufferSet[cBufferType_Max]; + + static WorkView sWorkSpaceV; + static WorkView sWorkSpaceHideV; + + static u32 sCaptureFlag; + public: + // Public for now, until flag test functions are determined + static u32 sFlag; + private: + static u32 D_804BEC58; + static u32 sPushCount; + static s32 sWorkBuffer; }; +} -private: - u8 mFlags; // at 0x0 - Screen mScreen; // at 0x4 - -public: - static void clean(); - - static void setBuffer(BufferType type, TextureBuffer* buffer) { -#line 163 - EGG_ASSERT(type < cBufferType_Max); - spBufferSet[type].mpTexBuffer = buffer; - } - - static void clearBuffer(BufferType type) { -#line 174 - EGG_ASSERT(type < cBufferType_Max); - spBufferSet[type].mpTexBuffer = NULL; - spBufferSet[type].mpAllocBase = NULL; - spBufferSet[type].WORD_0x8 = 0; - } - - static TextureBuffer* getBuffer(BufferType type) { - return spBufferSet[type].mpTexBuffer; - } - - ScreenEffectBase(); - virtual ~ScreenEffectBase() {} // at 0x8 - - Screen& GetScreen() { - return mScreen; - } - const Screen& GetScreen() const { - return mScreen; - } - - bool isVisible() const { - return mFlags & EFFECT_VISIBLE; - } - bool isFlag0x2() const { - return mFlags & EFFECT_0x2; - } - - void copyFromAnother(const Screen&); - TextureBuffer* capture(BufferType, bool) const; - bool release(BufferType) const; - void doCapture(int) const; - void setupGX(bool) const; - const WorkView& setupView() const; - -private: - static EffectBuffer spBufferSet[cBufferType_Max]; - - static WorkView sWorkSpaceV; - static WorkView sWorkSpaceHideV; - - static u32 sCaptureFlag; - -public: - // Public for now, until flag test functions are determined - static u32 sFlag; - -private: - static u32 D_804BEC58; - static u32 sPushCount; - static s32 sWorkBuffer; -}; -} // namespace EGG - -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggShadowTexture.h b/include/egg/gfx/eggShadowTexture.h index 551e9f4..82ca82a 100644 --- a/include/egg/gfx/eggShadowTexture.h +++ b/include/egg/gfx/eggShadowTexture.h @@ -1,32 +1,36 @@ #ifndef EGG_GFX_SHADOW_TEXTURE_H #define EGG_GFX_SHADOW_TEXTURE_H +#include "types_egg.h" #include "eggModelSnapshot.h" #include "eggPostEffectBase.h" -#include "types_egg.h" -namespace EGG { -class ShadowTexture : public ModelSnapshot { -public: - ShadowTexture(u16, u16, u16); +namespace EGG +{ + class ShadowTexture : public ModelSnapshot + { + public: + ShadowTexture(u16, u16, u16); - void Calc(); - void Draw(Screen*, bool, bool, bool); + void Calc(); + void Draw(Screen *, bool, bool, bool); - // Temporary names, needed for regalloc - void SetCapTexture0(CapTexture* pCapTexture) { - POST_EFF_0xE4->setCapTexture(pCapTexture); - } - void SetCapTexture1(CapTexture* pCapTexture) { - POST_EFF_0xE8->setCapTexture(pCapTexture); - } + // Temporary names, needed for regalloc + void SetCapTexture0(CapTexture *pCapTexture) + { + POST_EFF_0xE4->setCapTexture(pCapTexture); + } + void SetCapTexture1(CapTexture *pCapTexture) + { + POST_EFF_0xE8->setCapTexture(pCapTexture); + } - // private: - u16 SHORT_0x70; - char UNK_0x72[0xE4 - 0x72]; - // TO-DO: May not be base - PostEffectBase* POST_EFF_0xE4; - PostEffectBase* POST_EFF_0xE8; -}; -} // namespace EGG + //private: + u16 SHORT_0x70; + char UNK_0x72[0xE4 - 0x72]; + // TO-DO: May not be base + PostEffectBase *POST_EFF_0xE4; + PostEffectBase *POST_EFF_0xE8; + }; +} -#endif +#endif \ No newline at end of file diff --git a/include/egg/gfx/eggShadowTextureManager.h b/include/egg/gfx/eggShadowTextureManager.h index b9cf94e..6cc09bd 100644 --- a/include/egg/gfx/eggShadowTextureManager.h +++ b/include/egg/gfx/eggShadowTextureManager.h @@ -2,33 +2,36 @@ #define EGG_GFX_SHADOW_TEXTURE_MANAGER_H #include "types_egg.h" -namespace EGG { -class ShadowTextureManager { -public: - enum EShadowMgrFlag { SHADOW_MGR_ACTIVE = (1 << 0) }; +namespace EGG +{ + class ShadowTextureManager + { + public: + enum EShadowMgrFlag + { + SHADOW_MGR_ACTIVE = (1 << 0) + }; -private: - static const int GROUP_MAX = 16; + private: + static const int GROUP_MAX = 16; - u8 mFlags; // at 0x0 - u16 mFreeGroup; // at 0x2 - u16 mShadowIdx; // at 0x4 - ShadowTexture* mGroups[GROUP_MAX]; // at 0x8 + u8 mFlags; // at 0x0 + u16 mFreeGroup; // at 0x2 + u16 mShadowIdx; // at 0x4 + ShadowTexture *mGroups[GROUP_MAX]; // at 0x8 -public: - ShadowTextureManager(); - virtual ~ShadowTextureManager() {} // at 0x8 + public: + ShadowTextureManager(); + virtual ~ShadowTextureManager() {} // at 0x8 - void Reset(); - void Set(u16, ShadowTexture*); - u16 Append(ShadowTexture*); - void Calc(); - void Draw(Screen*); + void Reset(); + void Set(u16, ShadowTexture *); + u16 Append(ShadowTexture *); + void Calc(); + void Draw(Screen *); - bool IsActive() const { - return mFlags & SHADOW_MGR_ACTIVE; - } -}; -} // namespace EGG + bool IsActive() const { return mFlags & SHADOW_MGR_ACTIVE; } + }; +} #endif diff --git a/include/egg/gfx/eggStateGX.h b/include/egg/gfx/eggStateGX.h index d830497..0222ef6 100644 --- a/include/egg/gfx/eggStateGX.h +++ b/include/egg/gfx/eggStateGX.h @@ -1,143 +1,143 @@ #ifndef EGG_GFX_STATE_GX_H #define EGG_GFX_STATE_GX_H -#include "g3d_tmem.h" #include "types_egg.h" - +#include "g3d_tmem.h" #include #include -namespace EGG { -class StateGX { -public: - enum StateFlags { USE_TMEM = 0x10, VALID_CACHE = 0x20 }; - - enum CacheFlags { - PROJECTIONV_CACHED = 0x1, - VIEWPORT_CACHED = 0x2, - SCISSOR_CACHED = 0x4, - SCISSOR_BOX_CACHED = 0x8, - DITHER_CACHED = 0x10, - COLOR_UPDATE_CACHED = 0x20, - ALPHA_UPDATE_CACHED = 0x40, - }; - - struct CachedState { - u32 flags; // at 0x0 - int scissorOfsX; // at 0x4 - int scissorOfsY; // at 0x8 - bool colorUpdate; // at 0xC - bool alphaUpdate; // at 0xD - bool dither; // at 0xE - }; - - struct ScopedColor { - ScopedColor(bool x) { - old = sCache.colorUpdate; - GXSetColorUpdate_(x); - } - - ~ScopedColor() { - GXSetColorUpdate_(old); - } - - bool old; +namespace EGG +{ + class StateGX + { + public: + enum StateFlags + { + USE_TMEM = 0x10, + VALID_CACHE = 0x20 + }; + + enum CacheFlags + { + PROJECTIONV_CACHED = 0x1, + VIEWPORT_CACHED = 0x2, + SCISSOR_CACHED = 0x4, + SCISSOR_BOX_CACHED = 0x8, + DITHER_CACHED = 0x10, + COLOR_UPDATE_CACHED = 0x20, + ALPHA_UPDATE_CACHED = 0x40, + }; + + struct CachedState + { + u32 flags; // at 0x0 + int scissorOfsX; // at 0x4 + int scissorOfsY; // at 0x8 + bool colorUpdate; // at 0xC + bool alphaUpdate; // at 0xD + bool dither; // at 0xE + }; + + struct ScopedColorUpdate + { + ScopedColorUpdate(bool x) + { + old = sCache.colorUpdate; + GXSetColorUpdate_(x); + } + + ~ScopedColorUpdate() + { + GXSetColorUpdate_(old); + } + + bool old; + }; + + struct ScopedAlphaUpdate + { + ScopedAlphaUpdate(bool x) + { + old = sCache.alphaUpdate; + GXSetAlphaUpdate_(x); + } + + ~ScopedAlphaUpdate() + { + GXSetAlphaUpdate_(old); + } + + bool old; + }; + + struct ScopedDitherUpdate + { + ScopedDitherUpdate(bool x) + { + old = sCache.dither; + GXSetDither_(x); + } + + ~ScopedDitherUpdate() + { + GXSetDither_(old); + } + + bool old; + }; + + public: + static GXPixelFmt getDefaultPixelFormat() { return s_pixFormat; } + static UNKWORD getDefaultPixelFormatArg2() { return sDefaultPixelFormatArg2; } + static GXColor& getDefaultTexColor() { return sDefaultTexColor; } + static void setDefaultTexColor(GXColor c) { sDefaultTexColor = c; } + static u16 getEfbWidth() { return s_widthFb; } + static void setEfbWidth(u16 w) { s_widthFb = w; } + static u16 getEfbHeight() { return s_heightEfb; } + static void setEfbHeight(u16 h) { s_heightEfb = h; } + + static void initialize(); + static void frameInit(); + static void doResetStateCache(); + static void resetGX(); + static void resetVtx(); + static void resetColorChannel(); + static void resetIndirect(); + static void resetTexture(); + static void resetTexGen(); + static void resetTev(); + static void resetPE(); + static void resetStateCache(); + static void GXSetProjection_(Mtx44, int); + static void GXSetProjectionv_(const f32 *); + static void GXSetViewport_(f32, f32, f32, f32, f32, f32); + static void GXSetScissor_(u32, u32, u32, u32); + static void GXSetScissorBoxOffset_(int, int); + static void GXSetColorUpdate_(bool); + static void GXSetAlphaUpdate_(bool); + static void GXSetDither_(bool); + static void GXSetPixelFmt_(GXPixelFmt, UNKWORD); + + private: + static CachedState sCache; + static u8 sDefaultTexObjImage[4 * 4] __attribute__ ((aligned (32))); + + static const f32 lbl_80378C68[2][3]; + static const f32 lbl_80378C80[]; + + static u16 s_widthFb; + static u16 s_heightEfb; + static GXPixelFmt s_pixFormat; + static UNKWORD sDefaultPixelFormatArg2; + static GXPixelFmt s_pixFormatCurrent; + static UNKWORD sCurrentPixelFormatArg2; + static GXColor sDefaultTexColor; + + static u16 sStateFlags; + static f32 sModifyRatio; + static nw4r::g3d::tmem::TMemLayout sTMemLayout; + + static const GXColor cDefaultGXColor; }; - - struct ScopedAlpha { - ScopedAlpha(bool x) { - old = sCache.alphaUpdate; - GXSetAlphaUpdate_(x); - } - - ~ScopedAlpha() { - GXSetAlphaUpdate_(old); - } - - bool old; - }; - - struct ScopedDither { - ScopedDither(bool x) { - old = sCache.dither; - GXSetDither_(x); - } - - ~ScopedDither() { - GXSetDither_(old); - } - - bool old; - }; - -public: - static GXPixelFmt getDefaultPixelFormat() { - return s_pixFormat; - } - static UNKWORD getDefaultPixelFormatArg2() { - return sDefaultPixelFormatArg2; - } - static GXColor& getDefaultTexColor() { - return sDefaultTexColor; - } - static void setDefaultTexColor(GXColor c) { - sDefaultTexColor = c; - } - static u16 getEfbWidth() { - return s_widthFb; - } - static void setEfbWidth(u16 w) { - s_widthFb = w; - } - static u16 getEfbHeight() { - return s_heightEfb; - } - static void setEfbHeight(u16 h) { - s_heightEfb = h; - } - - static void initialize(); - static void frameInit(); - static void doResetStateCache(); - static void resetGX(); - static void resetVtx(); - static void resetColorChannel(); - static void resetIndirect(); - static void resetTexture(); - static void resetTexGen(); - static void resetTev(); - static void resetPE(); - static void resetStateCache(); - static void GXSetProjection_(Mtx44, int); - static void GXSetProjectionv_(const f32*); - static void GXSetViewport_(f32, f32, f32, f32, f32, f32); - static void GXSetScissor_(u32, u32, u32, u32); - static void GXSetScissorBoxOffset_(int, int); - static void GXSetColorUpdate_(bool); - static void GXSetAlphaUpdate_(bool); - static void GXSetDither_(bool); - static void GXSetPixelFmt_(GXPixelFmt, UNKWORD); - -private: - static CachedState sCache; - static u8 sDefaultTexObjImage[4 * 4] __attribute__((aligned(32))); - - static const f32 lbl_80378C68[2][3]; - static const f32 lbl_80378C80[]; - - static u16 s_widthFb; - static u16 s_heightEfb; - static GXPixelFmt s_pixFormat; - static UNKWORD sDefaultPixelFormatArg2; - static GXPixelFmt s_pixFormatCurrent; - static UNKWORD sCurrentPixelFormatArg2; - static GXColor sDefaultTexColor; - - static u16 sStateFlags; - static f32 sModifyRatio; - static nw4r::g3d::tmem::TMemLayout sTMemLayout; - - static const GXColor cDefaultGXColor; -}; -} // namespace EGG +} #endif diff --git a/include/egg/gfx/eggTextureBuffer.h b/include/egg/gfx/eggTextureBuffer.h index a88712b..247d30d 100644 --- a/include/egg/gfx/eggTextureBuffer.h +++ b/include/egg/gfx/eggTextureBuffer.h @@ -1,67 +1,72 @@ #ifndef EGG_GFX_TEXTURE_BUFFER_H #define EGG_GFX_TEXTURE_BUFFER_H -#include "eggCapTexture.h" #include "types_egg.h" - +#include "eggCapTexture.h" #include -namespace EGG { -class TextureBuffer : public CapTexture { -public: - enum EBufferState { STATE_FREE, STATE_ALLOCED }; +namespace EGG +{ + class TextureBuffer : public CapTexture + { + public: + enum EBufferState + { + STATE_FREE, + STATE_ALLOCED + }; - static void initialize(u32, Heap*); - static TextureBuffer* getNotJoin(); + static void initialize(u32, Heap *); + static TextureBuffer * getNotJoin(); - static TextureBuffer* alloc(u16 w, u16 h, GXTexFmt fmt) { - if (w == 0 || h == 0) - return NULL; + static TextureBuffer * alloc(u16 w, u16 h, GXTexFmt fmt) + { + if (w == 0 || h == 0) return NULL; - TextureBuffer* buf = getNotJoin(); - buf->setWidth(w); - buf->setHeight(h); - buf->setFormat(fmt); - buf->configure(); + TextureBuffer *buf = getNotJoin(); + buf->setWidth(w); + buf->setHeight(h); + buf->setFormat(fmt); + buf->configure(); - buf->setWrapS(0); - buf->setWrapT(0); - buf->setMinFilt(1); - buf->setMagFilt(1); + buf->setWrapS(0); + buf->setWrapT(0); + buf->setMinFilter(1); + buf->setMagFilter(1); - buf->alloc(buf->getTexBufferSize()); - return buf; - } + buf->alloc(buf->getTexBufferSize()); + return buf; + } - static void append(TextureBuffer* buf) { - if (spTailNotJoin != NULL) - spTailNotJoin->mpNext = buf; + static void append(TextureBuffer *buf) + { + if (spTailNotJoin != NULL) spTailNotJoin->mpNext = buf; - buf->mpPrev = spTailNotJoin; - buf->mpNext = NULL; + buf->mpPrev = spTailNotJoin; + buf->mpNext = NULL; - spTailNotJoin = buf; - } + spTailNotJoin = buf; + } - TextureBuffer(); - virtual ~TextureBuffer() {} // at 0x8 - virtual void configure(); // at 0xC + TextureBuffer(); + virtual ~TextureBuffer() {} // at 0x8 + virtual void configure(); // at 0xC - void alloc(u32); - void free(); + void alloc(u32); + void free(); -private: - u32 mSize; // at 0x2C - EBufferState mState; // at 0x30 - TextureBuffer* mpNext; // at 0x34 - TextureBuffer* mpPrev; // at 0x38 + private: + u32 mSize; // at 0x2C + EBufferState mState; // at 0x30 + TextureBuffer *mpNext; // at 0x34 + TextureBuffer *mpPrev; // at 0x38 - static const u32 NUM_BUFFERS = 64; - static TextureBuffer* spHead; - static TextureBuffer* spTailNotJoin; - static TextureBuffer* spBufferAll; - static u32 sBufferAllSize; - static TextureBuffer spBufferTable[NUM_BUFFERS]; -}; -} // namespace EGG + static const u32 NUM_BUFFERS = 64; + static TextureBuffer *spHead; + static TextureBuffer *spTailNotJoin; + static TextureBuffer *spBufferAll; + static u32 sBufferAllSize; + static TextureBuffer spBufferTable[NUM_BUFFERS]; + }; +} #endif diff --git a/include/egg/math.h b/include/egg/math.h index d35834d..d4f94de 100644 --- a/include/egg/math.h +++ b/include/egg/math.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #endif diff --git a/include/egg/math/eggMath.h b/include/egg/math/eggMath.h index 180a96f..2f3adbe 100644 --- a/include/egg/math/eggMath.h +++ b/include/egg/math/eggMath.h @@ -1,14 +1,54 @@ #ifndef EGG_MATH_MATH_H #define EGG_MATH_MATH_H -#include "types_egg.h" +#include + +#include namespace EGG { -template struct Math { - static T sqrt(T); - static T sin(T); - static T cos(T); - static T atan2(T, T); + +template class Math { +public: + static T sqrt(T t); + static T sin(T t); + static T cos(T t); + static T atan2(T ty, T tx); + + static T zero() { + return static_cast(0); + } + + static T pi() { + return static_cast(M_PI); + } + static T pi_half() { + return static_cast(M_PI / 2); + } + static T pi2() { + return static_cast(M_PI * 2); + } + + static T neg(T t) { + return -t; + } + static T inv(T t) { + return static_cast(1) / t; + } + static T square(T t) { + return t * t; + } + + static T abs(T t) { + return t > zero() ? t : neg(t); + } + + static T min(T t1, T t2) { + return t1 < t2 ? t1 : t2; + } + static T max(T t1, T t2) { + return t1 > t2 ? t1 : t2; + } }; + } // namespace EGG #endif diff --git a/include/egg/math/eggMatrix.h b/include/egg/math/eggMatrix.h index e67c9d7..fb0d8e2 100644 --- a/include/egg/math/eggMatrix.h +++ b/include/egg/math/eggMatrix.h @@ -1,40 +1,93 @@ #ifndef EGG_MATH_MATRIX_H #define EGG_MATH_MATRIX_H -#include "types_egg.h" +#include + +#include + +#include namespace EGG { -struct Matrix33f { - f32& operator()(int i, int j) { - return tbl[i][j]; - } - f32 tbl[3][3]; -}; +class Matrix33f : public nw4r::math::MTX33 {}; + +class Matrix34f : public nw4r::math::MTX34 { +public: + static Matrix34f ident; -struct Matrix34f { +public: Matrix34f() {} - Matrix34f(f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32); + + // clang-format off + Matrix34f(f32 m00, f32 m01, f32 m02, f32 m03, + f32 m10, f32 m11, f32 m12, f32 m13, + f32 m20, f32 m21, f32 m22, f32 m23); + // clang-format on void makeZero() { - tbl[0][3] = tbl[0][2] = tbl[0][1] = tbl[0][0] = 0.0f; - tbl[1][3] = tbl[1][2] = tbl[1][1] = tbl[1][0] = 0.0f; - tbl[2][3] = tbl[2][2] = tbl[2][1] = tbl[2][0] = 0.0f; + _03 = _02 = _01 = _00 = 0.0f; + _13 = _12 = _11 = _10 = 0.0f; + _23 = _22 = _21 = _20 = 0.0f; } - void makeIdentity(); - void makeQ(const Quatf&); - void makeS(const Vector3f&); - void setAxisRotation(const Vector3f&, f32); - void loadPosMtx(u32); + Matrix34f& operator=(const Matrix34f& rOther) { + copyFrom(rOther); + return *this; + } + + f32& operator()(int i) { + return a[i]; + } + const f32 operator()(int i) const { + return a[i]; + } f32& operator()(int i, int j) { - return tbl[i][j]; + return m[i][j]; + } + const f32 operator()(int i, int j) const { + return m[i][j]; } - f32 tbl[3][4]; + void copyFrom(const Matrix34f& rOther) { + for (int i = 0; i < 3 * 4; i++) { + (*this)(i) = rOther(i); + } + } - static Matrix34f ident; + void getBase(int index, Vector3f& rBase) const { + rBase.x = (*this)(0, index); + rBase.y = (*this)(1, index); + rBase.z = (*this)(2, index); + } + void setBase(int index, const Vector3f& rBase) { + (*this)(0, index) = rBase.x; + (*this)(1, index) = rBase.y; + (*this)(2, index) = rBase.z; + } + + void getTranslation(Vector3f& rTrans) const { + getBase(3, rTrans); + } + void setTranslation(const Vector3f& rTrans) { + setBase(3, rTrans); + } + + Vector3f rotate(const Vector3f& rVec) const { + f32 x = _00 * rVec.x + _01 * rVec.y + _02 * rVec.z; + f32 y = _10 * rVec.x + _11 * rVec.y + _12 * rVec.z; + f32 z = _20 * rVec.x + _21 * rVec.y + _22 * rVec.z; + return Vector3f(x, y, z); + } + + void makeIdentity(); + + void makeQ(const Quatf& rQuat); + void makeS(const Vector3f& rScale); + + void setAxisRotation(const Vector3f& rAxis, f32 angle); + void loadPosMtx(u32 id); }; + } // namespace EGG #endif diff --git a/include/egg/math/eggQuat.h b/include/egg/math/eggQuat.h index 9ca3ccd..62cb8d3 100644 --- a/include/egg/math/eggQuat.h +++ b/include/egg/math/eggQuat.h @@ -1,27 +1,30 @@ #ifndef EGG_MATH_QUAT_H #define EGG_MATH_QUAT_H -#include "types_egg.h" +#include -namespace EGG { - -// Forward declaration -class Vector3f; +#include -Quatf operator*(const Quatf& lhs, const Vector3f& rhs); -Quatf operator*(const Quatf& lhs, const Quatf& rhs); +namespace EGG { -struct Quatf { +class Quatf { +public: Quatf() {} + Quatf(f32 fw, Vector3f vxyz) : v(vxyz), w(fw) {} ~Quatf() {} - void setAxisRotation(const Vector3f&, f32); - Quatf conjugate() const; + void multScalar(f32 scale) { + v *= scale; + w *= scale; + } - Vector3f rotateVector(const Vector3f& v); - void slerpTo(const Quatf& q2, f32 t, Quatf& out) const; + void set(f32 fw, f32 fx, f32 fy, f32 fz); + void setAxisRotation(const Vector3f& rAxis, f32 angle); - f32 x, y, z, w; +public: + Vector3f v; // at 0x0 + f32 w; // at 0xC }; + } // namespace EGG #endif diff --git a/include/egg/math/eggRay.h b/include/egg/math/eggRay.h new file mode 100644 index 0000000..04ed41b --- /dev/null +++ b/include/egg/math/eggRay.h @@ -0,0 +1,22 @@ +#ifndef EGG_MATH_RAY_H +#define EGG_MATH_RAY_H +#include + +#include + +namespace EGG { + +class Ray3f { +public: + Ray3f() {} + Ray3f(const Vector3f& rDir, const Vector3f& rOrigin) + : dir(rDir), origin(rOrigin) {} + +public: + Vector3f dir; // at 0x0 + Vector3f origin; // at 0xC +}; + +} // namespace EGG + +#endif diff --git a/include/egg/math/eggVector.h b/include/egg/math/eggVector.h index 06b0514..0d5fc1e 100644 --- a/include/egg/math/eggVector.h +++ b/include/egg/math/eggVector.h @@ -1,58 +1,286 @@ #ifndef EGG_MATH_VECTOR_H #define EGG_MATH_VECTOR_H -#include "eggMath.h" -#include "math_types.h" -#include "types_egg.h" +#include + +#include + +#include + +#include namespace EGG { -struct Vector2f : nw4r::math::VEC2 { - Vector2f() {} - Vector2f(f32 _x, f32 _y) : VEC2(_x, _y) {} - ~Vector2f() {} +class Vector2f : public nw4r::math::VEC2 { +public: static const Vector2f zero; static const Vector2f ex; static const Vector2f ey; -}; -Vector3f operator+(const Vector3f& lhs, const Vector3f& rhs); -Vector3f operator-(const Vector3f& lhs, const Vector3f& rhs); -Vector3f operator*(const Vector3f& lhs, f32 scalar); -Vector3f operator/(const Vector3f& lhs, f32 scalar); +public: + Vector2f() {} + Vector2f(const nw4r::math::VEC2& rVec) : VEC2(rVec) {} + Vector2f(f32 fx, f32 fy) : VEC2(fx, fy) {} + ~Vector2f() {} -struct Vector3f : nw4r::math::VEC3 { - Vector3f() {} - Vector3f(f32 _x, f32 _y, f32 _z) : VEC3(_x, _y, _z) {} - ~Vector3f() {} + operator Vec*() { + return reinterpret_cast(this); + } + operator const Vec*() const { + return reinterpret_cast(this); + } + + f32& operator()(int i) { + return reinterpret_cast(&x)[i]; + } + const f32 operator()(int i) const { + return reinterpret_cast(&x)[i]; + } - void normalise(); - Vector3f cross(const Vector3f& other) const; + void set(f32 fx, f32 fy) { + x = fx; + y = fy; + } - f32 length() const { - return Math::sqrt(squaredLength()); + Vector2f& operator=(const Vector2f& rRhs) { + x = rRhs.x; + y = rRhs.y; + return *this; } - f32 squaredLength() const { - return x * x + y * y + z * z; + Vector2f operator-() const { + return Vector2f(-x, -y); + } + + Vector2f operator+(const Vector2f& rRhs) const { + return Vector2f(x + rRhs.x, y + rRhs.y); + } + Vector2f operator-(const Vector2f& rRhs) const { + return Vector2f(x - rRhs.x, y - rRhs.y); } - f32 dot(const Vector3f& rhs) const { - return x * rhs.x + y * rhs.y + z * rhs.z; + Vector2f operator*(f32 scale) const { + return Vector2f(x * scale, y * scale); + } + Vector2f operator/(f32 scale) const { + f32 inv = 1 / scale; + return Vector2f(x * inv, y * inv); } - f32 distance(const Vector3f& other) const { - Vector3f delta = other - *this; - return delta.length(); + friend Vector2f operator*(f32 f, const Vector2f& rVec) { + return Vector2f(rVec.x * f, rVec.y * f); } - f32& operator()(int i) { - return reinterpret_cast(this)[i]; + Vector2f& operator+=(const Vector2f& rRhs) { + x += rRhs.x; + y += rRhs.y; + return *this; + } + Vector2f& operator-=(const Vector2f& rRhs) { + x -= rRhs.x; + y -= rRhs.y; + return *this; + } + + Vector2f& operator*=(f32 scale) { + x *= scale; + y *= scale; + return *this; + } + Vector2f& operator/=(f32 scale) { + f32 inv = 1 / scale; + x *= inv; + y *= inv; + return *this; + } + + bool operator==(const Vector2f& rRhs) const { + return x == rRhs.x && y == rRhs.y; + } + bool operator!=(const Vector2f& rRhs) const { + return x != rRhs.x || y != rRhs.y; + } + + void vtx() const { + GXPosition3f32(x, y, 0.0f); + } + void tex() const { + GXTexCoord2f32(x, y); + } + + void multScalar(f32 scale) { + x *= scale; + y *= scale; + } + void divScalar(f32 scale) { + f32 inv = 1 / scale; + x *= inv; + y *= inv; } + f32 squaredLength() const { + return x * x + y * y; + } + f32 length() const { + return Math::sqrt(squaredLength()); + } + + f32 dot(const Vector2f& rOther) const { + return x * rOther.x + y * rOther.y; + } + f32 distance(const Vector2f& rOther) const { + f32 fx = rOther.x - x * rOther.x - x; + f32 fy = rOther.y - y * rOther.y - y; + return Math::sqrt(fx + fy); + } +}; + +class Vector3f : public nw4r::math::VEC3 { +public: static const Vector3f zero; static const Vector3f ex; static const Vector3f ey; static const Vector3f ez; + +public: + Vector3f() {} + Vector3f(const nw4r::math::VEC3& rVec) : VEC3(rVec) {} + Vector3f(f32 fx, f32 fy, f32 fz) : VEC3(fx, fy, fz) {} + ~Vector3f() {} + + operator Vec*() { + return reinterpret_cast(this); + } + operator const Vec*() const { + return reinterpret_cast(this); + } + + f32& operator()(int i) { + return reinterpret_cast(&x)[i]; + } + const f32 operator()(int i) const { + return reinterpret_cast(&x)[i]; + } + + void set(f32 fx, f32 fy, f32 fz) { + x = fx; + y = fy; + z = fz; + } + + Vector3f& operator=(const Vector3f& rRhs) { + x = rRhs.x; + y = rRhs.y; + z = rRhs.z; + return *this; + } + + Vector3f operator-() const { + return Vector3f(-x, -y, -z); + } + + Vector3f operator+(const Vector3f& rRhs) const { + return Vector3f(x + rRhs.x, y + rRhs.y, z + rRhs.z); + } + Vector3f operator-(const Vector3f& rRhs) const { + return Vector3f(x - rRhs.x, y - rRhs.y, z - rRhs.z); + } + + Vector3f operator*(f32 scale) const { + return Vector3f(x * scale, y * scale, z * scale); + } + Vector3f operator/(f32 scale) const { + f32 inv = 1 / scale; + return Vector3f(x * inv, y * inv, z * inv); + } + + friend Vector3f operator*(f32 f, const Vector3f& rVec) { + return Vector3f(rVec.x * f, rVec.y * f, rVec.z * f); + } + + Vector3f& operator+=(const Vector3f& rRhs) { + x += rRhs.x; + y += rRhs.y; + z += rRhs.z; + return *this; + } + Vector3f& operator-=(const Vector3f& rRhs) { + x -= rRhs.x; + y -= rRhs.y; + z -= rRhs.z; + return *this; + } + + Vector3f& operator*=(f32 scale) { + x *= scale; + y *= scale; + z *= scale; + return *this; + } + Vector3f& operator/=(f32 scale) { + f32 inv = 1 / scale; + x *= inv; + y *= inv; + z *= inv; + return *this; + } + + bool operator==(const Vector3f& rRhs) const { + return x == rRhs.x && y == rRhs.y && z == rRhs.z; + } + bool operator!=(const Vector3f& rRhs) const { + return x != rRhs.x || y != rRhs.y && z != rRhs.z; + } + + void vtx() const { + GXPosition3f32(x, y, z); + } + void nrm() const { + GXNormal3f32(x, y, z); + } + + void multScalar(f32 scale) { + x *= scale; + y *= scale; + z *= scale; + } + void divScalar(f32 scale) { + f32 inv = 1 / scale; + x *= inv; + y *= inv; + z *= inv; + } + + f32 squaredLength() const { + return x * x + y * y + z * z; + } + f32 length() const { + return Math::sqrt(squaredLength()); + } + + f32 dot(const Vector3f& rOther) const { + return x * rOther.x + y * rOther.y + z * rOther.z; + } + Vector3f cross(const Vector3f& rOther) const { + f32 fx = y * rOther.z - z * rOther.y; + f32 fy = z * rOther.x - x * rOther.z; + f32 fz = x * rOther.y - y * rOther.x; + return Vector3f(fx, fy, fz); + } + f32 distance(const Vector3f& rOther) const { + f32 fx = rOther.x - x * rOther.x - x; + f32 fy = rOther.y - y * rOther.y - y; + f32 fz = rOther.z - z * rOther.z - z; + return Math::sqrt(fx + fy + fz); + } + + f32 normalise(); + f32 normalize() { + return normalise(); + } + + bool isZero(f32 threshold) const { + return length() <= threshold; + } }; } // namespace EGG diff --git a/include/egg/prim.h b/include/egg/prim.h index ef27d84..8c749dc 100644 --- a/include/egg/prim.h +++ b/include/egg/prim.h @@ -2,5 +2,7 @@ #define EGG_PUBLIC_PRIM_H #include +#include +#include #endif diff --git a/include/egg/prim/eggAssert.h b/include/egg/prim/eggAssert.h index 61b44a3..1adc033 100644 --- a/include/egg/prim/eggAssert.h +++ b/include/egg/prim/eggAssert.h @@ -5,17 +5,19 @@ #define EGG_ASSERT(EXP) \ if (!(EXP)) \ system_halt(__FILE__, __LINE__, #EXP) + #define EGG_ASSERT_MSG(EXP, ...) \ if (!(EXP)) \ system_halt(__FILE__, __LINE__, __VA_ARGS__) + #define EGG_PRINT(...) system_print(true, __FILE__, __VA_ARGS__) #ifdef __cplusplus extern "C" { #endif -void system_halt(char* file, int line, char* msg, ...); -void system_print(bool bVisible, char* file, char* msg, ...); +void system_halt(char* pFile, int line, char* pMsg, ...); +void system_print(bool visible, char* pFile, char* pMsg, ...); #ifdef __cplusplus } diff --git a/include/egg/prim/eggBuffer.h b/include/egg/prim/eggBuffer.h new file mode 100644 index 0000000..4e82779 --- /dev/null +++ b/include/egg/prim/eggBuffer.h @@ -0,0 +1,141 @@ +#ifndef EGG_PRIM_BUFFER_H +#define EGG_PRIM_BUFFER_H +#include + +#include +#include + +namespace EGG { + +template class TBuffer { +public: + class iterator { + public: + iterator(TBuffer* pBuffer, int index) + : mBuffer(pBuffer), mIndex(index) {} + + int get_index() const { + return mIndex; + } + + iterator& operator++() { + mIndex++; + return *this; + } + + T& operator*() { + return (*mBuffer)(mIndex); + } + + friend bool operator==(const iterator& rLhs, const iterator& rRhs) { + return rLhs.mBuffer == rRhs.mBuffer && rLhs.mIndex == rRhs.mIndex; + } + friend bool operator!=(const iterator& rLhs, const iterator& rRhs) { + return !(rLhs == rRhs); + } + + private: + TBuffer* mBuffer; // at 0x0 + int mIndex; // at 0x4 + }; + +public: + TBuffer() : mSize(0), mBuffer(NULL) {} + + virtual ~TBuffer() { + if (mBuffer == NULL) { + return; + } + + delete[] mBuffer; + mBuffer = NULL; + } // at 0x8 + + virtual void allocate(int size, int align = 0) { + mSize = size; + + if (align != 0) { + mBuffer = new T[mSize]; + } else { + mBuffer = new T[mSize]; + } + + flush(); + onAllocate(NULL); + } // at 0xC + + virtual void allocate(int size, Heap* pHeap, int align = 0) { + mSize = size; + + if (pHeap == NULL) { + pHeap = Heap::getCurrentHeap(); + } + + if (align != 0) { + mBuffer = new (pHeap) T[mSize]; + } else { + mBuffer = new (pHeap) T[mSize]; + } + + flush(); + onAllocate(pHeap); + } // at 0x10 + + virtual void onAllocate(Heap* /* pHeap */) {} // at 0x14 + virtual void errRangeOver() const {} // at 0x18 + + T& operator()(int i) { + checkRange(i); + return mBuffer[i]; + } + const T& operator()(int i) const { + checkRange(i); + return mBuffer[i]; + } + + T& get(int i) { + checkRange(i); + return mBuffer[i]; + } + const T& get(int i) const { + checkRange(i); + return mBuffer[i]; + } + + int getSize() const { + return mSize; + } + int size() const { + return mSize; + } + + iterator begin() { + return iterator(this, 0); + } + iterator end() { + return iterator(this, getSize()); + } + +private: + void flush() {} + + void checkRange(int i) const { + if (!isRangeValid(i)) { + errRangeOver(); +#line 174 + EGG_ASSERT_MSG(false, "TBuffer::checkRange %d (0<=x<%d)\n", i, mSize); + } + } + + bool isRangeValid(int i) const { + return i >= 0 && i < mSize; + } + +private: + int mSize; // at 0x4 + T* mBuffer; // at 0x8 +}; + +} // namespace EGG + +#endif diff --git a/include/egg/prim/eggNw4rList.h b/include/egg/prim/eggNw4rList.h new file mode 100644 index 0000000..32b3f5b --- /dev/null +++ b/include/egg/prim/eggNw4rList.h @@ -0,0 +1,42 @@ +#ifndef EGG_PRIM_NW4R_LIST_H +#define EGG_PRIM_NW4R_LIST_H +#include + +#include + +namespace EGG { + +template class TNw4rList { +public: + TNw4rList() { + nw4r::ut::List_Init(&mList, T::getLinkOffset()); + } + + void append(T* pObject) { + nw4r::ut::List_Append(&mList, pObject); + } + void remove(T* pObject) { + nw4r::ut::List_Remove(&mList, pObject); + } + + T* getNext(T* pObject) { + return static_cast(nw4r::ut::List_GetNext(&mList, pObject)); + } + +private: + nw4r::ut::List mList; // at 0x0 +}; + +} // namespace EGG + +/** + * List for-each macro. + * + * @param TYPE Element type + * @param NAME Element name + * @param LIST Reference to list + */ +#define EGG_NW4R_LIST_FOREACH(TYPE, NAME, LIST) \ + for (TYPE* NAME = NULL; (NAME = (LIST).getNext(NAME)) != NULL;) + +#endif diff --git a/include/egg/types_egg.h b/include/egg/types_egg.h index 6d6df7d..6831bdf 100644 --- a/include/egg/types_egg.h +++ b/include/egg/types_egg.h @@ -1,95 +1,92 @@ -#ifndef TYPES_EGG_H -#define TYPES_EGG_H +#ifndef EGG_TYPES_H +#define EGG_TYPES_H #include -namespace EGG { -// gfx -struct CapTexture; -struct CpuTexture; -struct DrawGX; -struct DrawPathBase; -struct DrawPathBloom; -struct DrawPathDOF; -struct DrawPathHDR; -struct DrawPathLightMap; -struct DrawPathShadowVolume; -struct Fog; -struct FogManager; -struct G3DUtility; -struct GfxEngine; -struct GXUtility; -struct IDrawGX; -struct IScnProc; -struct IScnProcModel; -struct LightObj; -struct LightManager; -struct LightTexture; -struct LightTextureManager; -struct ModelBoundingInfo; -struct ModelEx; -struct ModelSnapshot; -struct PostEffectBase; -struct PostEffectBlur; -struct PostEffectBlurGather; -struct PostEffectHDR; -struct PostEffectSimple; -struct ResTIMG; -struct ScnRenderer; -struct ScnRootEx; -struct Screen; -struct ScreenEffectBase; -struct ShadowTextureManager; -struct ShadowTexture; -struct StateGX; -struct StateGX; -struct TextureBuffer; +namespace EGG +{ + // gfx + struct CapTexture; + struct CpuTexture; + struct DrawGX; + struct DrawPathBase; + struct DrawPathBloom; + struct DrawPathDOF; + struct DrawPathHDR; + struct DrawPathLightMap; + struct DrawPathShadowVolume; + struct Fog; + struct FogManager; + struct G3DUtility; + struct GfxEngine; + struct GXUtility; + struct IDrawGX; + struct IScnProc; + struct IScnProcModel; + struct LightObj; + struct LightManager; + struct LightTexture; + struct LightTextureManager; + struct ModelBoundingInfo; + struct ModelEx; + struct ModelSnapshot; + struct PostEffectBase; + struct PostEffectBlur; + struct PostEffectBlurGather; + struct PostEffectHDR; + struct PostEffectSimple; + struct ResTIMG; + struct ScnRenderer; + struct ScnRootEx; + struct Screen; + struct ScreenEffectBase; + struct ShadowTextureManager; + struct ShadowTexture; + struct StateGX; + struct StateGX; + struct TextureBuffer; -// math -template struct Math; -struct Matrix33f; -struct Matrix34f; -struct Matrix44f; -struct Quatf; -struct Vector2f; -struct Vector3f; + // math + template struct Math; + struct Matrix33f; + struct Matrix34f; + struct Matrix44f; + struct Quatf; + struct Vector2f; + struct Vector3f; -// core -struct Allocator; -struct Archive; -struct AsyncDisplay; -template struct IBinary; -template struct TBitFlag; -struct CntFile; -struct ColorFader; -struct Decomp; -struct Display; -struct Disposer; -struct DvdFile; -struct DvdRipper; -struct ExpHeap; -struct Fader; -struct FrmHeap; -struct Heap; -struct PerformanceView; -struct ProcessMeter; -struct Scene; -struct SceneManager; -struct Stream; -struct RamStream; -struct Thread; -struct Video; -struct Xfb; -struct XfbManager; + // core + struct Allocator; + struct Archive; + struct AsyncDisplay; + template struct IBinary; + template struct TBitFlag; + struct CntFile; + struct ColorFader; + struct Decomp; + struct Display; + struct Disposer; + struct DvdFile; + struct DvdRipper; + struct ExpHeap; + struct Fader; + struct FrmHeap; + struct Heap; + struct Scene; + struct SceneManager; + struct Thread; + struct Video; + struct Xfb; + struct XfbManager; -// audio -struct ArcPlayer; -struct IAudioMgr; -struct SimpleAudioMgr; -struct SoundHeapMgr; + // audio + struct ArcPlayer; + struct IAudioMgr; + struct SimpleAudioMgr; + struct SoundHeapMgr; -// util -struct Exception; -struct MsgRes; -} // namespace EGG + // util + struct Exception; + struct MsgRes; +} #endif diff --git a/include/egg/util.h b/include/egg/util.h new file mode 100644 index 0000000..e958372 --- /dev/null +++ b/include/egg/util.h @@ -0,0 +1,7 @@ +#ifndef EGG_PUBLIC_UTIL_H +#define EGG_PUBLIC_UTIL_H + +#include +#include + +#endif diff --git a/include/egg/util/eggEffect.h b/include/egg/util/eggEffect.h deleted file mode 100644 index 60eea20..0000000 --- a/include/egg/util/eggEffect.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef EGG_UTIL_EFFECT_H -#define EGG_UTIL_EFFECT_H -#include "ef_handle.h" -#include "math_types.h" -#include "types_egg.h" - -namespace EGG { -static const nw4r::ef::HandleBase cInvalidHandle; -} - -#endif diff --git a/include/egg/util/eggException.h b/include/egg/util/eggException.h index 99413c0..e09177e 100644 --- a/include/egg/util/eggException.h +++ b/include/egg/util/eggException.h @@ -1,16 +1,15 @@ #ifndef EGG_UTIL_EXCEPTION_H #define EGG_UTIL_EXCEPTION_H -#include "types_egg.h" - -#include +#include namespace EGG { -struct Exception { - typedef void (*UserCallback)(KPADStatus*); - static Exception* create(u16, u16, u16, Heap*); - static UNKTYPE setUserCallBack(UserCallback); +class Exception { +public: + static Exception* create(u16 width, u16 height, u16 attr, Heap* pHeap); + static void setPadInfo(const u16* pPadInfo); }; + } // namespace EGG #endif diff --git a/include/egg/util/eggMsgRes.h b/include/egg/util/eggMsgRes.h index 52e1870..076fd63 100644 --- a/include/egg/util/eggMsgRes.h +++ b/include/egg/util/eggMsgRes.h @@ -1,139 +1,136 @@ -#ifndef EGG_UTIL_MSGRES_H -#define EGG_UTIL_MSGRES_H -#include "eggAssert.h" -#include "types_egg.h" +#ifndef EGG_UTIL_MSG_RES_H +#define EGG_UTIL_MSG_RES_H +#include + +#include namespace EGG { -// Escape sequence (Official name = "Tag") -const char cTagMark = 0x1A; -const u32 cMsgSectionMagic[] = {'INF1', 'DAT1', 'STR1', 'MID1', 'FLW1', 'FLI1'}; -const u32 cShifts[] = {0x00000020, 0x00000018, 0x00000010, - 0x00000008, 0x00000000, 0x00000000}; - -struct MaskUnk { - u32 INT_0x0; - u32 INT_0x4; -}; -const MaskUnk cMasks[] = {{0xffffffff, 0x00000000}, - {0xffffff00, 0x000000ff}, - {0xffff0000, 0x0000ffff}, - {0xff000000, 0x00ffffff}, - {0x00000000, 0xffffffff}}; - -struct MsgRes { - struct MsgHeaderBlock { - u32 mMagicTop; // "MESG", at 0x0 - u32 mMagicBot; // "bmg1", at 0x4 + +class MsgRes { +public: + struct DataBlockHeader { + u32 mSignature; // at 0x0 + u32 mType; // at 0x4 u32 mDataSize; // at 0x8 u32 mNumBlocks; // at 0xC - u8 mEncoding; // at 0x10 - u8 UNK_0x11[3]; - UNKWORD WORD_0x14; - UNKWORD WORD_0x18; - UNKWORD WORD_0x1C; }; - struct MsgInfoBlockEntry { - u32 mDataBlkOfs; // at 0x0 - u32 mAttrib; // at 0x4 + struct DataBlock { + u32 mKind; // at 0x0 + u32 mDataSize; // at 0x4 }; - struct MsgInfoBlock { - u32 mMagic; // at 0x0 - u32 mDataSize; // at 0x4 - u16 mNumEntries; // at 0x8 - u16 mItemSize; // at 0xA - u16 SHORT_0xC; - u8 UNK_0xE; - u8 UNK_0xF; - MsgInfoBlockEntry mMsgInfo[]; // at 0x10 + struct MessageHeader : DataBlockHeader { + enum EEncoding { + ENCODING_NONE, + ENCODING_1BYTE, + ENCODING_2BYTE, + ENCODING_SJIS, + ENCODING_UTF8, + }; + + u8 mEncoding; // at 0x10 + char UNK_0x11[0x20 - 0x11]; }; - struct MsgDataBlock { - u32 mMagic; // at 0x0 - u32 mDataSize; // at 0x4 - wchar_t mStringPool[]; // at 0x8 - }; + struct MessageInfoDataBlock : DataBlock { + struct Entry { + u32 mDataOffset; // at 0x0 + u32 mAttribute; // at 0x4 + }; - struct MsgStrAttrBlock { - u32 mMagic; // at 0x0 - u32 mDataSize; // at 0x4 - // TO-DO + u16 mNumEntries; // at 0x8 + u16 mEntrySize; // at 0xA + u16 mGroupID; // at 0xC + Entry mContent[1]; // at 0x10 }; - struct MsgIdBlock { - u32 mMagic; // at 0x0 - u32 mDataSize; // at 0x4 - u16 mNumEntries; // at 0x8 - u8 UNK_0xA; - u8 UNK_0xB; - u32 WORD_0xC; - u32 mMsgIds[]; // at 0x10 + struct MessageDataBlock : DataBlock { + wchar_t mContent[1]; // at 0x8 }; - struct MsgFlowChartBlock { - u32 mMagic; // at 0x0 - u32 mDataSize; // at 0x4 - // TO-DO - }; + struct StringAttributeDataBlock : DataBlock {}; - struct MsgFlowLabelBlock { - u32 mMagic; // at 0x0 - u32 mDataSize; // at 0x4 - // TO-DO + struct MessageIDDataBlock : DataBlock { + u16 mNumEntries; // at 0x8 + u8 mForm; // at 0xA + u8 mFormSupplement; // at 0xB + char UNK_0xC[0x10 - 0xC]; + u32 mContent[]; // at 0x10 }; + struct FlowChartInfoDataBlock : DataBlock {}; + + struct FlowLabelInfoDataBlock : DataBlock {}; + +protected: enum EDataBlkKind { - BLOCK_MSGINFO, /* INF1 */ - BLOCK_MSGDATA, /* DAT1 */ - BLOCK_STRATTR, /* STR1 */ - BLOCK_MSGID, /* MID1 */ - BLOCK_FLOWCHART, /* FLW1 */ - BLOCK_FLOWLABEL, /* FLI1 */ - BLOCK_ILLEGAL + DATABLK_MSGINFO, + DATABLK_MSGDATA, + DATABLK_STRATTR, + DATABLK_MSGID, + DATABLK_FLOWCHART, + DATABLK_FLOWLABEL, + DATABLK_MAX }; - MsgHeaderBlock* mMsgHeader; // "MESGbmg1", at 0x0 - MsgInfoBlock* mMsgInfoDataBlk; // "INF1", at 0x4 - MsgDataBlock* mMsgDataBlk; // "DAT1", at 0x8 - MsgStrAttrBlock* mMsgStrDataBlk; // "STR1", at 0xC - MsgIdBlock* mMsgIDDataBlk; // "MID1", at 0x10 - MsgFlowChartBlock* mMsgFlowChartBlk; // "FLW1", at 0x14 - MsgFlowLabelBlock* mMsgFlowLabelBlk; // "FLI1", at 0x18 + static const u16 cTagMark = '\x1A'; + static const u32 cDataBlkKindCodeSet[DATABLK_MAX]; - // Unofficial symbol - inline u32 getBlkSize(const void* dataBlkHeader) { -#line 260 - EGG_ASSERT(dataBlkHeader); - // Any block cast will do (except MsgHeaderBlock), - // as they all have mDataSize at 0x4. - return ((MsgInfoBlock*)dataBlkHeader)->mDataSize; - } + static const u32 cFormSupplementMax = 5; + struct MsgIDMask { + u32 groupMask; // at 0x0 + u32 indexMask; // at 0x4 + }; + static const u32 cMainMsgIdBitNumSet[cFormSupplementMax]; + static const MsgIDMask cMsgIdMaskSet[cFormSupplementMax]; + +private: + const MessageHeader* mMsgHeader; // at 0x0 + const MessageInfoDataBlock* mMsgInfoDataBlk; // at 0x4 + const MessageDataBlock* mMsgDataBlk; // at 0x8 + const StringAttributeDataBlock* mMsgStrDataBlk; // at 0xC + const MessageIDDataBlock* mMsgIDDataBlk; // at 0x10 + const FlowChartInfoDataBlock* mMsgFlowChartBlk; // at 0x14 + const FlowLabelInfoDataBlock* mMsgFlowLabelBlk; // at 0x18 + +public: + MsgRes(const void* pData); + virtual ~MsgRes(); // at 0x8 + + const wchar_t* getMsg(u32 group, u32 idx); + + static void analyzeTag(u16 code, const wchar_t* pTag, u8* pTagLength, + u32* pTagID, void** ppParam); + +protected: + const MessageInfoDataBlock::Entry* getMsgEntry(u32 group, u32 idx); + u32 getMsgID(u16 idx); - // Unofficial symbol - inline u32 getDataBlkKind(const void* data) { +private: + u32 getDataBlkKind(const void* data) { #line 271 EGG_ASSERT(data); - // Any block cast will do, as they all have mMagic at 0x0. - return ((MsgInfoBlock*)data)->mMagic; + return static_cast(data)->mKind; } - MsgRes(const void*); - virtual ~MsgRes(); - static void analyzeTag(u16, const wchar_t*, u8*, unsigned int*, void**); - const wchar_t* getMsg(unsigned int, unsigned int); - MsgInfoBlockEntry* getMsgEntry(unsigned int, unsigned int) - __attribute__((never_inline)); - u32 getMsgID(u16); // inlined - EDataBlkKind analyzeDataBlkKind(unsigned int); // inlined - const void* extractMsgHeader(const void*); // inlined - const void* extractMsgInfoDataBlk(const void*); // inlined - const void* extractMsgDataBlk(const void*); // inlined - const void* extractStrAttrDataBlk(const void*); // inlined - const void* extractMsgIDDataBlk(const void*); // inlined - const void* extractFlowChartInfoDataBlk(const void*); // inlined - const void* extractFlowLabelInfoDataBlk(const void*); // inlined + u32 getDataBlkSize(const void* dataBlkHeader) { +#line 260 + EGG_ASSERT(dataBlkHeader); + return static_cast(dataBlkHeader)->mDataSize; + } + + void extractMsgHeader(const void* pData); + void extractMsgInfoDataBlk(const void* pData); + void extractMsgDataBlk(const void* pData); + void extractStrAttrDataBlk(const void* pData); + void extractMsgIDDataBlk(const void* pData); + void extractFlowChartInfoDataBlk(const void* pData); + void extractFlowLabelInfoDataBlk(const void* pData); + + EDataBlkKind analyzeDataBlkKind(u32 kind); }; + } // namespace EGG #endif diff --git a/include/lang.h b/include/lang.h new file mode 100644 index 0000000..499fc43 --- /dev/null +++ b/include/lang.h @@ -0,0 +1,13 @@ +/** + * Compatability macros for deprecated/future C++ features + */ + +#ifndef LANG_H +#define LANG_H + +#if __cplusplus >= 199711L +#define noexcept throw() +#define override +#endif + +#endif diff --git a/include/macros.h b/include/macros.h index 2c988d8..abed139 100644 --- a/include/macros.h +++ b/include/macros.h @@ -15,6 +15,7 @@ #define ROUND_DOWN_PTR(x, align) ((void*)(((u32)(x)) & (~((align) - 1)))) #define LENGTHOF(x) (sizeof((x)) / sizeof((x)[0])) +#define ARRAY_SIZE(x) LENGTHOF(x) #define MEMCLR(x) __memclr((x), sizeof(*(x))) diff --git a/include/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.h b/include/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.h index 040ea41..735df91 100644 --- a/include/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.h +++ b/include/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.h @@ -1,18 +1,21 @@ #ifndef NW4R_EF_DRAW_BILLBOARD_STRATEGY_H #define NW4R_EF_DRAW_BILLBOARD_STRATEGY_H -#include "ef_drawstrategyimpl.h" #include "types_nw4r.h" +#include "ef_drawstrategyimpl.h" -namespace nw4r { -namespace ef { -class DrawBillboardStrategy : public DrawStrategyImpl { -public: - DrawBillboardStrategy(); - virtual UNKTYPE GetCalcAheadFunc(ParticleManager*); // at 0x18 - - virtual void Draw(const DrawInfo&, ParticleManager*); -}; -} // namespace ef -} // namespace nw4r +namespace nw4r +{ + namespace ef + { + class DrawBillboardStrategy : public DrawStrategyImpl + { + public: + DrawBillboardStrategy(); + virtual UNKTYPE GetCalcAheadFunc(ParticleManager *); // at 0x18 + + virtual void Draw(const DrawInfo &, ParticleManager *); + }; + } +} #endif diff --git a/include/nw4r/ef/drawstrategy/ef_drawdirectionalstrategy.h b/include/nw4r/ef/drawstrategy/ef_drawdirectionalstrategy.h index 7f841f1..6d1dba6 100644 --- a/include/nw4r/ef/drawstrategy/ef_drawdirectionalstrategy.h +++ b/include/nw4r/ef/drawstrategy/ef_drawdirectionalstrategy.h @@ -1,18 +1,21 @@ #ifndef NW4R_EF_DRAW_DIRECTIONAL_STRATEGY_H #define NW4R_EF_DRAW_DIRECTIONAL_STRATEGY_H -#include "ef_drawstrategyimpl.h" #include "types_nw4r.h" +#include "ef_drawstrategyimpl.h" -namespace nw4r { -namespace ef { -class DrawDirectionalStrategy : public DrawStrategyImpl { -public: - DrawDirectionalStrategy(); - virtual UNKTYPE GetCalcAheadFunc(ParticleManager*); // at 0x18 - - virtual void Draw(const DrawInfo&, ParticleManager*); -}; -} // namespace ef -} // namespace nw4r +namespace nw4r +{ + namespace ef + { + class DrawDirectionalStrategy : public DrawStrategyImpl + { + public: + DrawDirectionalStrategy(); + virtual UNKTYPE GetCalcAheadFunc(ParticleManager *); // at 0x18 + + virtual void Draw(const DrawInfo &, ParticleManager *); + }; + } +} #endif diff --git a/include/nw4r/ef/drawstrategy/ef_drawstripestrategy.h b/include/nw4r/ef/drawstrategy/ef_drawstripestrategy.h index 00c2598..cb7a093 100644 --- a/include/nw4r/ef/drawstrategy/ef_drawstripestrategy.h +++ b/include/nw4r/ef/drawstrategy/ef_drawstripestrategy.h @@ -1,18 +1,21 @@ #ifndef NW4R_EF_DRAW_STRIPE_STRATEGY_H #define NW4R_EF_DRAW_STRIPE_STRATEGY_H -#include "ef_drawstrategyimpl.h" #include "types_nw4r.h" +#include "ef_drawstrategyimpl.h" -namespace nw4r { -namespace ef { -class DrawStripeStrategy : public DrawStrategyImpl { -public: - DrawStripeStrategy(); - virtual UNKTYPE GetCalcAheadFunc(ParticleManager*); // at 0x18 - - virtual UNKTYPE Draw(const DrawInfo&, ParticleManager*); -}; -} // namespace ef -} // namespace nw4r +namespace nw4r +{ + namespace ef + { + class DrawStripeStrategy : public DrawStrategyImpl + { + public: + DrawStripeStrategy(); + virtual UNKTYPE GetCalcAheadFunc(ParticleManager *); // at 0x18 + + virtual UNKTYPE Draw(const DrawInfo &, ParticleManager *); + }; + } +} #endif diff --git a/include/nw4r/ef/ef_effect.h b/include/nw4r/ef/ef_effect.h index d30bad6..ca461e2 100644 --- a/include/nw4r/ef/ef_effect.h +++ b/include/nw4r/ef/ef_effect.h @@ -115,6 +115,13 @@ class Effect : public ReferencedObject { reinterpret_cast(&rColor), ignoreLifeStatus); } + void Modifier_SetSimpleLightDiffuse(const GXColor& rColor, + bool ignoreLifeStatus) { + ForeachParticleManager( + ParticleManager::ModifierTravFunc_SetSimpleLightDiffuse, + reinterpret_cast(&rColor), ignoreLifeStatus); + } + // @bug Surely meant to be a const reference... void Modifier_SetScale(math::VEC2& rScale, bool ignoreLifeStatus) { ForeachParticleManager(ParticleManager::ModifierTravFunc_SetScale, diff --git a/include/nw4r/ef/ef_handle.h b/include/nw4r/ef/ef_handle.h index 08c8dc1..9e6b231 100644 --- a/include/nw4r/ef/ef_handle.h +++ b/include/nw4r/ef/ef_handle.h @@ -7,6 +7,9 @@ namespace nw4r { namespace ef { +// Forward declarations +class Effect; + class HandleBase { private: u32 mObjectID; // at 0x0 @@ -26,11 +29,13 @@ class HandleBase { template class Handle : public HandleBase { public: + Handle() {} Handle(const Handle& rOther) : HandleBase(rOther) {} Handle(T* pObject) : HandleBase(static_cast(pObject)) {} Handle& operator=(T* pObject) { *this = static_cast(pObject); + return *this; } bool IsAlive() const { @@ -55,6 +60,8 @@ template class Handle : public HandleBase { } }; +typedef nw4r::ef::Handle EffectHandle; + } // namespace ef } // namespace nw4r diff --git a/include/nw4r/ef/ef_particlemanager.h b/include/nw4r/ef/ef_particlemanager.h index 91da4cb..a16c619 100644 --- a/include/nw4r/ef/ef_particlemanager.h +++ b/include/nw4r/ef/ef_particlemanager.h @@ -162,6 +162,13 @@ class ParticleManager : public ReferencedObject { *reinterpret_cast(param); } + static void ModifierTravFunc_SetSimpleLightDiffuse(void* pObject, + ForEachParam param) { + + static_cast(pObject)->mModifier.mLight.mDiffuse = + *reinterpret_cast(param); + } + static void ModifierTravFunc_SetScale(void* pObject, ForEachParam param) { static_cast(pObject)->mModifier.mScale = *reinterpret_cast(param); diff --git a/include/nw4r/g3d/g3d_scnproc.h b/include/nw4r/g3d/g3d_scnproc.h index 99447cc..469cccf 100644 --- a/include/nw4r/g3d/g3d_scnproc.h +++ b/include/nw4r/g3d/g3d_scnproc.h @@ -13,7 +13,8 @@ class ScnProc : public ScnLeaf { public: static ScnProc* Construct(MEMAllocator* pAllocator, u32* pSize, - DrawProc pProc, bool opa, bool xlu, u32 userData); + DrawProc pProc, bool opa, bool xlu, + u32 userData = 0); ScnProc(MEMAllocator* pAllocator, DrawProc pProc, void* pUserData, bool opa, bool xlu) diff --git a/include/nw4r/g3d/g3d_scnrfl.h b/include/nw4r/g3d/g3d_scnrfl.h index 104865b..a51813e 100644 --- a/include/nw4r/g3d/g3d_scnrfl.h +++ b/include/nw4r/g3d/g3d_scnrfl.h @@ -18,7 +18,7 @@ class ScnRfl : public ScnLeaf { public: static ScnRfl* Construct(MEMAllocator* pAllocator, u32* pSize, RFLResolution resolution, u32 exprFlags, - u32 userDataSize); + u32 userDataSize = 0); ScnRfl(MEMAllocator* pAllocator, void* pNglBuffer, void* pUserData, RFLResolution resolution, u32 exprFlag); diff --git a/include/nw4r/g3d/res/g3d_resshp.h b/include/nw4r/g3d/res/g3d_resshp.h index 6134699..650822c 100644 --- a/include/nw4r/g3d/res/g3d_resshp.h +++ b/include/nw4r/g3d/res/g3d_resshp.h @@ -18,6 +18,9 @@ namespace g3d { * ******************************************************************************/ struct ResPrePrimDL { + static const int SIZE_GXVTXDESCLIST = (GX_VA_TEX7 + 1) + 1; + static const int SIZE_GXVTXATTRFMTLIST = (GX_VA_TEX7 - GX_VA_POS + 1) + 1; + union { struct { u8 cullMode[10]; // at 0x0 diff --git a/include/nw4r/lyt/lyt_pane.h b/include/nw4r/lyt/lyt_pane.h index c8d2cdc..25f4d58 100644 --- a/include/nw4r/lyt/lyt_pane.h +++ b/include/nw4r/lyt/lyt_pane.h @@ -79,7 +79,11 @@ class Pane : public detail::PaneBase { NW4R_UT_RTTI_DECL(Pane); private: - enum FlagBit { BIT_VISIBLE, BIT_INFLUENCED_ALPHA, BIT_LOCATION_ADJUST }; + enum { + BIT_VISIBLE, + BIT_INFLUENCED_ALPHA, + BIT_LOCATION_ADJUST, + }; // Need the typedef before the class definition is complete typedef ut::LinkList PaneList; diff --git a/include/nw4r/snd/snd_BasicSound.h b/include/nw4r/snd/snd_BasicSound.h index 12861e1..7985fbd 100644 --- a/include/nw4r/snd/snd_BasicSound.h +++ b/include/nw4r/snd/snd_BasicSound.h @@ -154,6 +154,10 @@ class BasicSound { AmbientArgAllocaterCallback* pArgAlloc, void* pArg); + bool GetStartedFlag() const { + return mStartedFlag; + } + void SetPriority(int priority) { mPriority = priority; } diff --git a/include/nw4r/snd/snd_RemoteSpeakerManager.h b/include/nw4r/snd/snd_RemoteSpeakerManager.h index 4b1dc6a..c362987 100644 --- a/include/nw4r/snd/snd_RemoteSpeakerManager.h +++ b/include/nw4r/snd/snd_RemoteSpeakerManager.h @@ -23,9 +23,17 @@ class RemoteSpeakerManager { private: static const int SPEAKER_ALARM_HZ = 150; +#if defined(__KOKESHI__) +#pragma warning off(10124) +#endif + static const int SPEAKER_ALARM_PERIOD_NSEC = static_cast(1.0f / SPEAKER_ALARM_HZ * 1000 * 1000 * 1000); +#if defined(__KOKESHI__) +#pragma warning reset(10124) +#endif + private: RemoteSpeakerManager(); diff --git a/include/nw4r/snd/snd_SeqPlayer.h b/include/nw4r/snd/snd_SeqPlayer.h index dd5e959..1d4903e 100644 --- a/include/nw4r/snd/snd_SeqPlayer.h +++ b/include/nw4r/snd/snd_SeqPlayer.h @@ -143,6 +143,10 @@ class SeqPlayer : public BasicPlayer, return mParserParam; } + u32 GetTickCounter() const { + return mTickCounter; + } + private: static const int DEFAULT_TEMPO = 120; static const int DEFAULT_TIMEBASE = 48; diff --git a/include/nw4r/snd/snd_SeqSound.h b/include/nw4r/snd/snd_SeqSound.h index da1977b..0d37cac 100644 --- a/include/nw4r/snd/snd_SeqSound.h +++ b/include/nw4r/snd/snd_SeqSound.h @@ -81,6 +81,10 @@ class SeqSound : public BasicSound { return sizeof(mFileStreamBuffer); } + u32 GetTick() const { + return !GetStartedFlag() ? 0 : mSeqPlayer.GetTickCounter(); + } + private: typedef void (*SeqLoadCallback)(bool success, const void* pBase, void* pCallbackArg); diff --git a/include/nw4r/snd/snd_SeqSoundHandle.h b/include/nw4r/snd/snd_SeqSoundHandle.h index e22b00d..796e72e 100644 --- a/include/nw4r/snd/snd_SeqSoundHandle.h +++ b/include/nw4r/snd/snd_SeqSoundHandle.h @@ -43,6 +43,14 @@ class SeqSoundHandle : private ut::NonCopyable { } } + u32 GetTick() const { + if (IsAttachedSound()) { + return mSound->GetTick(); + } + + return 0; + } + private: detail::SeqSound* mSound; // at 0x0 }; diff --git a/include/nw4r/snd/snd_Sound3DListener.h b/include/nw4r/snd/snd_Sound3DListener.h index d2bf333..4ca0493 100644 --- a/include/nw4r/snd/snd_Sound3DListener.h +++ b/include/nw4r/snd/snd_Sound3DListener.h @@ -14,6 +14,9 @@ class Sound3DListener { const math::MTX34& GetMatrix() const { return mMtx; } + void SetMatrix(const math::MTX34& rMtx) { + mMtx = rMtx; + } f32 GetInteriorSize() const { return mInteriorSize; diff --git a/include/nw4r/snd/snd_Sound3DManager.h b/include/nw4r/snd/snd_Sound3DManager.h index 62c5ffc..e1ec10e 100644 --- a/include/nw4r/snd/snd_Sound3DManager.h +++ b/include/nw4r/snd/snd_Sound3DManager.h @@ -50,6 +50,9 @@ class Sound3DManager : public detail::BasicSound::AmbientParamUpdateCallback, Sound3DListener* GetListener() const { return mListener; } + void AddListener(Sound3DListener* pListener) { + mListener = pListener; + } int GetMaxPriorityReduction() const { return mMaxPriorityReduction; diff --git a/include/nw4r/snd/snd_SoundSystem.h b/include/nw4r/snd/snd_SoundSystem.h index 7eb941c..71c1662 100644 --- a/include/nw4r/snd/snd_SoundSystem.h +++ b/include/nw4r/snd/snd_SoundSystem.h @@ -6,6 +6,8 @@ #include #include +#include + namespace nw4r { namespace snd { @@ -14,6 +16,12 @@ class FxBase; class SoundSystem { public: + static const int DEFAULT_DVD_THREAD_PRIORITY = 3; + static const int DEFAULT_DVD_THREAD_STACK_SIZE = OS_MEM_KB_TO_B(16); + + static const int DEFAULT_SOUND_THREAD_PRIORITY = 4; + static const int DEFAULT_SOUND_THREAD_STACK_SIZE = OS_MEM_KB_TO_B(16); + struct SoundSystemParam { s32 soundThreadPriority; // at 0x0 u32 soundThreadStackSize; // at 0x4 @@ -64,13 +72,6 @@ class SoundSystem { detail::AxManager::GetInstance().ClearEffect(bus, frame); } -private: - static const int DEFAULT_DVD_THREAD_PRIORITY = 3; - static const int DEFAULT_DVD_THREAD_STACK_SIZE = 0x4000; - - static const int DEFAULT_SOUND_THREAD_PRIORITY = 4; - static const int DEFAULT_SOUND_THREAD_STACK_SIZE = 0x4000; - private: static detail::TaskThread sTaskThread; }; diff --git a/include/nw4r/snd/snd_Types.h b/include/nw4r/snd/snd_Types.h index d095b39..8f3c67e 100644 --- a/include/nw4r/snd/snd_Types.h +++ b/include/nw4r/snd/snd_Types.h @@ -10,10 +10,6 @@ static const int CHANNEL_MAX = 2; static const int REMOTE_FILTER_MAX = 127; -// 12 notes each with 256 microtones -static const int SEMITONE_MAX = 12; -static const int MICROTONE_MAX = 256; - // Volume in range [-90.4db, 6.0db] static const f32 VOLUME_MIN_DB = -90.4f; static const f32 VOLUME_MAX_DB = 6.0f; diff --git a/include/nw4r/snd/snd_Util.h b/include/nw4r/snd/snd_Util.h index 867c024..d0fa93f 100644 --- a/include/nw4r/snd/snd_Util.h +++ b/include/nw4r/snd/snd_Util.h @@ -2,140 +2,195 @@ #define NW4R_SND_UTIL_H #include +#include + namespace nw4r { namespace snd { namespace detail { -namespace Util { - -/****************************************************************************** - * - * Pan info - * - ******************************************************************************/ -enum PanCurve { - PAN_CURVE_SQRT, - PAN_CURVE_SINCOS, - PAN_CURVE_LINEAR, -}; -struct PanInfo { - PanCurve curve; // at 0x0 - bool centerZero; // at 0x4 - bool zeroClamp; // at 0x5 - - PanInfo() : curve(PAN_CURVE_SQRT), centerZero(false), zeroClamp(false) {} -}; +class Util { +public: + // 12 notes each with 256 microtones + static const int SEMITONE_MAX = 12; + static const int MICROTONE_MAX = 256; -/****************************************************************************** - * - * DataRef - * - ******************************************************************************/ -enum RefType { - REFTYPE_ADDRESS, - REFTYPE_OFFSET, -}; - -enum DataType { - DATATYPE_T0, - DATATYPE_T1, - DATATYPE_T2, - DATATYPE_T3, - DATATYPE_INVALID -}; +#if defined(__KOKESHI__) +#pragma warning off(10124) +#endif -template -struct DataRef { - u8 refType; // at 0x0 - u8 dataType; // at 0x1 - u16 reserved; // at 0x2 - u32 value; // at 0x4 -}; + static const int VOLUME_MIN = + static_cast(10 * VOLUME_MIN_DB); // -90.4db + static const int VOLUME_MAX = + static_cast(10 * VOLUME_MAX_DB); // +6.0db -/****************************************************************************** - * - * Table - * - ******************************************************************************/ -template struct Table { - u32 count; // at 0x0 - T items[1]; // at 0x4 -}; +#if defined(__KOKESHI__) +#pragma warning reset(10124) +#endif -/****************************************************************************** - * - * DataRef accessor functions - * - ******************************************************************************/ -template -inline const T0* GetDataRefAddress0(const DataRef& rRef, - const void* pBase) { - return static_cast(GetDataRefAddressImpl( - static_cast(rRef.refType), rRef.value, pBase)); -} - -template -inline const T1* GetDataRefAddress1(const DataRef& rRef, - const void* pBase) { - return static_cast(GetDataRefAddressImpl( - static_cast(rRef.refType), rRef.value, pBase)); -} - -template -inline const T2* GetDataRefAddress2(const DataRef& rRef, - const void* pBase) { - return static_cast(GetDataRefAddressImpl( - static_cast(rRef.refType), rRef.value, pBase)); -} - -template -inline const T3* GetDataRefAddress3(const DataRef& rRef, - const void* pBase) { - return static_cast(GetDataRefAddressImpl( - static_cast(rRef.refType), rRef.value, pBase)); -} - -/****************************************************************************** - * - * Read big endian value - * - ******************************************************************************/ +public: + /****************************************************************************** + * + * Pan info + * + ******************************************************************************/ + enum PanCurve { + PAN_CURVE_SQRT, + PAN_CURVE_SINCOS, + PAN_CURVE_LINEAR, + }; + + struct PanInfo { + PanCurve curve; // at 0x0 + bool centerZero; // at 0x4 + bool zeroClamp; // at 0x5 + + PanInfo() + : curve(PAN_CURVE_SQRT), centerZero(false), zeroClamp(false) {} + }; + + /****************************************************************************** + * + * DataRef + * + ******************************************************************************/ + enum RefType { + REFTYPE_ADDRESS, + REFTYPE_OFFSET, + }; + + enum DataType { + DATATYPE_T0, + DATATYPE_T1, + DATATYPE_T2, + DATATYPE_T3, + DATATYPE_INVALID + }; + + template + struct DataRef { + u8 refType; // at 0x0 + u8 dataType; // at 0x1 + u16 reserved; // at 0x2 + u32 value; // at 0x4 + }; + + template + static inline const T0* + GetDataRefAddress0(const DataRef& rRef, const void* pBase) { + return static_cast(GetDataRefAddressImpl( + static_cast(rRef.refType), rRef.value, pBase)); + } + + template + static inline const T1* + GetDataRefAddress1(const DataRef& rRef, const void* pBase) { + return static_cast(GetDataRefAddressImpl( + static_cast(rRef.refType), rRef.value, pBase)); + } + + template + static inline const T2* + GetDataRefAddress2(const DataRef& rRef, const void* pBase) { + return static_cast(GetDataRefAddressImpl( + static_cast(rRef.refType), rRef.value, pBase)); + } + + template + static inline const T3* + GetDataRefAddress3(const DataRef& rRef, const void* pBase) { + return static_cast(GetDataRefAddressImpl( + static_cast(rRef.refType), rRef.value, pBase)); + } + + /****************************************************************************** + * + * Table + * + ******************************************************************************/ + template struct Table { + u32 count; // at 0x0 + T items[1]; // at 0x4 + }; + + /****************************************************************************** + * + * Read big endian value + * + ******************************************************************************/ #ifdef NW4R_LITLE_ENDIAN -inline u16 ReadBigEndian(u16 x) { - return x >> 8 | x << 8; -} - -inline u32 ReadBigEndian(u32 x) { - return (x >> 24) & 0x000000FF | (x >> 8) & 0x0000FF00 | - (x << 8) & 0x00FF0000 | (x << 24) & 0xFF000000; -} + static inline u16 ReadBigEndian(u16 x) { + return x >> 8 | x << 8; + } + + static inline u32 ReadBigEndian(u32 x) { + return (x >> 24) & 0x000000FF | (x >> 8) & 0x0000FF00 | + (x << 8) & 0x00FF0000 | (x << 24) & 0xFF000000; + } #else -inline u16 ReadBigEndian(u16 x) { - return x; -} + static inline u16 ReadBigEndian(u16 x) { + return x; + } -inline u32 ReadBigEndian(u32 x) { - return x; -} + static inline u32 ReadBigEndian(u32 x) { + return x; + } #endif -/****************************************************************************** - * - * Utility functions - * - ******************************************************************************/ -f32 CalcPitchRatio(int pitch); -f32 CalcVolumeRatio(f32 db); -f32 CalcPanRatio(f32 pan, const PanInfo& rInfo); -f32 CalcSurroundPanRatio(f32 pan, const PanInfo& rInfo); -int CalcLpfFreq(f32 scale); -void GetRemoteFilterCoefs(int filter, u16* pB0, u16* pB1, u16* pB2, u16* pA1, - u16* pA2); -u16 CalcRandom(); -const void* GetDataRefAddressImpl(RefType type, u32 value, const void* pBase); - -} // namespace Util + /****************************************************************************** + * + * Utility functions + * + ******************************************************************************/ + static f32 CalcPitchRatio(int pitch); + static f32 CalcVolumeRatio(f32 db); + static f32 CalcPanRatio(f32 pan, const PanInfo& rInfo); + static f32 CalcSurroundPanRatio(f32 pan, const PanInfo& rInfo); + static int CalcLpfFreq(f32 scale); + static void GetRemoteFilterCoefs(int filter, u16* pB0, u16* pB1, u16* pB2, + u16* pA1, u16* pA2); + static u16 CalcRandom(); + +private: + static const void* GetDataRefAddressImpl(RefType type, u32 value, + const void* pBase); + +private: + // Chromatic scale (tbl[idx] / tbl[idx-1] == ~1.06) + static const f32 NoteTable[SEMITONE_MAX]; + // Each note contains 256 microtones + static const f32 PitchTable[MICROTONE_MAX]; + + // Table index is the millibel / hundredth-of-a-decibel + // dB(idx) = VOLUME_MIN_DB + (idx / 10) + // tbl[idx] = 10 ** (dB(idx) / 20) + static const int VOLUME_TABLE_SIZE = VOLUME_RANGE_MB + 1; + static const f32 Decibel2RatioTable[VOLUME_TABLE_SIZE]; + + // 1/256 step + static const int PAN_TABLE_MIN = 0; + static const int PAN_TABLE_MAX = 256; + static const int PAN_TABLE_CENTER = PAN_TABLE_MAX / 2; + static const int PAN_TABLE_SIZE = PAN_TABLE_MAX + 1; + // tbl[idx] = sqrt(1 - (idx / PAN_TABLE_MAX)) + static const f32 Pan2RatioTableSqrt[PAN_TABLE_SIZE]; + // tbl[idx] = cos(idx * (PI / (2 * PAN_TABLE_MAX))) + static const f32 Pan2RatioTableSinCos[PAN_TABLE_SIZE]; + // tbl[idx] = 1 - (idx * (1 / PAN_TABLE_MAX)) + static const f32 Pan2RatioTableLinear[PAN_TABLE_SIZE]; + + // Pan curve tables + static const int PAN_CURVE_NUM = PAN_CURVE_LINEAR + 1; + static const f32* PanTableTable[PAN_CURVE_NUM]; + + // Biquad filter coefficients (b0, b1, b2, a1, a2) + static const int COEF_TABLE_MIN = 0; + static const int COEF_TABLE_MAX = REMOTE_FILTER_MAX; + static const int COEF_TABLE_SIZE = COEF_TABLE_MAX + 1; + static const int IIR_COEF_COUNT = 5; + static const u16 RemoteFilterCoefTable[COEF_TABLE_SIZE][IIR_COEF_COUNT]; +}; + } // namespace detail } // namespace snd } // namespace nw4r diff --git a/include/nw4r/types_nw4r.h b/include/nw4r/types_nw4r.h index d1c68ad..47fe82b 100644 --- a/include/nw4r/types_nw4r.h +++ b/include/nw4r/types_nw4r.h @@ -5,234 +5,17 @@ #define NW4R_BYTEORDER_BIG 0xFEFF #define NW4R_BYTEORDER_LITTLE 0xFFFE -#define NW4R_VERSION(major, minor) ((major & 0xFF) << 8 | minor & 0xFF) - #ifdef NW4R_LITTLE_ENDIAN #define NW4R_BYTEORDER_NATIVE NW4R_BYTEORDER_LITTLE #else #define NW4R_BYTEORDER_NATIVE NW4R_BYTEORDER_BIG #endif +#define NW4R_VERSION(major, minor) ((major & 0xFF) << 8 | minor & 0xFF) + #define NW4R_LIB_VERSION(NAME, ORIGINAL_DATE, ORIGINAL_TIME, ORIGINAL_CWCC) \ const char* NW4R_##NAME##_Version_ = \ "<< NW4R - " #NAME " \tfinal build: " ORIGINAL_DATE \ " " ORIGINAL_TIME " (" ORIGINAL_CWCC ") >>" -namespace nw4r { -namespace ut { -namespace detail { - -struct RuntimeTypeInfo; -struct ResFontBase; - -} // namespace detail - -template struct AutoLock; -struct AutoInterruptLock; -struct BinaryBlockHeader; -struct BinaryFileHeader; -struct CharStrmReader; -struct CharWidths; -struct CharWriter; -struct Color; -struct DvdFileStream; -struct DvdLockedFileStream; -struct FileStream; -struct Font; -struct Glyph; -struct IOStream; -template struct LinkList; -struct List; -struct NandFileStream; -template struct PrintContext; -struct Rect; -struct ResFont; -struct RomFont; -template struct TagProcessorBase; -template struct TextWriterBase; - -} // namespace ut - -namespace ef { -struct DrawOrder; -struct DrawInfo; -struct DrawStrategy; -struct DrawStrategyImpl; -struct DrawStrategyBuilder; -struct Effect; -struct EffectSystem; -struct EffectProject; -struct Emitter; -struct EmitterDrawSetting; -struct EmitFormBuilder; -struct ResEmitter; -struct EmitterResource; -struct EmitterForm; -struct EmitterInheritSetting; -struct Particle; -struct ParticleManager; -struct MemoryManager; -struct MemoryManagerBase; -} // namespace ef - -namespace math { - -struct VEC2; -struct VEC3; -struct MTX33; -struct MTX34; -struct MTX44; -struct QUAT; -struct PLANE; -struct AABB; -struct FRUSTUM; - -} // namespace math - -namespace snd { - -struct AxVoice; -struct FxBase; -struct SoundPlayer; -struct SoundHandle; -struct SeqSoundHandle; -struct SoundArchive; -struct SoundArchivePlayer; -struct Sound3DActor; -struct Sound3DListener; -struct Sound3DManager; -struct SoundHandle; -struct StrmSoundHandle; -struct WaveSoundHandle; - -namespace detail { - -struct AxfxImpl; -struct AxManager; -struct AxVoiceManager; -struct ExternalSoundPlayer; - -struct BasicSound; -struct BasicPlayer; -struct ChannelManager; -struct SeqSound; -struct SeqPlayer; -struct MmlParser; -struct MmlSeqTrack; -struct SeqTrack; -struct SeqTrackAllocator; -template struct SoundInstanceManager; -struct StrmBufferPool; -struct StrmSound; -struct NoteOnCallback; -struct PlayerHeap; -struct SoundArchiveFileReader; -struct SoundThread; -struct WaveSound; -struct StrmPlayer; -struct WsdPlayer; -} // namespace detail -} // namespace snd - -namespace g3d { -struct AnmObjVis; -struct AnmObjVisNode; -struct AnmObjVisOR; -struct AnmObjVisRes; -struct AnmObj; -struct AnmObjChr; -struct FuncObjCalcWorld; -struct AnmScn; -struct AnmScnRes; -struct CameraAnmResult; -struct Draw1Mat1ShpSwap; -struct DrawResMdlReplacement; -struct FogAnmResult; -struct ResFile; -struct ResMdl; -struct ResPltt; -struct ResTex; -struct ResTexSrt; -struct ResMat; -struct ResTexPlttInfo; -struct ResShp; -struct ResFog; -struct ResAnmChr; -struct ResAnmVis; -struct ResAnmClr; -struct ResAnmTexPat; -struct ResAnmTexSrt; -struct ResAnmShp; -struct ResAnmScn; -struct ResAnmFog; -struct ResAnmCamera; -struct ResVtxPos; -struct ResVtxNrm; -struct ResVtxClr; -struct ResVtxTexCoord; -struct ClrAnmResult; -struct TexPatAnmResult; -struct TexSrtAnmResult; -struct ScnMdl1Mat1Shp; -struct TexSrt; -struct TexSrtTypedef; -struct LightObj; -struct LightAnmResult; -struct LightSet; -struct LightSetting; -struct LightSetData; -struct AmbLightObj; -struct AmbLightAnmResult; -struct Fog; -struct ScnRoot; -struct ScnProc; -struct ScnLeaf; -struct ScnObj; -struct ScnRfl; -struct ScnGroup; -struct ScnMdlSimple; -struct ScnMdl; -struct IScnObjGather; -struct IScnObjCallback; - -namespace G3DState { -struct IndMtxOp; -} -} // namespace g3d - -namespace lyt { -struct Size; - -namespace detail { -struct PaneBase; -struct TexCoordAry; -} // namespace detail - -namespace res { -struct Group; -struct Pane; -struct Bounding; -struct AnimationBlock; -struct BinaryFileHeader; -} // namespace res - -struct Group; -struct GroupContainer; -struct Pane; -struct DrawInfo; -struct AnimResource; -struct AnimTransform; -struct AnimTransformBasic; -struct AnimationLink; -struct ResourceAccessor; -struct ArcResourceAccessor; -struct FontRefLink; -struct Material; -struct Layout; -struct Bounding; -struct ResBlockSet; -struct TexMap; -} // namespace lyt -} // namespace nw4r - #endif diff --git a/include/nw4r/ut/ut_list.h b/include/nw4r/ut/ut_list.h index 7b0b9a3..c603724 100644 --- a/include/nw4r/ut/ut_list.h +++ b/include/nw4r/ut/ut_list.h @@ -58,6 +58,25 @@ inline u16 List_GetSize(const List* pList) { return pList->numObjects; } +/****************************************************************************** + * + * Macros + * + ******************************************************************************/ +/** + * Declares a member Link. + */ +#define NW4R_UT_LIST_LINK_DECL() nw4r::ut::Link link + +/** + * Initializes a List object for use with the specified type. + * + * @param LIST Reference to list + * @param T List element type + */ +#define NW4R_UT_LIST_INIT(LIST, T) \ + nw4r::ut::List_Init(&(LIST), offsetof(T, link)) + /** * Gets the underlying Link within the specified object. * diff --git a/include/revolution/ARC/arc.h b/include/revolution/ARC/arc.h index 481df6b..7cf5810 100644 --- a/include/revolution/ARC/arc.h +++ b/include/revolution/ARC/arc.h @@ -40,12 +40,12 @@ typedef struct ARCDirEntry { } ARCDirEntry; BOOL ARCGetCurrentDir(ARCHandle* handle, char* string, u32 maxlen); -BOOL ARCInitHandle(void* bin, ARCHandle* handle); +BOOL ARCInitHandle(const void* bin, ARCHandle* handle); BOOL ARCOpen(ARCHandle* handle, const char* path, ARCFileInfo* info); BOOL ARCFastOpen(ARCHandle* handle, s32 entrynum, ARCFileInfo* info); s32 ARCConvertPathToEntrynum(ARCHandle* handle, const char* path); void* ARCGetStartAddrInMem(ARCFileInfo* info); -s32 ARCGetStartOffset(ARCFileInfo* info); +u32 ARCGetStartOffset(ARCFileInfo* info); u32 ARCGetLength(ARCFileInfo* info); BOOL ARCClose(ARCFileInfo* info); BOOL ARCChangeDir(ARCHandle* handle, const char* path); diff --git a/include/revolution/AX/AX.h b/include/revolution/AX/AX.h index ba90ff0..09c6ca9 100644 --- a/include/revolution/AX/AX.h +++ b/include/revolution/AX/AX.h @@ -11,4 +11,4 @@ void AXInitEx(u32 mode); #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/AX/AXAlloc.h b/include/revolution/AX/AXAlloc.h index 3cabacc..b158c16 100644 --- a/include/revolution/AX/AXAlloc.h +++ b/include/revolution/AX/AXAlloc.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_AX_ALLOC_H #define RVL_SDK_AX_ALLOC_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/AX/AXAux.h b/include/revolution/AX/AXAux.h index 75e90e3..bdc7216 100644 --- a/include/revolution/AX/AXAux.h +++ b/include/revolution/AX/AXAux.h @@ -59,4 +59,4 @@ void AXGetAuxCCallback(AXAuxCallback* callback, void** context); #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/AX/AXCL.h b/include/revolution/AX/AXCL.h index 29279c8..4a865f8 100644 --- a/include/revolution/AX/AXCL.h +++ b/include/revolution/AX/AXCL.h @@ -37,4 +37,4 @@ void AXSetAuxCReturnVolume(u16 volume); #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/AX/AXComp.h b/include/revolution/AX/AXComp.h index 36f917f..1a8a112 100644 --- a/include/revolution/AX/AXComp.h +++ b/include/revolution/AX/AXComp.h @@ -10,4 +10,4 @@ extern u16 __AXCompressorTable[]; #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/AX/AXOut.h b/include/revolution/AX/AXOut.h index 08e3489..3405398 100644 --- a/include/revolution/AX/AXOut.h +++ b/include/revolution/AX/AXOut.h @@ -23,4 +23,4 @@ s32 AXRmtAdvancePtr(s32 num); #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/AX/AXVPB.h b/include/revolution/AX/AXVPB.h index 7c837ec..8b243c8 100644 --- a/include/revolution/AX/AXVPB.h +++ b/include/revolution/AX/AXVPB.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_AX_VPB_H #define RVL_SDK_AX_VPB_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/AX/DSPCode.h b/include/revolution/AX/DSPCode.h index 2167564..2b3b0a6 100644 --- a/include/revolution/AX/DSPCode.h +++ b/include/revolution/AX/DSPCode.h @@ -14,4 +14,4 @@ extern u16 axDspSlaveLength; #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/AXFX/AXFXChorus.h b/include/revolution/AXFX/AXFXChorus.h index a8d111b..a9315ba 100644 --- a/include/revolution/AXFX/AXFXChorus.h +++ b/include/revolution/AXFX/AXFXChorus.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_AXFX_CHORUS_H #define RVL_SDK_AXFX_CHORUS_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif @@ -23,4 +22,4 @@ void AXFXChorusCallback(void* chans, void* context); #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/AXFX/AXFXHooks.h b/include/revolution/AXFX/AXFXHooks.h index 86529de..01cce85 100644 --- a/include/revolution/AXFX/AXFXHooks.h +++ b/include/revolution/AXFX/AXFXHooks.h @@ -17,4 +17,4 @@ void AXFXGetHooks(AXFXAllocHook* alloc, AXFXFreeHook* free); #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/AXFX/AXFXReverbHi.h b/include/revolution/AXFX/AXFXReverbHi.h index be0e88e..0430b99 100644 --- a/include/revolution/AXFX/AXFXReverbHi.h +++ b/include/revolution/AXFX/AXFXReverbHi.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_AXFX_REVERB_HI_H #define RVL_SDK_AXFX_REVERB_HI_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif @@ -26,4 +25,4 @@ void AXFXReverbHiCallback(void* chans, void* context); #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/AXFX/AXFXReverbHiDpl2.h b/include/revolution/AXFX/AXFXReverbHiDpl2.h index 4dc8f48..1e11240 100644 --- a/include/revolution/AXFX/AXFXReverbHiDpl2.h +++ b/include/revolution/AXFX/AXFXReverbHiDpl2.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_AXFX_REVERB_HI_DPL2_H #define RVL_SDK_AXFX_REVERB_HI_DPL2_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/BTE.h b/include/revolution/BTE.h index 0318864..7dfba99 100644 --- a/include/revolution/BTE.h +++ b/include/revolution/BTE.h @@ -23,6 +23,16 @@ extern "C" { #include #include +/****************************************************************************** + * + * RVL + * + ******************************************************************************/ +#include + +// Yeah... +#undef TRUE + #ifdef __cplusplus } #endif diff --git a/include/revolution/BTE/audio_a2dp_hw/audio_a2dp_hw.h b/include/revolution/BTE/audio_a2dp_hw/audio_a2dp_hw.h index d0223e8..2015591 100644 --- a/include/revolution/BTE/audio_a2dp_hw/audio_a2dp_hw.h +++ b/include/revolution/BTE/audio_a2dp_hw/audio_a2dp_hw.h @@ -83,3 +83,4 @@ typedef enum { ******************************************************************************/ #endif /* A2DP_AUDIO_HW_H */ + diff --git a/include/revolution/BTE/bta/ag/bta_ag_at.h b/include/revolution/BTE/bta/ag/bta_ag_at.h index 6ead04f..90d7b0f 100644 --- a/include/revolution/BTE/bta/ag/bta_ag_at.h +++ b/include/revolution/BTE/bta/ag/bta_ag_at.h @@ -118,3 +118,4 @@ extern void bta_ag_at_reinit(tBTA_AG_AT_CB *p_cb); extern void bta_ag_at_parse(tBTA_AG_AT_CB *p_cb, char *p_buf, UINT16 len); #endif /* BTA_AG_AT_H */ + diff --git a/include/revolution/BTE/bta/dm/bta_dm_int.h b/include/revolution/BTE/bta/dm/bta_dm_int.h index 83f580e..3ff008f 100644 --- a/include/revolution/BTE/bta/dm/bta_dm_int.h +++ b/include/revolution/BTE/bta/dm/bta_dm_int.h @@ -1011,3 +1011,4 @@ extern void bta_dm_execute_callback(tBTA_DM_MSG *p_data); extern void bta_dm_set_afh_channel_assesment(tBTA_DM_MSG *p_data); #endif /* BTA_DM_INT_H */ + diff --git a/include/revolution/BTE/bta/gatt/bta_gatts_int.h b/include/revolution/BTE/bta/gatt/bta_gatts_int.h index c6f0b40..4810c05 100644 --- a/include/revolution/BTE/bta/gatt/bta_gatts_int.h +++ b/include/revolution/BTE/bta/gatt/bta_gatts_int.h @@ -243,3 +243,4 @@ extern tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_attr_id(tBTA_GATTS_CB *p_c #endif /* BTA_GATTS_INT_H */ + diff --git a/include/revolution/BTE/bta/hh/bta_hh_int.h b/include/revolution/BTE/bta/hh/bta_hh_int.h index bbbb197..f3a8e54 100644 --- a/include/revolution/BTE/bta/hh/bta_hh_int.h +++ b/include/revolution/BTE/bta/hh/bta_hh_int.h @@ -245,3 +245,4 @@ extern void bta_hh_trace_dev_db(void); #endif #endif + diff --git a/include/revolution/BTE/bta/hl/bta_hl_int.h b/include/revolution/BTE/bta/hl/bta_hl_int.h index c07e973..648eb2c 100644 --- a/include/revolution/BTE/bta/hl/bta_hl_int.h +++ b/include/revolution/BTE/bta/hl/bta_hl_int.h @@ -854,3 +854,5 @@ extern "C" } #endif #endif /* BTA_MSE_INT_H */ + + diff --git a/include/revolution/BTE/bta/include/bd.h b/include/revolution/BTE/bta/include/bd.h index 878e2e9..33c3de1 100644 --- a/include/revolution/BTE/bta/include/bd.h +++ b/include/revolution/BTE/bta/include/bd.h @@ -99,3 +99,4 @@ extern void bdsetany(BD_ADDR a); #endif #endif /* BD_H */ + diff --git a/include/revolution/BTE/bta/include/bta_ag_api.h b/include/revolution/BTE/bta/include/bta_ag_api.h index 391dedd..f16687c 100644 --- a/include/revolution/BTE/bta/include/bta_ag_api.h +++ b/include/revolution/BTE/bta/include/bta_ag_api.h @@ -510,3 +510,5 @@ BTA_API void BTA_AgSetCodec(UINT16 handle, tBTA_AG_PEER_CODEC codec); #endif #endif /* BTA_AG_API_H */ + + diff --git a/include/revolution/BTE/bta/include/bta_ag_ci.h b/include/revolution/BTE/bta/include/bta_ag_ci.h index 76ed3ae..3bc0e53 100644 --- a/include/revolution/BTE/bta/include/bta_ag_ci.h +++ b/include/revolution/BTE/bta/include/bta_ag_ci.h @@ -79,3 +79,4 @@ BTA_API extern void bta_ag_ci_wbs_command (UINT16 handle, char *p_data, UINT16 l #endif #endif /* BTA_AG_CI_H */ + diff --git a/include/revolution/BTE/bta/include/bta_ag_co.h b/include/revolution/BTE/bta/include/bta_ag_co.h index 0fc1441..c6a3392 100644 --- a/include/revolution/BTE/bta/include/bta_ag_co.h +++ b/include/revolution/BTE/bta/include/bta_ag_co.h @@ -109,3 +109,4 @@ BTA_API extern void bta_ag_co_data_close(UINT16 handle); BTA_API extern void bta_ag_co_tx_write(UINT16 handle, UINT8 *p_data, UINT16 len); #endif /* BTA_AG_CO_H */ + diff --git a/include/revolution/BTE/bta/include/bta_api.h b/include/revolution/BTE/bta/include/bta_api.h index 4bfcbca..60fa9b9 100644 --- a/include/revolution/BTE/bta/include/bta_api.h +++ b/include/revolution/BTE/bta/include/bta_api.h @@ -9,6 +9,9 @@ * - Change search callback event IDs * - Change tBTA_DM_INQ_RES structure * + * 2025/05/02: + * - Add BTA_DmSendHciReset + * * Compile with REVOLUTION defined to include these changes. * ******************************************************************************/ @@ -1351,6 +1354,17 @@ BTA_API extern void BTA_DmAuthorizeReply(BD_ADDR bd_addr, tBTA_SERVICE_ID servic *******************************************************************************/ BTA_API extern void BTA_DmSignalStrength(tBTA_SIG_STRENGTH_MASK mask, UINT16 period, BOOLEAN start); +#ifdef REVOLUTION +/******************************************************************************* +** +** Function BTA_DmSendHciReset +** +** Returns void +** +*******************************************************************************/ +void BTA_DmSendHciReset(void); +#endif + /******************************************************************************* ** ** Function BTA_DmWriteInqTxPower diff --git a/include/revolution/BTE/bta/include/bta_av_ci.h b/include/revolution/BTE/bta/include/bta_av_ci.h index c8849fd..63668a9 100644 --- a/include/revolution/BTE/bta/include/bta_av_ci.h +++ b/include/revolution/BTE/bta/include/bta_av_ci.h @@ -71,3 +71,4 @@ BTA_API extern void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code, #endif #endif /* BTA_AV_CI_H */ + diff --git a/include/revolution/BTE/bta/include/bta_av_co.h b/include/revolution/BTE/bta/include/bta_av_co.h index e316f85..862ac5e 100644 --- a/include/revolution/BTE/bta/include/bta_av_co.h +++ b/include/revolution/BTE/bta/include/bta_av_co.h @@ -389,3 +389,4 @@ BTA_API extern void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, UINT16 delay); BTA_API extern void bta_av_co_video_delay(tBTA_AV_HNDL hndl, UINT16 delay); #endif /* BTA_AV_CO_H */ + diff --git a/include/revolution/BTE/bta/include/bta_av_sbc.h b/include/revolution/BTE/bta/include/bta_av_sbc.h index c211051..98eb6ae 100644 --- a/include/revolution/BTE/bta/include/bta_av_sbc.h +++ b/include/revolution/BTE/bta/include/bta_av_sbc.h @@ -204,3 +204,4 @@ extern UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap); extern void bta_av_sbc_bld_hdr(BT_HDR *p_buf, UINT16 fr_per_pkt); #endif /* BTA_AV_SBC_H */ + diff --git a/include/revolution/BTE/bta/include/bta_dm_ci.h b/include/revolution/BTE/bta/include/bta_dm_ci.h index 1068ebc..bf0983e 100644 --- a/include/revolution/BTE/bta/include/bta_dm_ci.h +++ b/include/revolution/BTE/bta/include/bta_dm_ci.h @@ -78,3 +78,4 @@ BTA_API extern void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle); #endif #endif + diff --git a/include/revolution/BTE/bta/include/bta_fs_ci.h b/include/revolution/BTE/bta/include/bta_fs_ci.h index 15ab31a..e2b5093 100644 --- a/include/revolution/BTE/bta/include/bta_fs_ci.h +++ b/include/revolution/BTE/bta/include/bta_fs_ci.h @@ -253,3 +253,4 @@ BTA_API extern void bta_fs_ci_resume_op(int fd, tBTA_FS_CO_STATUS status, const #endif #endif /* BTA_FS_CI_H */ + diff --git a/include/revolution/BTE/bta/include/bta_gatt_api.h b/include/revolution/BTE/bta/include/bta_gatt_api.h index 516151c..0404847 100644 --- a/include/revolution/BTE/bta/include/bta_gatt_api.h +++ b/include/revolution/BTE/bta/include/bta_gatt_api.h @@ -1216,3 +1216,4 @@ BTA_API extern void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_r #endif /* BTA_GATT_API_H */ + diff --git a/include/revolution/BTE/bta/include/bta_gattc_ci.h b/include/revolution/BTE/bta/include/bta_gattc_ci.h index e84d519..1525e3e 100644 --- a/include/revolution/BTE/bta/include/bta_gattc_ci.h +++ b/include/revolution/BTE/bta/include/bta_gattc_ci.h @@ -117,3 +117,4 @@ BTA_API extern void bta_gattc_ci_cache_save(BD_ADDR server_bda, UINT16 evt, #endif #endif /* BTA_GATTC_CI_H */ + diff --git a/include/revolution/BTE/bta/include/bta_gattc_co.h b/include/revolution/BTE/bta/include/bta_gattc_co.h index 9b1cb81..d2392b8 100644 --- a/include/revolution/BTE/bta/include/bta_gattc_co.h +++ b/include/revolution/BTE/bta/include/bta_gattc_co.h @@ -98,3 +98,4 @@ BTA_API extern void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt, UINT16 start_index, UINT16 conn_id); #endif /* BTA_GATT_CO_H */ + diff --git a/include/revolution/BTE/bta/include/bta_gatts_co.h b/include/revolution/BTE/bta/include/bta_gatts_co.h index 75c8b8e..86f65dc 100644 --- a/include/revolution/BTE/bta/include/bta_gatts_co.h +++ b/include/revolution/BTE/bta/include/bta_gatts_co.h @@ -79,3 +79,4 @@ BTA_API extern BOOLEAN bta_gatts_co_load_handle_range(UINT8 index, #endif /* BTA_GATTS_CO_H */ + diff --git a/include/revolution/BTE/bta/include/bta_hh_api.h b/include/revolution/BTE/bta/include/bta_hh_api.h index d7d2b58..2cf6a4c 100644 --- a/include/revolution/BTE/bta/include/bta_hh_api.h +++ b/include/revolution/BTE/bta/include/bta_hh_api.h @@ -303,7 +303,11 @@ extern "C" ** Returns void ** *******************************************************************************/ +#ifdef REVOLUTION +BTA_API extern void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback); +#else BTA_API extern void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback); +#endif /******************************************************************************* ** @@ -429,7 +433,11 @@ BTA_API extern void BTA_HhGetIdle(UINT8 dev_handle); ** Returns void ** *******************************************************************************/ +#ifdef REVOLUTION +BTA_API extern void BTA_HhSendData(UINT8 dev_handle, BT_HDR *p_buf); +#else BTA_API extern void BTA_HhSendData(UINT8 dev_handle, BD_ADDR dev_bda, BT_HDR *p_buf); +#endif /******************************************************************************* ** diff --git a/include/revolution/BTE/bta/include/bta_hh_co.h b/include/revolution/BTE/bta/include/bta_hh_co.h index 6233e93..8f648df 100644 --- a/include/revolution/BTE/bta/include/bta_hh_co.h +++ b/include/revolution/BTE/bta/include/bta_hh_co.h @@ -69,3 +69,4 @@ BTA_API extern void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, BTA_API extern void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id); #endif /* BTA_HH_CO_H */ + diff --git a/include/revolution/BTE/bta/include/bta_hl_api.h b/include/revolution/BTE/bta/include/bta_hl_api.h index 3b80008..e7febf8 100644 --- a/include/revolution/BTE/bta/include/bta_hl_api.h +++ b/include/revolution/BTE/bta/include/bta_hl_api.h @@ -868,3 +868,41 @@ extern "C" #endif #endif /* BTA_HL_API_H */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/revolution/BTE/bta/include/bta_hl_ci.h b/include/revolution/BTE/bta/include/bta_hl_ci.h index 52462a7..4d3951c 100644 --- a/include/revolution/BTE/bta/include/bta_hl_ci.h +++ b/include/revolution/BTE/bta/include/bta_hl_ci.h @@ -121,3 +121,5 @@ BTA_API extern void bta_hl_ci_put_echo_data( tBTA_HL_MCL_HANDLE mcl_handle, tBTA_HL_STATUS status, UINT16 evt ); #endif /* BTA_HL_CI_H */ + + diff --git a/include/revolution/BTE/bta/include/bta_jv_api.h b/include/revolution/BTE/bta/include/bta_jv_api.h index 0f5aa0c..73a9164 100644 --- a/include/revolution/BTE/bta/include/bta_jv_api.h +++ b/include/revolution/BTE/bta/include/bta_jv_api.h @@ -1119,3 +1119,4 @@ UINT16 BTA_JvRfcommGetPortHdl(UINT32 handle); #endif #endif /* BTA_JV_API_H */ + diff --git a/include/revolution/BTE/bta/include/bta_jv_co.h b/include/revolution/BTE/bta/include/bta_jv_co.h index 51294a4..098766c 100644 --- a/include/revolution/BTE/bta/include/bta_jv_co.h +++ b/include/revolution/BTE/bta/include/bta_jv_co.h @@ -47,3 +47,4 @@ BTA_API extern int bta_co_rfc_data_outgoing_size(void *user_data, int *size); BTA_API extern int bta_co_rfc_data_outgoing(void *user_data, UINT8* buf, UINT16 size); #endif /* BTA_DG_CO_H */ + diff --git a/include/revolution/BTE/bta/include/bta_op_api.h b/include/revolution/BTE/bta/include/bta_op_api.h index e10d5a0..c26ea35 100644 --- a/include/revolution/BTE/bta/include/bta_op_api.h +++ b/include/revolution/BTE/bta/include/bta_op_api.h @@ -64,3 +64,4 @@ typedef UINT8 tBTA_OP_FMT; typedef UINT8 tBTA_OP_FMT_MASK; #endif /* BTA_OP_API_H */ + diff --git a/include/revolution/BTE/bta/include/bta_pan_api.h b/include/revolution/BTE/bta/include/bta_pan_api.h index 94190de..2166766 100644 --- a/include/revolution/BTE/bta/include/bta_pan_api.h +++ b/include/revolution/BTE/bta/include/bta_pan_api.h @@ -198,3 +198,4 @@ BTA_API extern void BTA_PanClose(UINT16 handle); #endif #endif /* BTA_PAN_API_H */ + diff --git a/include/revolution/BTE/bta/include/bta_pan_ci.h b/include/revolution/BTE/bta/include/bta_pan_ci.h index 2c76122..faeef54 100644 --- a/include/revolution/BTE/bta/include/bta_pan_ci.h +++ b/include/revolution/BTE/bta/include/bta_pan_ci.h @@ -148,3 +148,4 @@ BTA_API extern void bta_pan_ci_set_mfilters(UINT16 handle, UINT16 num_mcast_filt #endif #endif /* BTA_PAN_CI_H */ + diff --git a/include/revolution/BTE/bta/include/bta_pan_co.h b/include/revolution/BTE/bta/include/bta_pan_co.h index df68b60..5b20fad 100644 --- a/include/revolution/BTE/bta/include/bta_pan_co.h +++ b/include/revolution/BTE/bta/include/bta_pan_co.h @@ -198,3 +198,4 @@ BTA_API extern void bta_pan_co_mfilt_ind(UINT16 handle, BOOLEAN indication, tBT UINT16 len, UINT8 *p_filters); #endif /* BTA_PAN_CO_H */ + diff --git a/include/revolution/BTE/bta/include/bta_sys_ci.h b/include/revolution/BTE/bta/include/bta_sys_ci.h index 52f4b30..4818386 100644 --- a/include/revolution/BTE/bta/include/bta_sys_ci.h +++ b/include/revolution/BTE/bta/include/bta_sys_ci.h @@ -66,3 +66,4 @@ BTA_API void bta_sys_hw_ci_disabled( tBTA_SYS_HW_MODULE module ); #endif #endif + diff --git a/include/revolution/BTE/embdrv/sbc/encoder/include/sbc_enc_func_declare.h b/include/revolution/BTE/embdrv/sbc/encoder/include/sbc_enc_func_declare.h index 45ccf23..2ac34ff 100644 --- a/include/revolution/BTE/embdrv/sbc/encoder/include/sbc_enc_func_declare.h +++ b/include/revolution/BTE/embdrv/sbc/encoder/include/sbc_enc_func_declare.h @@ -54,3 +54,4 @@ extern void EncQuantizer(SBC_ENC_PARAMS *); SINT32 SBC_Multiply_32_16_Simplified(SINT32 s32In2Temp,SINT32 s32In1Temp); #endif #endif + diff --git a/include/revolution/BTE/gki/common/gki.h b/include/revolution/BTE/gki/common/gki.h index c9824ab..5180dcd 100644 --- a/include/revolution/BTE/gki/common/gki.h +++ b/include/revolution/BTE/gki/common/gki.h @@ -491,3 +491,4 @@ GKI_API extern void GKI_print_task(void); #endif + diff --git a/include/revolution/BTE/gki/common/gki_inet.h b/include/revolution/BTE/gki/common/gki_inet.h index 7a9fbdd..6640931 100644 --- a/include/revolution/BTE/gki/common/gki_inet.h +++ b/include/revolution/BTE/gki/common/gki_inet.h @@ -44,3 +44,4 @@ extern UINT8 *ntoh6(UINT8 *p); #endif #endif /* GKI_INET_H */ + diff --git a/include/revolution/BTE/gki/platform/gki_int.h b/include/revolution/BTE/gki/platform/gki_int.h index a971888..df8fb38 100644 --- a/include/revolution/BTE/gki/platform/gki_int.h +++ b/include/revolution/BTE/gki/platform/gki_int.h @@ -136,3 +136,4 @@ GKI_API extern tGKI_CB *gki_cb_ptr; #endif #endif + diff --git a/include/revolution/BTE/hci/include/bt_hci_lib.h b/include/revolution/BTE/hci/include/bt_hci_lib.h index 6904a9b..468e513 100644 --- a/include/revolution/BTE/hci/include/bt_hci_lib.h +++ b/include/revolution/BTE/hci/include/bt_hci_lib.h @@ -199,3 +199,4 @@ typedef struct { extern const bt_hc_interface_t* bt_hc_get_interface(void); #endif /* BT_HCI_LIB_H */ + diff --git a/include/revolution/BTE/hci/include/bt_vendor_lib.h b/include/revolution/BTE/hci/include/bt_vendor_lib.h index 98935d3..054e317 100644 --- a/include/revolution/BTE/hci/include/bt_vendor_lib.h +++ b/include/revolution/BTE/hci/include/bt_vendor_lib.h @@ -320,3 +320,4 @@ typedef struct { extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE; #endif /* BT_VENDOR_LIB_H */ + diff --git a/include/revolution/BTE/hci/include/hci.h b/include/revolution/BTE/hci/include/hci.h index be9b70b..0bfec2b 100644 --- a/include/revolution/BTE/hci/include/hci.h +++ b/include/revolution/BTE/hci/include/hci.h @@ -83,3 +83,4 @@ typedef struct { #endif /* HCI_H */ + diff --git a/include/revolution/BTE/hci/include/userial.h b/include/revolution/BTE/hci/include/userial.h index 534df8c..d3a5480 100644 --- a/include/revolution/BTE/hci/include/userial.h +++ b/include/revolution/BTE/hci/include/userial.h @@ -138,3 +138,4 @@ void userial_close(void); void userial_ioctl(userial_ioctl_op_t op, void *p_data); #endif /* USERIAL_H */ + diff --git a/include/revolution/BTE/hci/include/utils.h b/include/revolution/BTE/hci/include/utils.h index 0aa5592..0f1517c 100644 --- a/include/revolution/BTE/hci/include/utils.h +++ b/include/revolution/BTE/hci/include/utils.h @@ -191,3 +191,4 @@ void utils_lock (void); void utils_unlock (void); #endif /* UTILS_H */ + diff --git a/include/revolution/BTE/include/bt_trace.h b/include/revolution/BTE/include/bt_trace.h index a007210..6c3e7b1 100644 --- a/include/revolution/BTE/include/bt_trace.h +++ b/include/revolution/BTE/include/bt_trace.h @@ -4774,3 +4774,5 @@ extern UINT8 btif_trace_level; #endif /* BT_TRACE_H */ + + diff --git a/include/revolution/BTE/include/gki_target.h b/include/revolution/BTE/include/gki_target.h index 871ec7d..d31744d 100644 --- a/include/revolution/BTE/include/gki_target.h +++ b/include/revolution/BTE/include/gki_target.h @@ -465,4 +465,4 @@ EXPORT_API extern void LogMsg (UINT32 trace_set_mask, const char *fmt_str, ...); } #endif -#endif /* GKI_TARGET_H */ +#endif /* GKI_TARGET_H */ \ No newline at end of file diff --git a/include/revolution/BTE/rvl/uusb_ppc.h b/include/revolution/BTE/rvl/uusb_ppc.h new file mode 100644 index 0000000..75de136 --- /dev/null +++ b/include/revolution/BTE/rvl/uusb_ppc.h @@ -0,0 +1,14 @@ +#ifndef RVL_SDK_BTE_RVL_UUSB_PPC_H +#define RVL_SDK_BTE_RVL_UUSB_PPC_H +#include + +#ifdef __cplusplus +extern "C" { +#endif + +u32 __ntd_get_allocated_mem_size(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/revolution/BTE/stack/avct/avct_int.h b/include/revolution/BTE/stack/avct/avct_int.h index 143dc16..b93c032 100644 --- a/include/revolution/BTE/stack/avct/avct_int.h +++ b/include/revolution/BTE/stack/avct/avct_int.h @@ -235,3 +235,5 @@ extern const tL2CAP_APPL_INFO avct_l2c_br_appl; #endif #endif /* AVCT_INT_H */ + + diff --git a/include/revolution/BTE/stack/avdt/avdt_defs.h b/include/revolution/BTE/stack/avdt/avdt_defs.h index 3772db7..b6dbbc4 100644 --- a/include/revolution/BTE/stack/avdt/avdt_defs.h +++ b/include/revolution/BTE/stack/avdt/avdt_defs.h @@ -200,3 +200,4 @@ *(p)++ = (UINT8) (nosp); #endif /* AVDT_DEFS_H */ + diff --git a/include/revolution/BTE/stack/avrc/avrc_int.h b/include/revolution/BTE/stack/avrc/avrc_int.h index 621cbcf..b6c90b1 100644 --- a/include/revolution/BTE/stack/avrc/avrc_int.h +++ b/include/revolution/BTE/stack/avrc/avrc_int.h @@ -135,3 +135,4 @@ extern BOOLEAN avrc_is_valid_opcode(UINT8 opcode); #endif #endif /* AVRC_INT_H */ + diff --git a/include/revolution/BTE/stack/bnep/bnep_int.h b/include/revolution/BTE/stack/bnep/bnep_int.h index 858e87a..528c809 100644 --- a/include/revolution/BTE/stack/bnep/bnep_int.h +++ b/include/revolution/BTE/stack/bnep/bnep_int.h @@ -248,3 +248,4 @@ extern void bnep_dump_status (void); #endif + diff --git a/include/revolution/BTE/stack/btm/btm_int.h b/include/revolution/BTE/stack/btm/btm_int.h index 98fdbb0..e5f4c15 100644 --- a/include/revolution/BTE/stack/btm/btm_int.h +++ b/include/revolution/BTE/stack/btm/btm_int.h @@ -1111,3 +1111,4 @@ extern void btm_brcm_arc_init (void); #endif #endif + diff --git a/include/revolution/BTE/stack/hid/hidh_int.h b/include/revolution/BTE/stack/hid/hidh_int.h index 49e6086..ad07412 100644 --- a/include/revolution/BTE/stack/hid/hidh_int.h +++ b/include/revolution/BTE/stack/hid/hidh_int.h @@ -91,3 +91,4 @@ HID_API extern tHID_HOST_CTB *hidh_cb_ptr; #endif #endif + diff --git a/include/revolution/BTE/stack/include/avct_api.h b/include/revolution/BTE/stack/include/avct_api.h index ccfcc25..2880011 100644 --- a/include/revolution/BTE/stack/include/avct_api.h +++ b/include/revolution/BTE/stack/include/avct_api.h @@ -276,3 +276,4 @@ AVCT_API extern UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR * #endif /* AVCT_API_H */ + diff --git a/include/revolution/BTE/stack/include/avdtc_api.h b/include/revolution/BTE/stack/include/avdtc_api.h index c8ba488..14a1a21 100644 --- a/include/revolution/BTE/stack/include/avdtc_api.h +++ b/include/revolution/BTE/stack/include/avdtc_api.h @@ -228,3 +228,4 @@ AVDT_API extern void AVDTC_Rej(UINT8 handle, BD_ADDR bd_addr, UINT8 cmd, UINT8 l #endif #endif /* AVDT_CAPI_H */ + diff --git a/include/revolution/BTE/stack/include/bt_types.h b/include/revolution/BTE/stack/include/bt_types.h index 40f9e6a..5809968 100644 --- a/include/revolution/BTE/stack/include/bt_types.h +++ b/include/revolution/BTE/stack/include/bt_types.h @@ -687,3 +687,4 @@ typedef UINT8 tBT_DEVICE_TYPE; typedef void (BT_LOG_FUNC) (int trace_type, const char *fmt_str, ...); #endif + diff --git a/include/revolution/BTE/stack/include/btm_api.h b/include/revolution/BTE/stack/include/btm_api.h index 09bb749..46c0c54 100644 --- a/include/revolution/BTE/stack/include/btm_api.h +++ b/include/revolution/BTE/stack/include/btm_api.h @@ -1,3 +1,15 @@ +/****************************************************************************** + * + * NOTICE OF CHANGES + * 2025/03/13: + * - Restore old function signatures + * + * Compile with REVOLUTION defined to include these changes. + * + ******************************************************************************/ + + + /****************************************************************************** * * Copyright (C) 1999-2012 Broadcom Corporation @@ -2181,8 +2193,11 @@ extern "C" { ** registered. ** *******************************************************************************/ +#ifdef REVOLUTION + BTM_API extern tBTM_STATUS BTM_RegisterForVSEvents (tBTM_VS_EVT_CB *p_cb); +#else BTM_API extern tBTM_STATUS BTM_RegisterForVSEvents (tBTM_VS_EVT_CB *p_cb, BOOLEAN is_register); - +#endif /******************************************************************************* ** diff --git a/include/revolution/BTE/stack/include/dyn_mem.h b/include/revolution/BTE/stack/include/dyn_mem.h index aabdbc8..3ad8361 100644 --- a/include/revolution/BTE/stack/include/dyn_mem.h +++ b/include/revolution/BTE/stack/include/dyn_mem.h @@ -184,3 +184,4 @@ #endif #endif /* #ifdef DYN_MEM_H */ + diff --git a/include/revolution/BTE/stack/include/gap_api.h b/include/revolution/BTE/stack/include/gap_api.h index 1e5401d..a210f69 100644 --- a/include/revolution/BTE/stack/include/gap_api.h +++ b/include/revolution/BTE/stack/include/gap_api.h @@ -800,3 +800,4 @@ GAP_API extern BOOLEAN GAP_BleUpdateReconnectAddr (BD_ADDR peer_bda, #endif #endif /* GAP_API_H */ + diff --git a/include/revolution/BTE/stack/include/hcidefs.h b/include/revolution/BTE/stack/include/hcidefs.h index 1d6863a..1a0b3e8 100644 --- a/include/revolution/BTE/stack/include/hcidefs.h +++ b/include/revolution/BTE/stack/include/hcidefs.h @@ -2230,3 +2230,4 @@ Commands of HCI_GRP_VENDOR_SPECIFIC group for WIDCOMM SW LM Simulator #endif + diff --git a/include/revolution/BTE/stack/include/hcimsgs.h b/include/revolution/BTE/stack/include/hcimsgs.h index 572027e..3a23dbe 100644 --- a/include/revolution/BTE/stack/include/hcimsgs.h +++ b/include/revolution/BTE/stack/include/hcimsgs.h @@ -1328,3 +1328,4 @@ HCI_API extern BOOLEAN btsnd_hcic_ble_read_supported_states (void); #endif #endif + diff --git a/include/revolution/BTE/stack/include/hiddefs.h b/include/revolution/BTE/stack/include/hiddefs.h index c5db44e..e29a4c4 100644 --- a/include/revolution/BTE/stack/include/hiddefs.h +++ b/include/revolution/BTE/stack/include/hiddefs.h @@ -155,3 +155,4 @@ typedef struct sdp_info } tHID_DEV_SDP_INFO; #endif + diff --git a/include/revolution/BTE/stack/include/profiles_api.h b/include/revolution/BTE/stack/include/profiles_api.h index ae9e0aa..eee0dd8 100644 --- a/include/revolution/BTE/stack/include/profiles_api.h +++ b/include/revolution/BTE/stack/include/profiles_api.h @@ -68,3 +68,4 @@ typedef struct } tBT_SECURITY; #endif /* PROFILES_API_H */ + diff --git a/include/revolution/BTE/stack/include/sdpdefs.h b/include/revolution/BTE/stack/include/sdpdefs.h index 7ab1146..c290e03 100644 --- a/include/revolution/BTE/stack/include/sdpdefs.h +++ b/include/revolution/BTE/stack/include/sdpdefs.h @@ -315,3 +315,5 @@ #define ATTR_ID_NETADDRESS_OR_DEVLOCATION 0x0306 #endif + + diff --git a/include/revolution/BTE/stack/pan/pan_int.h b/include/revolution/BTE/stack/pan/pan_int.h index 774e743..4e02236 100644 --- a/include/revolution/BTE/stack/pan/pan_int.h +++ b/include/revolution/BTE/stack/pan/pan_int.h @@ -155,3 +155,4 @@ extern void pan_dump_status (void); #endif #endif + diff --git a/include/revolution/BTE/stack/rfcomm/rfc_int.h b/include/revolution/BTE/stack/rfcomm/rfc_int.h index db70528..83a63e3 100644 --- a/include/revolution/BTE/stack/rfcomm/rfc_int.h +++ b/include/revolution/BTE/stack/rfcomm/rfc_int.h @@ -384,3 +384,4 @@ extern void PORT_LineStatusInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT8 line_status); #endif #endif + diff --git a/include/revolution/BTE/stack/sdp/sdpint.h b/include/revolution/BTE/stack/sdp/sdpint.h index f899c85..b300664 100644 --- a/include/revolution/BTE/stack/sdp/sdpint.h +++ b/include/revolution/BTE/stack/sdp/sdpint.h @@ -326,3 +326,4 @@ extern void sdp_disc_server_rsp (tCONN_CB *p_ccb, BT_HDR *p_msg); #endif + diff --git a/include/revolution/BTE/stack/smp/smp_int.h b/include/revolution/BTE/stack/smp/smp_int.h index a30b3b4..9eb2f10 100644 --- a/include/revolution/BTE/stack/smp/smp_int.h +++ b/include/revolution/BTE/stack/smp/smp_int.h @@ -312,3 +312,4 @@ extern void smp_set_state(tSMP_STATE state); extern tSMP_STATE smp_get_state(void); #endif /* SMP_INT_H */ + diff --git a/include/revolution/BTE/udrv/include/uipc.h b/include/revolution/BTE/udrv/include/uipc.h index 5f9bbf9..37d508c 100644 --- a/include/revolution/BTE/udrv/include/uipc.h +++ b/include/revolution/BTE/udrv/include/uipc.h @@ -145,3 +145,5 @@ UDRV_API extern BOOLEAN UIPC_Ioctl(tUIPC_CH_ID ch_id, UINT32 request, void *para #endif /* UIPC_H */ + + diff --git a/include/revolution/CNT/cnt.h b/include/revolution/CNT/cnt.h index 90b25eb..0f88f9d 100644 --- a/include/revolution/CNT/cnt.h +++ b/include/revolution/CNT/cnt.h @@ -3,6 +3,7 @@ #include #include + #ifdef __cplusplus extern "C" { #endif @@ -19,6 +20,10 @@ typedef struct CNTFileInfo { u32 position; // at 0xC } CNTFileInfo; +typedef enum { + CNT_RESULT_OK = 0, +} CNTResult; + s32 contentFastOpenNAND(CNTHandle* handle, s32 entrynum, CNTFileInfo* info); s32 contentConvertPathToEntrynumNAND(CNTHandle* handle, const char* path); u32 contentGetLengthNAND(const CNTFileInfo* info); diff --git a/include/revolution/DVD.h b/include/revolution/DVD.h index 4d6f756..4027201 100644 --- a/include/revolution/DVD.h +++ b/include/revolution/DVD.h @@ -9,9 +9,9 @@ extern "C" { #endif #include +#include #include #include -#include #include #include #include diff --git a/include/revolution/DVD/dvd.h b/include/revolution/DVD/dvd.h index 1e86e5c..c24783d 100644 --- a/include/revolution/DVD/dvd.h +++ b/include/revolution/DVD/dvd.h @@ -17,9 +17,9 @@ typedef struct OSAlarm OSAlarm; typedef enum { DVD_RESULT_COVER_CLOSED = -4, DVD_RESULT_CANCELED, - DVD_RESULT_M2, - DVD_RESULT_FATAL, - DVD_RESULT_OK, + DVD_RESULT_IGNORED, + DVD_RESULT_FATAL_ERROR, + DVD_RESULT_GOOD, } DVDResult; typedef enum { diff --git a/include/revolution/DVD/dvdfs.h b/include/revolution/DVD/dvdfs.h index 5bd82bc..7175a4e 100644 --- a/include/revolution/DVD/dvdfs.h +++ b/include/revolution/DVD/dvdfs.h @@ -1,10 +1,8 @@ #ifndef RVL_SDK_DVD_FS_H #define RVL_SDK_DVD_FS_H -#include - #include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/DVD/dvdidutils.h b/include/revolution/DVD/dvdidutils.h index 833cc41..c917ca8 100644 --- a/include/revolution/DVD/dvdidutils.h +++ b/include/revolution/DVD/dvdidutils.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_DVD_ID_UTILS_H #define RVL_SDK_DVD_ID_UTILS_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/DVD/dvdqueue.h b/include/revolution/DVD/dvdqueue.h index f62a911..d06f2ba 100644 --- a/include/revolution/DVD/dvdqueue.h +++ b/include/revolution/DVD/dvdqueue.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_DVD_QUEUE_H #define RVL_SDK_DVD_QUEUE_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/ESP/esp.h b/include/revolution/ESP/esp.h index 60e3eb2..ea3eb8d 100644 --- a/include/revolution/ESP/esp.h +++ b/include/revolution/ESP/esp.h @@ -1,9 +1,8 @@ #ifndef RVL_SDK_ESP_H #define RVL_SDK_ESP_H -#include - #include #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/EXI/EXIBios.h b/include/revolution/EXI/EXIBios.h index a3f23a6..18889e6 100644 --- a/include/revolution/EXI/EXIBios.h +++ b/include/revolution/EXI/EXIBios.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_EXI_BIOS_H #define RVL_SDK_EXI_BIOS_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/EXI/EXICommon.h b/include/revolution/EXI/EXICommon.h index cd4799a..10ed342 100644 --- a/include/revolution/EXI/EXICommon.h +++ b/include/revolution/EXI/EXICommon.h @@ -51,6 +51,10 @@ typedef void (*EXICallback)(EXIChannel chan, OSContext* ctx); extern const u32 __EXIFreq; +#if defined(LIBKIWI_PRECOMPILE) +#define static inline +#endif + static u32 __EXISwap32(u32 val) { return val >> 24 & 0x000000FF | val >> 8 & 0x0000FF00 | val << 8 & 0x00FF0000 | val << 24 & 0xFF000000; @@ -58,6 +62,10 @@ static u32 __EXISwap32(u32 val) { BOOL EXIWriteReg(EXIChannel chan, u32 dev, u32 cmd, const void* buf, s32 len); +#if defined(LIBKIWI_PRECOMPILE) +#undef static +#endif + #ifdef __cplusplus } #endif diff --git a/include/revolution/EXI/EXIHardware.h b/include/revolution/EXI/EXIHardware.h index 2298c1d..29e09e0 100644 --- a/include/revolution/EXI/EXIHardware.h +++ b/include/revolution/EXI/EXIHardware.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_EXI_HARDWARE_H #define RVL_SDK_EXI_HARDWARE_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/EXI/EXIUart.h b/include/revolution/EXI/EXIUart.h index 714160d..27b50dc 100644 --- a/include/revolution/EXI/EXIUart.h +++ b/include/revolution/EXI/EXIUart.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_EXI_UART_H #define RVL_SDK_EXI_UART_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/FS/fs.h b/include/revolution/FS/fs.h index b3ab35b..e614210 100644 --- a/include/revolution/FS/fs.h +++ b/include/revolution/FS/fs.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_FS_H #define RVL_SDK_FS_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/GX/GXAttr.h b/include/revolution/GX/GXAttr.h index 6d5026a..035d0c7 100644 --- a/include/revolution/GX/GXAttr.h +++ b/include/revolution/GX/GXAttr.h @@ -47,11 +47,19 @@ void __GXSetVCD(void); void __GXCalculateVLim(void); void __GXSetVAT(void); +#if defined(LIBKIWI_PRECOMPILE) +#define static inline +#endif + static void GXSetTexCoordGen(GXTexCoordID id, GXTexGenType type, GXTexGenSrc src, u32 texMtxIdx) { GXSetTexCoordGen2(id, type, src, texMtxIdx, FALSE, GX_PTIDENTITY); } +#if defined(LIBKIWI_PRECOMPILE) +#undef static +#endif + #ifdef __cplusplus } #endif diff --git a/include/revolution/GX/GXBump.h b/include/revolution/GX/GXBump.h index 9168fa4..e1b6106 100644 --- a/include/revolution/GX/GXBump.h +++ b/include/revolution/GX/GXBump.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_GX_BUMP_H #define RVL_SDK_GX_BUMP_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/GX/GXDisplayList.h b/include/revolution/GX/GXDisplayList.h index f4355d4..47dc1c0 100644 --- a/include/revolution/GX/GXDisplayList.h +++ b/include/revolution/GX/GXDisplayList.h @@ -11,12 +11,20 @@ void GXBeginDisplayList(void* list, u32 size); u32 GXEndDisplayList(void); void GXCallDisplayList(void* list, u32 size); +#if defined(LIBKIWI_PRECOMPILE) +#define static inline +#endif + static void GXFastCallDisplayList(void* list, u32 size) { WGPIPE.c = GX_FIFO_CMD_CALL_DL; WGPIPE.p = list; WGPIPE.ui = size; } +#if defined(LIBKIWI_PRECOMPILE) +#undef static +#endif + #ifdef __cplusplus } #endif diff --git a/include/revolution/GX/GXFifo.h b/include/revolution/GX/GXFifo.h index 233e427..8fc5ee2 100644 --- a/include/revolution/GX/GXFifo.h +++ b/include/revolution/GX/GXFifo.h @@ -3,20 +3,31 @@ #include #include + +#include #ifdef __cplusplus extern "C" { #endif GX_PUBLIC_STRUCT_DECL(GXFifoObj, 128); -void GXGetGPStatus(u8*, u8*, u8*, u8*, u8*); +void GXGetGPStatus(GXBool* overhi, GXBool* underlow, GXBool* readIdle, + GXBool* cmdIdle, GXBool* brkpt); void GXSetCPUFifo(GXFifoObj*); BOOL GXGetCPUFifo(GXFifoObj*); +BOOL GXGetGPFifo(GXFifoObj*); + +void GXGetFifoPtrs(const GXFifoObj*, void** readPtr, void** writePtr); u32 GXGetFifoCount(GXFifoObj*); u8 GXGetFifoWrap(GXFifoObj*); +void GXEnableBreakPt(void* writePtr); +void GXDisableBreakPt(void); + +OSThread* GXGetCurrentGXThread(void); + #ifdef __cplusplus } #endif diff --git a/include/revolution/GX/GXFrameBuf.h b/include/revolution/GX/GXFrameBuf.h index 4fd769c..461afcb 100644 --- a/include/revolution/GX/GXFrameBuf.h +++ b/include/revolution/GX/GXFrameBuf.h @@ -5,20 +5,22 @@ extern "C" { #endif +#define GX_VFILTER_SZ 7 + typedef struct _GXRenderModeObj { - u32 tvInfo; // at 0x0 - u16 fbWidth; // at 0x4 - u16 efbHeight; // at 0x6 - u16 xfbHeight; // at 0x8 - u16 viXOrigin; // at 0xA - u16 viYOrigin; // at 0xC - u16 viWidth; // at 0xE - u16 viHeight; // at 0x10 - u32 xfbMode; // at 0x14 - u8 field_rendering; // at 0x18 - u8 aa; // at 0x19 - u8 sample_pattern[12][2]; // at 0x1A - u8 vfilter[7]; // at 0x32 + u32 tvInfo; // at 0x0 + u16 fbWidth; // at 0x4 + u16 efbHeight; // at 0x6 + u16 xfbHeight; // at 0x8 + u16 viXOrigin; // at 0xA + u16 viYOrigin; // at 0xC + u16 viWidth; // at 0xE + u16 viHeight; // at 0x10 + u32 xfbMode; // at 0x14 + GXBool field_rendering; // at 0x18 + GXBool aa; // at 0x19 + u8 sample_pattern[12][2]; // at 0x1A + u8 vfilter[GX_VFILTER_SZ]; // at 0x32 } GXRenderModeObj; extern GXRenderModeObj GXNtsc480IntDf; @@ -26,13 +28,21 @@ extern GXRenderModeObj GXPal528IntDf; extern GXRenderModeObj GXEurgb60Hz480IntDf; extern GXRenderModeObj GXMpal480IntDf; +void GXSetDispCopySrc(u16 x, u16 y, u16 w, u16 h); void GXSetTexCopySrc(u16 x, u16 y, u16 w, u16 h); + +void GXSetDispCopyDst(u16 w, u16 numXfbLines); void GXSetTexCopyDst(u16 w, u16 h, GXTexFmt fmt, GXBool mipmap); void GXSetCopyClamp(GXCopyClamp clamp); +u32 GXGetNumXfbLines(u16 efbHeight, f32 scaleY); +f32 GXGetYScaleFactor(u16 efbHeight, u16 xfbHeight); +void GXSetDispCopyYScale(f32 scaleY); + void GXSetCopyClear(GXColor color, u32 z); -void GXSetCopyFilter(GXBool, u8 sample_pattern[12][2], GXBool, u8 vfilter[7]); +void GXSetCopyFilter(GXBool, const u8 sample_pattern[12][2], GXBool, + const u8 vfilter[GX_VFILTER_SZ]); void GXCopyDisp(void*, GXBool); void GXCopyTex(void*, GXBool); diff --git a/include/revolution/GX/GXGeometry.h b/include/revolution/GX/GXGeometry.h index 6f08eae..a6460ec 100644 --- a/include/revolution/GX/GXGeometry.h +++ b/include/revolution/GX/GXGeometry.h @@ -7,6 +7,10 @@ extern "C" { #endif +#if defined(LIBKIWI_PRECOMPILE) +#define static inline +#endif + void GXBegin(GXPrimitive prim, GXVtxFmt fmt, u16 verts); static void GXEnd(void) {} @@ -21,6 +25,10 @@ void __GXSetDirtyState(void); void __GXSendFlushPrim(void); void __GXSetGenMode(void); +#if defined(LIBKIWI_PRECOMPILE) +#undef static +#endif + #ifdef __cplusplus } #endif diff --git a/include/revolution/GX/GXHardware.h b/include/revolution/GX/GXHardware.h index 071c37a..60a1725 100644 --- a/include/revolution/GX/GXHardware.h +++ b/include/revolution/GX/GXHardware.h @@ -61,9 +61,23 @@ typedef enum { GX_FIFO_CMD_LOAD_INDX_D = 0x38, GX_FIFO_CMD_CALL_DL = 0x40, - GX_FIFO_CMD_INVAL_VTX = 0x48 + GX_FIFO_CMD_INVAL_VTX = 0x48, + + GX_FIFO_CMD_DRAW_POINTS = GX_POINTS, + GX_FIFO_CMD_DRAW_LINES = GX_LINES, + GX_FIFO_CMD_DRAW_LINESTRIP = GX_LINESTRIP, + GX_FIFO_CMD_DRAW_TRIANGLES = GX_TRIANGLES, + GX_FIFO_CMD_DRAW_TRIANGLESTRIP = GX_TRIANGLESTRIP, + GX_FIFO_CMD_DRAW_TRIANGLEFAN = GX_TRIANGLEFAN, + GX_FIFO_CMD_DRAW_QUADS = GX_QUADS, } GXFifoCmd; +/** + * FIFO command sizes + */ +#define GX_FIFO_CMD_LOAD_INDX_SIZE 5 +#define GX_FIFO_CMD_DRAW_SIZE 3 + #define __GX_FIFO_SET_LOAD_INDX_DST(reg, x) ((reg) = GX_BITSET(reg, 20, 12, x)) #define __GX_FIFO_SET_LOAD_INDX_NELEM(reg, x) ((reg) = GX_BITSET(reg, 16, 4, x)) #define __GX_FIFO_SET_LOAD_INDX_INDEX(reg, x) ((reg) = GX_BITSET(reg, 0, 16, x)) diff --git a/include/revolution/GX/GXHardwareBP.h b/include/revolution/GX/GXHardwareBP.h index 55c100c..5d623ff 100644 --- a/include/revolution/GX/GXHardwareBP.h +++ b/include/revolution/GX/GXHardwareBP.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_GX_HARDWARE_BP_H #define RVL_SDK_GX_HARDWARE_BP_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif @@ -237,1899 +236,1672 @@ typedef enum { * BP register 0x0 - GenMode *****************************************************************************/ // NUMTEX [28:31] (4) - Active texture count -/* start bit */ #define GX_BP_GENMODE_NUMTEX_B 28 -/* end bit */ #define GX_BP_GENMODE_NUMTEX_E 31 -/* bit size */ #define GX_BP_GENMODE_NUMTEX_SZ 4 + /* start bit */ #define GX_BP_GENMODE_NUMTEX_B 28 + /* end bit */ #define GX_BP_GENMODE_NUMTEX_E 31 + /* bit size */ #define GX_BP_GENMODE_NUMTEX_SZ 4 -/* raw mask */ #define GX_BP_GENMODE_NUMTEX_MASK (((1 << 4) - 1) << 31 - 31) -/* local mask */ #define GX_BP_GENMODE_NUMTEX_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_GENMODE_NUMTEX_SHIFT 0 + /* raw mask */ #define GX_BP_GENMODE_NUMTEX_MASK (((1 << 4) - 1) << 31 - 31) + /* local mask */ #define GX_BP_GENMODE_NUMTEX_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_GENMODE_NUMTEX_SHIFT 0 -/* get value */ #define GX_BP_GET_GENMODE_NUMTEX(reg) GX_BITGET((reg), 28, 4) -/* set value */ #define GX_BP_SET_GENMODE_NUMTEX(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 4, x)) + /* get value */ #define GX_BP_GET_GENMODE_NUMTEX(reg) GX_BITGET((reg), 28, 4) + /* set value */ #define GX_BP_SET_GENMODE_NUMTEX(reg, x) ((reg) = GX_BITSET((reg), 28, 4, x)) // NUMCOLORS [25:27] (3) - Color/channel count -/* start bit */ #define GX_BP_GENMODE_NUMCOLORS_B 25 -/* end bit */ #define GX_BP_GENMODE_NUMCOLORS_E 27 -/* bit size */ #define GX_BP_GENMODE_NUMCOLORS_SZ 3 + /* start bit */ #define GX_BP_GENMODE_NUMCOLORS_B 25 + /* end bit */ #define GX_BP_GENMODE_NUMCOLORS_E 27 + /* bit size */ #define GX_BP_GENMODE_NUMCOLORS_SZ 3 -/* raw mask */ #define GX_BP_GENMODE_NUMCOLORS_MASK \ - (((1 << 3) - 1) << 31 - 27) -/* local mask */ #define GX_BP_GENMODE_NUMCOLORS_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_GENMODE_NUMCOLORS_SHIFT 4 + /* raw mask */ #define GX_BP_GENMODE_NUMCOLORS_MASK (((1 << 3) - 1) << 31 - 27) + /* local mask */ #define GX_BP_GENMODE_NUMCOLORS_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_GENMODE_NUMCOLORS_SHIFT 4 -/* get value */ #define GX_BP_GET_GENMODE_NUMCOLORS(reg) \ - GX_BITGET((reg), 25, 3) -/* set value */ #define GX_BP_SET_GENMODE_NUMCOLORS(reg, x) \ - ((reg) = GX_BITSET((reg), 25, 3, x)) + /* get value */ #define GX_BP_GET_GENMODE_NUMCOLORS(reg) GX_BITGET((reg), 25, 3) + /* set value */ #define GX_BP_SET_GENMODE_NUMCOLORS(reg, x) ((reg) = GX_BITSET((reg), 25, 3, x)) // MULTISAMPLE [22:22] (1) -/* start bit */ #define GX_BP_GENMODE_MULTISAMPLE_B 22 -/* end bit */ #define GX_BP_GENMODE_MULTISAMPLE_E 22 -/* bit size */ #define GX_BP_GENMODE_MULTISAMPLE_SZ 1 + /* start bit */ #define GX_BP_GENMODE_MULTISAMPLE_B 22 + /* end bit */ #define GX_BP_GENMODE_MULTISAMPLE_E 22 + /* bit size */ #define GX_BP_GENMODE_MULTISAMPLE_SZ 1 -/* raw mask */ #define GX_BP_GENMODE_MULTISAMPLE_MASK \ - (((1 << 1) - 1) << 31 - 22) -/* local mask */ #define GX_BP_GENMODE_MULTISAMPLE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_GENMODE_MULTISAMPLE_SHIFT 9 + /* raw mask */ #define GX_BP_GENMODE_MULTISAMPLE_MASK (((1 << 1) - 1) << 31 - 22) + /* local mask */ #define GX_BP_GENMODE_MULTISAMPLE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_GENMODE_MULTISAMPLE_SHIFT 9 -/* get value */ #define GX_BP_GET_GENMODE_MULTISAMPLE(reg) \ - GX_BITGET((reg), 22, 1) -/* set value */ #define GX_BP_SET_GENMODE_MULTISAMPLE(reg, x) \ - ((reg) = GX_BITSET((reg), 22, 1, x)) + /* get value */ #define GX_BP_GET_GENMODE_MULTISAMPLE(reg) GX_BITGET((reg), 22, 1) + /* set value */ #define GX_BP_SET_GENMODE_MULTISAMPLE(reg, x) ((reg) = GX_BITSET((reg), 22, 1, x)) // NUMTEVSTAGES [18:21] (4) -/* start bit */ #define GX_BP_GENMODE_NUMTEVSTAGES_B 18 -/* end bit */ #define GX_BP_GENMODE_NUMTEVSTAGES_E 21 -/* bit size */ #define GX_BP_GENMODE_NUMTEVSTAGES_SZ 4 + /* start bit */ #define GX_BP_GENMODE_NUMTEVSTAGES_B 18 + /* end bit */ #define GX_BP_GENMODE_NUMTEVSTAGES_E 21 + /* bit size */ #define GX_BP_GENMODE_NUMTEVSTAGES_SZ 4 -/* raw mask */ #define GX_BP_GENMODE_NUMTEVSTAGES_MASK \ - (((1 << 4) - 1) << 31 - 21) -/* local mask */ #define GX_BP_GENMODE_NUMTEVSTAGES_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_GENMODE_NUMTEVSTAGES_SHIFT 10 + /* raw mask */ #define GX_BP_GENMODE_NUMTEVSTAGES_MASK (((1 << 4) - 1) << 31 - 21) + /* local mask */ #define GX_BP_GENMODE_NUMTEVSTAGES_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_GENMODE_NUMTEVSTAGES_SHIFT 10 -/* get value */ #define GX_BP_GET_GENMODE_NUMTEVSTAGES(reg) \ - GX_BITGET((reg), 18, 4) -/* set value */ #define GX_BP_SET_GENMODE_NUMTEVSTAGES(reg, x) \ - ((reg) = GX_BITSET((reg), 18, 4, x)) + /* get value */ #define GX_BP_GET_GENMODE_NUMTEVSTAGES(reg) GX_BITGET((reg), 18, 4) + /* set value */ #define GX_BP_SET_GENMODE_NUMTEVSTAGES(reg, x) ((reg) = GX_BITSET((reg), 18, 4, x)) // CULLMODE [16:17] (2) -/* start bit */ #define GX_BP_GENMODE_CULLMODE_B 16 -/* end bit */ #define GX_BP_GENMODE_CULLMODE_E 17 -/* bit size */ #define GX_BP_GENMODE_CULLMODE_SZ 2 + /* start bit */ #define GX_BP_GENMODE_CULLMODE_B 16 + /* end bit */ #define GX_BP_GENMODE_CULLMODE_E 17 + /* bit size */ #define GX_BP_GENMODE_CULLMODE_SZ 2 -/* raw mask */ #define GX_BP_GENMODE_CULLMODE_MASK (((1 << 2) - 1) << 31 - 17) -/* local mask */ #define GX_BP_GENMODE_CULLMODE_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_GENMODE_CULLMODE_SHIFT 14 + /* raw mask */ #define GX_BP_GENMODE_CULLMODE_MASK (((1 << 2) - 1) << 31 - 17) + /* local mask */ #define GX_BP_GENMODE_CULLMODE_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_GENMODE_CULLMODE_SHIFT 14 -/* get value */ #define GX_BP_GET_GENMODE_CULLMODE(reg) GX_BITGET((reg), 16, 2) -/* set value */ #define GX_BP_SET_GENMODE_CULLMODE(reg, x) \ - ((reg) = GX_BITSET((reg), 16, 2, x)) + /* get value */ #define GX_BP_GET_GENMODE_CULLMODE(reg) GX_BITGET((reg), 16, 2) + /* set value */ #define GX_BP_SET_GENMODE_CULLMODE(reg, x) ((reg) = GX_BITSET((reg), 16, 2, x)) // NUMINDSTAGES [13:15] (3) -/* start bit */ #define GX_BP_GENMODE_NUMINDSTAGES_B 13 -/* end bit */ #define GX_BP_GENMODE_NUMINDSTAGES_E 15 -/* bit size */ #define GX_BP_GENMODE_NUMINDSTAGES_SZ 3 + /* start bit */ #define GX_BP_GENMODE_NUMINDSTAGES_B 13 + /* end bit */ #define GX_BP_GENMODE_NUMINDSTAGES_E 15 + /* bit size */ #define GX_BP_GENMODE_NUMINDSTAGES_SZ 3 -/* raw mask */ #define GX_BP_GENMODE_NUMINDSTAGES_MASK \ - (((1 << 3) - 1) << 31 - 15) -/* local mask */ #define GX_BP_GENMODE_NUMINDSTAGES_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_GENMODE_NUMINDSTAGES_SHIFT 16 + /* raw mask */ #define GX_BP_GENMODE_NUMINDSTAGES_MASK (((1 << 3) - 1) << 31 - 15) + /* local mask */ #define GX_BP_GENMODE_NUMINDSTAGES_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_GENMODE_NUMINDSTAGES_SHIFT 16 -/* get value */ #define GX_BP_GET_GENMODE_NUMINDSTAGES(reg) \ - GX_BITGET((reg), 13, 3) -/* set value */ #define GX_BP_SET_GENMODE_NUMINDSTAGES(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 3, x)) + /* get value */ #define GX_BP_GET_GENMODE_NUMINDSTAGES(reg) GX_BITGET((reg), 13, 3) + /* set value */ #define GX_BP_SET_GENMODE_NUMINDSTAGES(reg, x) ((reg) = GX_BITSET((reg), 13, 3, x)) // COPLANAR [12:12] (1) - Toggle co-planar ("Z freeze" according to Dolphin) -/* start bit */ #define GX_BP_GENMODE_COPLANAR_B 12 -/* end bit */ #define GX_BP_GENMODE_COPLANAR_E 12 -/* bit size */ #define GX_BP_GENMODE_COPLANAR_SZ 1 + /* start bit */ #define GX_BP_GENMODE_COPLANAR_B 12 + /* end bit */ #define GX_BP_GENMODE_COPLANAR_E 12 + /* bit size */ #define GX_BP_GENMODE_COPLANAR_SZ 1 + + /* raw mask */ #define GX_BP_GENMODE_COPLANAR_MASK (((1 << 1) - 1) << 31 - 12) + /* local mask */ #define GX_BP_GENMODE_COPLANAR_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_GENMODE_COPLANAR_SHIFT 19 -/* raw mask */ #define GX_BP_GENMODE_COPLANAR_MASK (((1 << 1) - 1) << 31 - 12) -/* local mask */ #define GX_BP_GENMODE_COPLANAR_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_GENMODE_COPLANAR_SHIFT 19 + /* get value */ #define GX_BP_GET_GENMODE_COPLANAR(reg) GX_BITGET((reg), 12, 1) + /* set value */ #define GX_BP_SET_GENMODE_COPLANAR(reg, x) ((reg) = GX_BITSET((reg), 12, 1, x)) -/* get value */ #define GX_BP_GET_GENMODE_COPLANAR(reg) GX_BITGET((reg), 12, 1) -/* set value */ #define GX_BP_SET_GENMODE_COPLANAR(reg, x) \ - ((reg) = GX_BITSET((reg), 12, 1, x)) /****************************************************************************** * BP structure - IndMtxA *****************************************************************************/ // M00 [21:31] (11) - Texture offset matrix #0 [0][0] -/* start bit */ #define GX_BP_INDMTXA_M00_B 21 -/* end bit */ #define GX_BP_INDMTXA_M00_E 31 -/* bit size */ #define GX_BP_INDMTXA_M00_SZ 11 + /* start bit */ #define GX_BP_INDMTXA_M00_B 21 + /* end bit */ #define GX_BP_INDMTXA_M00_E 31 + /* bit size */ #define GX_BP_INDMTXA_M00_SZ 11 -/* raw mask */ #define GX_BP_INDMTXA_M00_MASK (((1 << 11) - 1) << 31 - 31) -/* local mask */ #define GX_BP_INDMTXA_M00_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_INDMTXA_M00_SHIFT 0 + /* raw mask */ #define GX_BP_INDMTXA_M00_MASK (((1 << 11) - 1) << 31 - 31) + /* local mask */ #define GX_BP_INDMTXA_M00_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_INDMTXA_M00_SHIFT 0 -/* get value */ #define GX_BP_GET_INDMTXA_M00(reg) GX_BITGET((reg), 21, 11) -/* set value */ #define GX_BP_SET_INDMTXA_M00(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 11, x)) + /* get value */ #define GX_BP_GET_INDMTXA_M00(reg) GX_BITGET((reg), 21, 11) + /* set value */ #define GX_BP_SET_INDMTXA_M00(reg, x) ((reg) = GX_BITSET((reg), 21, 11, x)) // M10 [10:20] (11) - Texture offset matrix #0 [1][0] -/* start bit */ #define GX_BP_INDMTXA_M10_B 10 -/* end bit */ #define GX_BP_INDMTXA_M10_E 20 -/* bit size */ #define GX_BP_INDMTXA_M10_SZ 11 + /* start bit */ #define GX_BP_INDMTXA_M10_B 10 + /* end bit */ #define GX_BP_INDMTXA_M10_E 20 + /* bit size */ #define GX_BP_INDMTXA_M10_SZ 11 -/* raw mask */ #define GX_BP_INDMTXA_M10_MASK (((1 << 11) - 1) << 31 - 20) -/* local mask */ #define GX_BP_INDMTXA_M10_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_INDMTXA_M10_SHIFT 11 + /* raw mask */ #define GX_BP_INDMTXA_M10_MASK (((1 << 11) - 1) << 31 - 20) + /* local mask */ #define GX_BP_INDMTXA_M10_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_INDMTXA_M10_SHIFT 11 -/* get value */ #define GX_BP_GET_INDMTXA_M10(reg) GX_BITGET((reg), 10, 11) -/* set value */ #define GX_BP_SET_INDMTXA_M10(reg, x) \ - ((reg) = GX_BITSET((reg), 10, 11, x)) + /* get value */ #define GX_BP_GET_INDMTXA_M10(reg) GX_BITGET((reg), 10, 11) + /* set value */ #define GX_BP_SET_INDMTXA_M10(reg, x) ((reg) = GX_BITSET((reg), 10, 11, x)) // EXP [8:9] (2) - Bits 0-1 of scaling exponent #0 (2^x) -/* start bit */ #define GX_BP_INDMTXA_EXP_B 8 -/* end bit */ #define GX_BP_INDMTXA_EXP_E 9 -/* bit size */ #define GX_BP_INDMTXA_EXP_SZ 2 + /* start bit */ #define GX_BP_INDMTXA_EXP_B 8 + /* end bit */ #define GX_BP_INDMTXA_EXP_E 9 + /* bit size */ #define GX_BP_INDMTXA_EXP_SZ 2 -/* raw mask */ #define GX_BP_INDMTXA_EXP_MASK (((1 << 2) - 1) << 31 - 9) -/* local mask */ #define GX_BP_INDMTXA_EXP_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_INDMTXA_EXP_SHIFT 22 + /* raw mask */ #define GX_BP_INDMTXA_EXP_MASK (((1 << 2) - 1) << 31 - 9) + /* local mask */ #define GX_BP_INDMTXA_EXP_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_INDMTXA_EXP_SHIFT 22 + + /* get value */ #define GX_BP_GET_INDMTXA_EXP(reg) GX_BITGET((reg), 8, 2) + /* set value */ #define GX_BP_SET_INDMTXA_EXP(reg, x) ((reg) = GX_BITSET((reg), 8, 2, x)) -/* get value */ #define GX_BP_GET_INDMTXA_EXP(reg) GX_BITGET((reg), 8, 2) -/* set value */ #define GX_BP_SET_INDMTXA_EXP(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 2, x)) /****************************************************************************** * BP structure - IndMtxB *****************************************************************************/ // M01 [21:31] (11) - Texture offset matrix #0 [0][1] -/* start bit */ #define GX_BP_INDMTXB_M01_B 21 -/* end bit */ #define GX_BP_INDMTXB_M01_E 31 -/* bit size */ #define GX_BP_INDMTXB_M01_SZ 11 + /* start bit */ #define GX_BP_INDMTXB_M01_B 21 + /* end bit */ #define GX_BP_INDMTXB_M01_E 31 + /* bit size */ #define GX_BP_INDMTXB_M01_SZ 11 -/* raw mask */ #define GX_BP_INDMTXB_M01_MASK (((1 << 11) - 1) << 31 - 31) -/* local mask */ #define GX_BP_INDMTXB_M01_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_INDMTXB_M01_SHIFT 0 + /* raw mask */ #define GX_BP_INDMTXB_M01_MASK (((1 << 11) - 1) << 31 - 31) + /* local mask */ #define GX_BP_INDMTXB_M01_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_INDMTXB_M01_SHIFT 0 -/* get value */ #define GX_BP_GET_INDMTXB_M01(reg) GX_BITGET((reg), 21, 11) -/* set value */ #define GX_BP_SET_INDMTXB_M01(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 11, x)) + /* get value */ #define GX_BP_GET_INDMTXB_M01(reg) GX_BITGET((reg), 21, 11) + /* set value */ #define GX_BP_SET_INDMTXB_M01(reg, x) ((reg) = GX_BITSET((reg), 21, 11, x)) // M11 [10:20] (11) - Texture offset matrix #0 [1][1] -/* start bit */ #define GX_BP_INDMTXB_M11_B 10 -/* end bit */ #define GX_BP_INDMTXB_M11_E 20 -/* bit size */ #define GX_BP_INDMTXB_M11_SZ 11 + /* start bit */ #define GX_BP_INDMTXB_M11_B 10 + /* end bit */ #define GX_BP_INDMTXB_M11_E 20 + /* bit size */ #define GX_BP_INDMTXB_M11_SZ 11 -/* raw mask */ #define GX_BP_INDMTXB_M11_MASK (((1 << 11) - 1) << 31 - 20) -/* local mask */ #define GX_BP_INDMTXB_M11_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_INDMTXB_M11_SHIFT 11 + /* raw mask */ #define GX_BP_INDMTXB_M11_MASK (((1 << 11) - 1) << 31 - 20) + /* local mask */ #define GX_BP_INDMTXB_M11_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_INDMTXB_M11_SHIFT 11 -/* get value */ #define GX_BP_GET_INDMTXB_M11(reg) GX_BITGET((reg), 10, 11) -/* set value */ #define GX_BP_SET_INDMTXB_M11(reg, x) \ - ((reg) = GX_BITSET((reg), 10, 11, x)) + /* get value */ #define GX_BP_GET_INDMTXB_M11(reg) GX_BITGET((reg), 10, 11) + /* set value */ #define GX_BP_SET_INDMTXB_M11(reg, x) ((reg) = GX_BITSET((reg), 10, 11, x)) // EXP [8:9] (2) - Bits 2-3 of scaling exponent #0 (2^x) -/* start bit */ #define GX_BP_INDMTXB_EXP_B 8 -/* end bit */ #define GX_BP_INDMTXB_EXP_E 9 -/* bit size */ #define GX_BP_INDMTXB_EXP_SZ 2 + /* start bit */ #define GX_BP_INDMTXB_EXP_B 8 + /* end bit */ #define GX_BP_INDMTXB_EXP_E 9 + /* bit size */ #define GX_BP_INDMTXB_EXP_SZ 2 + + /* raw mask */ #define GX_BP_INDMTXB_EXP_MASK (((1 << 2) - 1) << 31 - 9) + /* local mask */ #define GX_BP_INDMTXB_EXP_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_INDMTXB_EXP_SHIFT 22 -/* raw mask */ #define GX_BP_INDMTXB_EXP_MASK (((1 << 2) - 1) << 31 - 9) -/* local mask */ #define GX_BP_INDMTXB_EXP_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_INDMTXB_EXP_SHIFT 22 + /* get value */ #define GX_BP_GET_INDMTXB_EXP(reg) GX_BITGET((reg), 8, 2) + /* set value */ #define GX_BP_SET_INDMTXB_EXP(reg, x) ((reg) = GX_BITSET((reg), 8, 2, x)) -/* get value */ #define GX_BP_GET_INDMTXB_EXP(reg) GX_BITGET((reg), 8, 2) -/* set value */ #define GX_BP_SET_INDMTXB_EXP(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 2, x)) /****************************************************************************** * BP structure - IndMtxC *****************************************************************************/ // M02 [21:31] (11) - Texture offset matrix #0 [0][2] -/* start bit */ #define GX_BP_INDMTXC_M02_B 21 -/* end bit */ #define GX_BP_INDMTXC_M02_E 31 -/* bit size */ #define GX_BP_INDMTXC_M02_SZ 11 + /* start bit */ #define GX_BP_INDMTXC_M02_B 21 + /* end bit */ #define GX_BP_INDMTXC_M02_E 31 + /* bit size */ #define GX_BP_INDMTXC_M02_SZ 11 -/* raw mask */ #define GX_BP_INDMTXC_M02_MASK (((1 << 11) - 1) << 31 - 31) -/* local mask */ #define GX_BP_INDMTXC_M02_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_INDMTXC_M02_SHIFT 0 + /* raw mask */ #define GX_BP_INDMTXC_M02_MASK (((1 << 11) - 1) << 31 - 31) + /* local mask */ #define GX_BP_INDMTXC_M02_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_INDMTXC_M02_SHIFT 0 -/* get value */ #define GX_BP_GET_INDMTXC_M02(reg) GX_BITGET((reg), 21, 11) -/* set value */ #define GX_BP_SET_INDMTXC_M02(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 11, x)) + /* get value */ #define GX_BP_GET_INDMTXC_M02(reg) GX_BITGET((reg), 21, 11) + /* set value */ #define GX_BP_SET_INDMTXC_M02(reg, x) ((reg) = GX_BITSET((reg), 21, 11, x)) // M12 [10:20] (11) - Texture offset matrix #0 [1][2] -/* start bit */ #define GX_BP_INDMTXC_M12_B 10 -/* end bit */ #define GX_BP_INDMTXC_M12_E 20 -/* bit size */ #define GX_BP_INDMTXC_M12_SZ 11 + /* start bit */ #define GX_BP_INDMTXC_M12_B 10 + /* end bit */ #define GX_BP_INDMTXC_M12_E 20 + /* bit size */ #define GX_BP_INDMTXC_M12_SZ 11 -/* raw mask */ #define GX_BP_INDMTXC_M12_MASK (((1 << 11) - 1) << 31 - 20) -/* local mask */ #define GX_BP_INDMTXC_M12_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_INDMTXC_M12_SHIFT 11 + /* raw mask */ #define GX_BP_INDMTXC_M12_MASK (((1 << 11) - 1) << 31 - 20) + /* local mask */ #define GX_BP_INDMTXC_M12_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_INDMTXC_M12_SHIFT 11 -/* get value */ #define GX_BP_GET_INDMTXC_M12(reg) GX_BITGET((reg), 10, 11) -/* set value */ #define GX_BP_SET_INDMTXC_M12(reg, x) \ - ((reg) = GX_BITSET((reg), 10, 11, x)) + /* get value */ #define GX_BP_GET_INDMTXC_M12(reg) GX_BITGET((reg), 10, 11) + /* set value */ #define GX_BP_SET_INDMTXC_M12(reg, x) ((reg) = GX_BITSET((reg), 10, 11, x)) // EXP [8:9] (2) - Bit 4 of scaling exponent #0 (2^x) -/* start bit */ #define GX_BP_INDMTXC_EXP_B 8 -/* end bit */ #define GX_BP_INDMTXC_EXP_E 9 -/* bit size */ #define GX_BP_INDMTXC_EXP_SZ 2 + /* start bit */ #define GX_BP_INDMTXC_EXP_B 8 + /* end bit */ #define GX_BP_INDMTXC_EXP_E 9 + /* bit size */ #define GX_BP_INDMTXC_EXP_SZ 2 + + /* raw mask */ #define GX_BP_INDMTXC_EXP_MASK (((1 << 2) - 1) << 31 - 9) + /* local mask */ #define GX_BP_INDMTXC_EXP_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_INDMTXC_EXP_SHIFT 22 -/* raw mask */ #define GX_BP_INDMTXC_EXP_MASK (((1 << 2) - 1) << 31 - 9) -/* local mask */ #define GX_BP_INDMTXC_EXP_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_INDMTXC_EXP_SHIFT 22 + /* get value */ #define GX_BP_GET_INDMTXC_EXP(reg) GX_BITGET((reg), 8, 2) + /* set value */ #define GX_BP_SET_INDMTXC_EXP(reg, x) ((reg) = GX_BITSET((reg), 8, 2, x)) -/* get value */ #define GX_BP_GET_INDMTXC_EXP(reg) GX_BITGET((reg), 8, 2) -/* set value */ #define GX_BP_SET_INDMTXC_EXP(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 2, x)) /****************************************************************************** * BP register 0xF - IndIMask *****************************************************************************/ // IMASK [24:31] (8) - Indirect mask for textures -/* start bit */ #define GX_BP_INDIMASK_IMASK_B 24 -/* end bit */ #define GX_BP_INDIMASK_IMASK_E 31 -/* bit size */ #define GX_BP_INDIMASK_IMASK_SZ 8 + /* start bit */ #define GX_BP_INDIMASK_IMASK_B 24 + /* end bit */ #define GX_BP_INDIMASK_IMASK_E 31 + /* bit size */ #define GX_BP_INDIMASK_IMASK_SZ 8 -/* raw mask */ #define GX_BP_INDIMASK_IMASK_MASK (((1 << 8) - 1) << 31 - 31) -/* local mask */ #define GX_BP_INDIMASK_IMASK_LMASK ((1 << 8) - 1) -/* bit shift */ #define GX_BP_INDIMASK_IMASK_SHIFT 0 + /* raw mask */ #define GX_BP_INDIMASK_IMASK_MASK (((1 << 8) - 1) << 31 - 31) + /* local mask */ #define GX_BP_INDIMASK_IMASK_LMASK ((1 << 8) - 1) + /* bit shift */ #define GX_BP_INDIMASK_IMASK_SHIFT 0 + + /* get value */ #define GX_BP_GET_INDIMASK_IMASK(reg) GX_BITGET((reg), 24, 8) + /* set value */ #define GX_BP_SET_INDIMASK_IMASK(reg, x) ((reg) = GX_BITSET((reg), 24, 8, x)) -/* get value */ #define GX_BP_GET_INDIMASK_IMASK(reg) GX_BITGET((reg), 24, 8) -/* set value */ #define GX_BP_SET_INDIMASK_IMASK(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 8, x)) /****************************************************************************** * BP structure - IndTevStage *****************************************************************************/ // STAGE [30:31] (2) - Indirect texture stage ID -/* start bit */ #define GX_BP_INDTEVSTAGE_STAGE_B 30 -/* end bit */ #define GX_BP_INDTEVSTAGE_STAGE_E 31 -/* bit size */ #define GX_BP_INDTEVSTAGE_STAGE_SZ 2 + /* start bit */ #define GX_BP_INDTEVSTAGE_STAGE_B 30 + /* end bit */ #define GX_BP_INDTEVSTAGE_STAGE_E 31 + /* bit size */ #define GX_BP_INDTEVSTAGE_STAGE_SZ 2 -/* raw mask */ #define GX_BP_INDTEVSTAGE_STAGE_MASK \ - (((1 << 2) - 1) << 31 - 31) -/* local mask */ #define GX_BP_INDTEVSTAGE_STAGE_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_INDTEVSTAGE_STAGE_SHIFT 0 + /* raw mask */ #define GX_BP_INDTEVSTAGE_STAGE_MASK (((1 << 2) - 1) << 31 - 31) + /* local mask */ #define GX_BP_INDTEVSTAGE_STAGE_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_INDTEVSTAGE_STAGE_SHIFT 0 -/* get value */ #define GX_BP_GET_INDTEVSTAGE_STAGE(reg) \ - GX_BITGET((reg), 30, 2) -/* set value */ #define GX_BP_SET_INDTEVSTAGE_STAGE(reg, x) \ - ((reg) = GX_BITSET((reg), 30, 2, x)) + /* get value */ #define GX_BP_GET_INDTEVSTAGE_STAGE(reg) GX_BITGET((reg), 30, 2) + /* set value */ #define GX_BP_SET_INDTEVSTAGE_STAGE(reg, x) ((reg) = GX_BITSET((reg), 30, 2, x)) // FORMAT [28:29] (2) - Indirect texture format -/* start bit */ #define GX_BP_INDTEVSTAGE_FORMAT_B 28 -/* end bit */ #define GX_BP_INDTEVSTAGE_FORMAT_E 29 -/* bit size */ #define GX_BP_INDTEVSTAGE_FORMAT_SZ 2 + /* start bit */ #define GX_BP_INDTEVSTAGE_FORMAT_B 28 + /* end bit */ #define GX_BP_INDTEVSTAGE_FORMAT_E 29 + /* bit size */ #define GX_BP_INDTEVSTAGE_FORMAT_SZ 2 -/* raw mask */ #define GX_BP_INDTEVSTAGE_FORMAT_MASK \ - (((1 << 2) - 1) << 31 - 29) -/* local mask */ #define GX_BP_INDTEVSTAGE_FORMAT_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_INDTEVSTAGE_FORMAT_SHIFT 2 + /* raw mask */ #define GX_BP_INDTEVSTAGE_FORMAT_MASK (((1 << 2) - 1) << 31 - 29) + /* local mask */ #define GX_BP_INDTEVSTAGE_FORMAT_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_INDTEVSTAGE_FORMAT_SHIFT 2 -/* get value */ #define GX_BP_GET_INDTEVSTAGE_FORMAT(reg) \ - GX_BITGET((reg), 28, 2) -/* set value */ #define GX_BP_SET_INDTEVSTAGE_FORMAT(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 2, x)) + /* get value */ #define GX_BP_GET_INDTEVSTAGE_FORMAT(reg) GX_BITGET((reg), 28, 2) + /* set value */ #define GX_BP_SET_INDTEVSTAGE_FORMAT(reg, x) ((reg) = GX_BITSET((reg), 28, 2, x)) // BIAS [25:27] (3) - Indirect texture bias -/* start bit */ #define GX_BP_INDTEVSTAGE_BIAS_B 25 -/* end bit */ #define GX_BP_INDTEVSTAGE_BIAS_E 27 -/* bit size */ #define GX_BP_INDTEVSTAGE_BIAS_SZ 3 + /* start bit */ #define GX_BP_INDTEVSTAGE_BIAS_B 25 + /* end bit */ #define GX_BP_INDTEVSTAGE_BIAS_E 27 + /* bit size */ #define GX_BP_INDTEVSTAGE_BIAS_SZ 3 -/* raw mask */ #define GX_BP_INDTEVSTAGE_BIAS_MASK (((1 << 3) - 1) << 31 - 27) -/* local mask */ #define GX_BP_INDTEVSTAGE_BIAS_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_INDTEVSTAGE_BIAS_SHIFT 4 + /* raw mask */ #define GX_BP_INDTEVSTAGE_BIAS_MASK (((1 << 3) - 1) << 31 - 27) + /* local mask */ #define GX_BP_INDTEVSTAGE_BIAS_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_INDTEVSTAGE_BIAS_SHIFT 4 -/* get value */ #define GX_BP_GET_INDTEVSTAGE_BIAS(reg) GX_BITGET((reg), 25, 3) -/* set value */ #define GX_BP_SET_INDTEVSTAGE_BIAS(reg, x) \ - ((reg) = GX_BITSET((reg), 25, 3, x)) + /* get value */ #define GX_BP_GET_INDTEVSTAGE_BIAS(reg) GX_BITGET((reg), 25, 3) + /* set value */ #define GX_BP_SET_INDTEVSTAGE_BIAS(reg, x) ((reg) = GX_BITSET((reg), 25, 3, x)) // ALPHA [23:24] (2) - Indirect texture alpha -/* start bit */ #define GX_BP_INDTEVSTAGE_ALPHA_B 23 -/* end bit */ #define GX_BP_INDTEVSTAGE_ALPHA_E 24 -/* bit size */ #define GX_BP_INDTEVSTAGE_ALPHA_SZ 2 + /* start bit */ #define GX_BP_INDTEVSTAGE_ALPHA_B 23 + /* end bit */ #define GX_BP_INDTEVSTAGE_ALPHA_E 24 + /* bit size */ #define GX_BP_INDTEVSTAGE_ALPHA_SZ 2 -/* raw mask */ #define GX_BP_INDTEVSTAGE_ALPHA_MASK \ - (((1 << 2) - 1) << 31 - 24) -/* local mask */ #define GX_BP_INDTEVSTAGE_ALPHA_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_INDTEVSTAGE_ALPHA_SHIFT 7 + /* raw mask */ #define GX_BP_INDTEVSTAGE_ALPHA_MASK (((1 << 2) - 1) << 31 - 24) + /* local mask */ #define GX_BP_INDTEVSTAGE_ALPHA_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_INDTEVSTAGE_ALPHA_SHIFT 7 -/* get value */ #define GX_BP_GET_INDTEVSTAGE_ALPHA(reg) \ - GX_BITGET((reg), 23, 2) -/* set value */ #define GX_BP_SET_INDTEVSTAGE_ALPHA(reg, x) \ - ((reg) = GX_BITSET((reg), 23, 2, x)) + /* get value */ #define GX_BP_GET_INDTEVSTAGE_ALPHA(reg) GX_BITGET((reg), 23, 2) + /* set value */ #define GX_BP_SET_INDTEVSTAGE_ALPHA(reg, x) ((reg) = GX_BITSET((reg), 23, 2, x)) // MTX [19:22] (4) - Indirect texture matrix -/* start bit */ #define GX_BP_INDTEVSTAGE_MTX_B 19 -/* end bit */ #define GX_BP_INDTEVSTAGE_MTX_E 22 -/* bit size */ #define GX_BP_INDTEVSTAGE_MTX_SZ 4 + /* start bit */ #define GX_BP_INDTEVSTAGE_MTX_B 19 + /* end bit */ #define GX_BP_INDTEVSTAGE_MTX_E 22 + /* bit size */ #define GX_BP_INDTEVSTAGE_MTX_SZ 4 -/* raw mask */ #define GX_BP_INDTEVSTAGE_MTX_MASK (((1 << 4) - 1) << 31 - 22) -/* local mask */ #define GX_BP_INDTEVSTAGE_MTX_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_INDTEVSTAGE_MTX_SHIFT 9 + /* raw mask */ #define GX_BP_INDTEVSTAGE_MTX_MASK (((1 << 4) - 1) << 31 - 22) + /* local mask */ #define GX_BP_INDTEVSTAGE_MTX_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_INDTEVSTAGE_MTX_SHIFT 9 -/* get value */ #define GX_BP_GET_INDTEVSTAGE_MTX(reg) GX_BITGET((reg), 19, 4) -/* set value */ #define GX_BP_SET_INDTEVSTAGE_MTX(reg, x) \ - ((reg) = GX_BITSET((reg), 19, 4, x)) + /* get value */ #define GX_BP_GET_INDTEVSTAGE_MTX(reg) GX_BITGET((reg), 19, 4) + /* set value */ #define GX_BP_SET_INDTEVSTAGE_MTX(reg, x) ((reg) = GX_BITSET((reg), 19, 4, x)) // WRAPS [16:18] (3) - S component wrap factor -/* start bit */ #define GX_BP_INDTEVSTAGE_WRAPS_B 16 -/* end bit */ #define GX_BP_INDTEVSTAGE_WRAPS_E 18 -/* bit size */ #define GX_BP_INDTEVSTAGE_WRAPS_SZ 3 + /* start bit */ #define GX_BP_INDTEVSTAGE_WRAPS_B 16 + /* end bit */ #define GX_BP_INDTEVSTAGE_WRAPS_E 18 + /* bit size */ #define GX_BP_INDTEVSTAGE_WRAPS_SZ 3 -/* raw mask */ #define GX_BP_INDTEVSTAGE_WRAPS_MASK \ - (((1 << 3) - 1) << 31 - 18) -/* local mask */ #define GX_BP_INDTEVSTAGE_WRAPS_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_INDTEVSTAGE_WRAPS_SHIFT 13 + /* raw mask */ #define GX_BP_INDTEVSTAGE_WRAPS_MASK (((1 << 3) - 1) << 31 - 18) + /* local mask */ #define GX_BP_INDTEVSTAGE_WRAPS_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_INDTEVSTAGE_WRAPS_SHIFT 13 -/* get value */ #define GX_BP_GET_INDTEVSTAGE_WRAPS(reg) \ - GX_BITGET((reg), 16, 3) -/* set value */ #define GX_BP_SET_INDTEVSTAGE_WRAPS(reg, x) \ - ((reg) = GX_BITSET((reg), 16, 3, x)) + /* get value */ #define GX_BP_GET_INDTEVSTAGE_WRAPS(reg) GX_BITGET((reg), 16, 3) + /* set value */ #define GX_BP_SET_INDTEVSTAGE_WRAPS(reg, x) ((reg) = GX_BITSET((reg), 16, 3, x)) // WRAPT [13:15] (3) - T component wrap factor -/* start bit */ #define GX_BP_INDTEVSTAGE_WRAPT_B 13 -/* end bit */ #define GX_BP_INDTEVSTAGE_WRAPT_E 15 -/* bit size */ #define GX_BP_INDTEVSTAGE_WRAPT_SZ 3 + /* start bit */ #define GX_BP_INDTEVSTAGE_WRAPT_B 13 + /* end bit */ #define GX_BP_INDTEVSTAGE_WRAPT_E 15 + /* bit size */ #define GX_BP_INDTEVSTAGE_WRAPT_SZ 3 -/* raw mask */ #define GX_BP_INDTEVSTAGE_WRAPT_MASK \ - (((1 << 3) - 1) << 31 - 15) -/* local mask */ #define GX_BP_INDTEVSTAGE_WRAPT_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_INDTEVSTAGE_WRAPT_SHIFT 16 + /* raw mask */ #define GX_BP_INDTEVSTAGE_WRAPT_MASK (((1 << 3) - 1) << 31 - 15) + /* local mask */ #define GX_BP_INDTEVSTAGE_WRAPT_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_INDTEVSTAGE_WRAPT_SHIFT 16 -/* get value */ #define GX_BP_GET_INDTEVSTAGE_WRAPT(reg) \ - GX_BITGET((reg), 13, 3) -/* set value */ #define GX_BP_SET_INDTEVSTAGE_WRAPT(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 3, x)) + /* get value */ #define GX_BP_GET_INDTEVSTAGE_WRAPT(reg) GX_BITGET((reg), 13, 3) + /* set value */ #define GX_BP_SET_INDTEVSTAGE_WRAPT(reg, x) ((reg) = GX_BITSET((reg), 13, 3, x)) // UTCLOD [12:12] (1) - Whether to use unmodified texcoords for mipmaps -/* start bit */ #define GX_BP_INDTEVSTAGE_UTCLOD_B 12 -/* end bit */ #define GX_BP_INDTEVSTAGE_UTCLOD_E 12 -/* bit size */ #define GX_BP_INDTEVSTAGE_UTCLOD_SZ 1 + /* start bit */ #define GX_BP_INDTEVSTAGE_UTCLOD_B 12 + /* end bit */ #define GX_BP_INDTEVSTAGE_UTCLOD_E 12 + /* bit size */ #define GX_BP_INDTEVSTAGE_UTCLOD_SZ 1 -/* raw mask */ #define GX_BP_INDTEVSTAGE_UTCLOD_MASK \ - (((1 << 1) - 1) << 31 - 12) -/* local mask */ #define GX_BP_INDTEVSTAGE_UTCLOD_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_INDTEVSTAGE_UTCLOD_SHIFT 19 + /* raw mask */ #define GX_BP_INDTEVSTAGE_UTCLOD_MASK (((1 << 1) - 1) << 31 - 12) + /* local mask */ #define GX_BP_INDTEVSTAGE_UTCLOD_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_INDTEVSTAGE_UTCLOD_SHIFT 19 -/* get value */ #define GX_BP_GET_INDTEVSTAGE_UTCLOD(reg) \ - GX_BITGET((reg), 12, 1) -/* set value */ #define GX_BP_SET_INDTEVSTAGE_UTCLOD(reg, x) \ - ((reg) = GX_BITSET((reg), 12, 1, x)) + /* get value */ #define GX_BP_GET_INDTEVSTAGE_UTCLOD(reg) GX_BITGET((reg), 12, 1) + /* set value */ #define GX_BP_SET_INDTEVSTAGE_UTCLOD(reg, x) ((reg) = GX_BITSET((reg), 12, 1, x)) // ADDPREV [11:11] (1) - Whether to add in results from previous tev stage -/* start bit */ #define GX_BP_INDTEVSTAGE_ADDPREV_B 11 -/* end bit */ #define GX_BP_INDTEVSTAGE_ADDPREV_E 11 -/* bit size */ #define GX_BP_INDTEVSTAGE_ADDPREV_SZ 1 + /* start bit */ #define GX_BP_INDTEVSTAGE_ADDPREV_B 11 + /* end bit */ #define GX_BP_INDTEVSTAGE_ADDPREV_E 11 + /* bit size */ #define GX_BP_INDTEVSTAGE_ADDPREV_SZ 1 + + /* raw mask */ #define GX_BP_INDTEVSTAGE_ADDPREV_MASK (((1 << 1) - 1) << 31 - 11) + /* local mask */ #define GX_BP_INDTEVSTAGE_ADDPREV_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_INDTEVSTAGE_ADDPREV_SHIFT 20 -/* raw mask */ #define GX_BP_INDTEVSTAGE_ADDPREV_MASK \ - (((1 << 1) - 1) << 31 - 11) -/* local mask */ #define GX_BP_INDTEVSTAGE_ADDPREV_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_INDTEVSTAGE_ADDPREV_SHIFT 20 + /* get value */ #define GX_BP_GET_INDTEVSTAGE_ADDPREV(reg) GX_BITGET((reg), 11, 1) + /* set value */ #define GX_BP_SET_INDTEVSTAGE_ADDPREV(reg, x) ((reg) = GX_BITSET((reg), 11, 1, x)) -/* get value */ #define GX_BP_GET_INDTEVSTAGE_ADDPREV(reg) \ - GX_BITGET((reg), 11, 1) -/* set value */ #define GX_BP_SET_INDTEVSTAGE_ADDPREV(reg, x) \ - ((reg) = GX_BITSET((reg), 11, 1, x)) /****************************************************************************** * BP register 0x20 - scissorTL *****************************************************************************/ // TOP [21:31] (11) - Top component -/* start bit */ #define GX_BP_SCISSORTL_TOP_B 21 -/* end bit */ #define GX_BP_SCISSORTL_TOP_E 31 -/* bit size */ #define GX_BP_SCISSORTL_TOP_SZ 11 + /* start bit */ #define GX_BP_SCISSORTL_TOP_B 21 + /* end bit */ #define GX_BP_SCISSORTL_TOP_E 31 + /* bit size */ #define GX_BP_SCISSORTL_TOP_SZ 11 -/* raw mask */ #define GX_BP_SCISSORTL_TOP_MASK (((1 << 11) - 1) << 31 - 31) -/* local mask */ #define GX_BP_SCISSORTL_TOP_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_SCISSORTL_TOP_SHIFT 0 + /* raw mask */ #define GX_BP_SCISSORTL_TOP_MASK (((1 << 11) - 1) << 31 - 31) + /* local mask */ #define GX_BP_SCISSORTL_TOP_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_SCISSORTL_TOP_SHIFT 0 -/* get value */ #define GX_BP_GET_SCISSORTL_TOP(reg) GX_BITGET((reg), 21, 11) -/* set value */ #define GX_BP_SET_SCISSORTL_TOP(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 11, x)) + /* get value */ #define GX_BP_GET_SCISSORTL_TOP(reg) GX_BITGET((reg), 21, 11) + /* set value */ #define GX_BP_SET_SCISSORTL_TOP(reg, x) ((reg) = GX_BITSET((reg), 21, 11, x)) // LEFT [9:19] (11) - Left component -/* start bit */ #define GX_BP_SCISSORTL_LEFT_B 9 -/* end bit */ #define GX_BP_SCISSORTL_LEFT_E 19 -/* bit size */ #define GX_BP_SCISSORTL_LEFT_SZ 11 + /* start bit */ #define GX_BP_SCISSORTL_LEFT_B 9 + /* end bit */ #define GX_BP_SCISSORTL_LEFT_E 19 + /* bit size */ #define GX_BP_SCISSORTL_LEFT_SZ 11 + + /* raw mask */ #define GX_BP_SCISSORTL_LEFT_MASK (((1 << 11) - 1) << 31 - 19) + /* local mask */ #define GX_BP_SCISSORTL_LEFT_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_SCISSORTL_LEFT_SHIFT 12 -/* raw mask */ #define GX_BP_SCISSORTL_LEFT_MASK (((1 << 11) - 1) << 31 - 19) -/* local mask */ #define GX_BP_SCISSORTL_LEFT_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_SCISSORTL_LEFT_SHIFT 12 + /* get value */ #define GX_BP_GET_SCISSORTL_LEFT(reg) GX_BITGET((reg), 9, 11) + /* set value */ #define GX_BP_SET_SCISSORTL_LEFT(reg, x) ((reg) = GX_BITSET((reg), 9, 11, x)) -/* get value */ #define GX_BP_GET_SCISSORTL_LEFT(reg) GX_BITGET((reg), 9, 11) -/* set value */ #define GX_BP_SET_SCISSORTL_LEFT(reg, x) \ - ((reg) = GX_BITSET((reg), 9, 11, x)) /****************************************************************************** * BP register 0x21 - scissorBR *****************************************************************************/ // BOT [21:31] (11) - Bottom component -/* start bit */ #define GX_BP_SCISSORBR_BOT_B 21 -/* end bit */ #define GX_BP_SCISSORBR_BOT_E 31 -/* bit size */ #define GX_BP_SCISSORBR_BOT_SZ 11 + /* start bit */ #define GX_BP_SCISSORBR_BOT_B 21 + /* end bit */ #define GX_BP_SCISSORBR_BOT_E 31 + /* bit size */ #define GX_BP_SCISSORBR_BOT_SZ 11 -/* raw mask */ #define GX_BP_SCISSORBR_BOT_MASK (((1 << 11) - 1) << 31 - 31) -/* local mask */ #define GX_BP_SCISSORBR_BOT_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_SCISSORBR_BOT_SHIFT 0 + /* raw mask */ #define GX_BP_SCISSORBR_BOT_MASK (((1 << 11) - 1) << 31 - 31) + /* local mask */ #define GX_BP_SCISSORBR_BOT_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_SCISSORBR_BOT_SHIFT 0 -/* get value */ #define GX_BP_GET_SCISSORBR_BOT(reg) GX_BITGET((reg), 21, 11) -/* set value */ #define GX_BP_SET_SCISSORBR_BOT(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 11, x)) + /* get value */ #define GX_BP_GET_SCISSORBR_BOT(reg) GX_BITGET((reg), 21, 11) + /* set value */ #define GX_BP_SET_SCISSORBR_BOT(reg, x) ((reg) = GX_BITSET((reg), 21, 11, x)) // RIGHT [9:19] (11) - Right component -/* start bit */ #define GX_BP_SCISSORBR_RIGHT_B 9 -/* end bit */ #define GX_BP_SCISSORBR_RIGHT_E 19 -/* bit size */ #define GX_BP_SCISSORBR_RIGHT_SZ 11 + /* start bit */ #define GX_BP_SCISSORBR_RIGHT_B 9 + /* end bit */ #define GX_BP_SCISSORBR_RIGHT_E 19 + /* bit size */ #define GX_BP_SCISSORBR_RIGHT_SZ 11 -/* raw mask */ #define GX_BP_SCISSORBR_RIGHT_MASK (((1 << 11) - 1) << 31 - 19) -/* local mask */ #define GX_BP_SCISSORBR_RIGHT_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_SCISSORBR_RIGHT_SHIFT 12 + /* raw mask */ #define GX_BP_SCISSORBR_RIGHT_MASK (((1 << 11) - 1) << 31 - 19) + /* local mask */ #define GX_BP_SCISSORBR_RIGHT_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_SCISSORBR_RIGHT_SHIFT 12 + + /* get value */ #define GX_BP_GET_SCISSORBR_RIGHT(reg) GX_BITGET((reg), 9, 11) + /* set value */ #define GX_BP_SET_SCISSORBR_RIGHT(reg, x) ((reg) = GX_BITSET((reg), 9, 11, x)) -/* get value */ #define GX_BP_GET_SCISSORBR_RIGHT(reg) GX_BITGET((reg), 9, 11) -/* set value */ #define GX_BP_SET_SCISSORBR_RIGHT(reg, x) \ - ((reg) = GX_BITSET((reg), 9, 11, x)) /****************************************************************************** * BP register 0x22 - linePtWidth *****************************************************************************/ // LINESZ [24:31] (8) - Line size/width -/* start bit */ #define GX_BP_LINEPTWIDTH_LINESZ_B 24 -/* end bit */ #define GX_BP_LINEPTWIDTH_LINESZ_E 31 -/* bit size */ #define GX_BP_LINEPTWIDTH_LINESZ_SZ 8 + /* start bit */ #define GX_BP_LINEPTWIDTH_LINESZ_B 24 + /* end bit */ #define GX_BP_LINEPTWIDTH_LINESZ_E 31 + /* bit size */ #define GX_BP_LINEPTWIDTH_LINESZ_SZ 8 -/* raw mask */ #define GX_BP_LINEPTWIDTH_LINESZ_MASK \ - (((1 << 8) - 1) << 31 - 31) -/* local mask */ #define GX_BP_LINEPTWIDTH_LINESZ_LMASK ((1 << 8) - 1) -/* bit shift */ #define GX_BP_LINEPTWIDTH_LINESZ_SHIFT 0 + /* raw mask */ #define GX_BP_LINEPTWIDTH_LINESZ_MASK (((1 << 8) - 1) << 31 - 31) + /* local mask */ #define GX_BP_LINEPTWIDTH_LINESZ_LMASK ((1 << 8) - 1) + /* bit shift */ #define GX_BP_LINEPTWIDTH_LINESZ_SHIFT 0 -/* get value */ #define GX_BP_GET_LINEPTWIDTH_LINESZ(reg) \ - GX_BITGET((reg), 24, 8) -/* set value */ #define GX_BP_SET_LINEPTWIDTH_LINESZ(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 8, x)) + /* get value */ #define GX_BP_GET_LINEPTWIDTH_LINESZ(reg) GX_BITGET((reg), 24, 8) + /* set value */ #define GX_BP_SET_LINEPTWIDTH_LINESZ(reg, x) ((reg) = GX_BITSET((reg), 24, 8, x)) // POINTSZ [16:23] (8) - Point size -/* start bit */ #define GX_BP_LINEPTWIDTH_POINTSZ_B 16 -/* end bit */ #define GX_BP_LINEPTWIDTH_POINTSZ_E 23 -/* bit size */ #define GX_BP_LINEPTWIDTH_POINTSZ_SZ 8 + /* start bit */ #define GX_BP_LINEPTWIDTH_POINTSZ_B 16 + /* end bit */ #define GX_BP_LINEPTWIDTH_POINTSZ_E 23 + /* bit size */ #define GX_BP_LINEPTWIDTH_POINTSZ_SZ 8 -/* raw mask */ #define GX_BP_LINEPTWIDTH_POINTSZ_MASK \ - (((1 << 8) - 1) << 31 - 23) -/* local mask */ #define GX_BP_LINEPTWIDTH_POINTSZ_LMASK ((1 << 8) - 1) -/* bit shift */ #define GX_BP_LINEPTWIDTH_POINTSZ_SHIFT 8 + /* raw mask */ #define GX_BP_LINEPTWIDTH_POINTSZ_MASK (((1 << 8) - 1) << 31 - 23) + /* local mask */ #define GX_BP_LINEPTWIDTH_POINTSZ_LMASK ((1 << 8) - 1) + /* bit shift */ #define GX_BP_LINEPTWIDTH_POINTSZ_SHIFT 8 -/* get value */ #define GX_BP_GET_LINEPTWIDTH_POINTSZ(reg) \ - GX_BITGET((reg), 16, 8) -/* set value */ #define GX_BP_SET_LINEPTWIDTH_POINTSZ(reg, x) \ - ((reg) = GX_BITSET((reg), 16, 8, x)) + /* get value */ #define GX_BP_GET_LINEPTWIDTH_POINTSZ(reg) GX_BITGET((reg), 16, 8) + /* set value */ #define GX_BP_SET_LINEPTWIDTH_POINTSZ(reg, x) ((reg) = GX_BITSET((reg), 16, 8, x)) // LINEOFS [13:15] (3) - Line offset -/* start bit */ #define GX_BP_LINEPTWIDTH_LINEOFS_B 13 -/* end bit */ #define GX_BP_LINEPTWIDTH_LINEOFS_E 15 -/* bit size */ #define GX_BP_LINEPTWIDTH_LINEOFS_SZ 3 + /* start bit */ #define GX_BP_LINEPTWIDTH_LINEOFS_B 13 + /* end bit */ #define GX_BP_LINEPTWIDTH_LINEOFS_E 15 + /* bit size */ #define GX_BP_LINEPTWIDTH_LINEOFS_SZ 3 -/* raw mask */ #define GX_BP_LINEPTWIDTH_LINEOFS_MASK \ - (((1 << 3) - 1) << 31 - 15) -/* local mask */ #define GX_BP_LINEPTWIDTH_LINEOFS_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_LINEPTWIDTH_LINEOFS_SHIFT 16 + /* raw mask */ #define GX_BP_LINEPTWIDTH_LINEOFS_MASK (((1 << 3) - 1) << 31 - 15) + /* local mask */ #define GX_BP_LINEPTWIDTH_LINEOFS_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_LINEPTWIDTH_LINEOFS_SHIFT 16 -/* get value */ #define GX_BP_GET_LINEPTWIDTH_LINEOFS(reg) \ - GX_BITGET((reg), 13, 3) -/* set value */ #define GX_BP_SET_LINEPTWIDTH_LINEOFS(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 3, x)) + /* get value */ #define GX_BP_GET_LINEPTWIDTH_LINEOFS(reg) GX_BITGET((reg), 13, 3) + /* set value */ #define GX_BP_SET_LINEPTWIDTH_LINEOFS(reg, x) ((reg) = GX_BITSET((reg), 13, 3, x)) // POINTOFS [10:12] (3) - Point offset -/* start bit */ #define GX_BP_LINEPTWIDTH_POINTOFS_B 10 -/* end bit */ #define GX_BP_LINEPTWIDTH_POINTOFS_E 12 -/* bit size */ #define GX_BP_LINEPTWIDTH_POINTOFS_SZ 3 - -/* raw mask */ #define GX_BP_LINEPTWIDTH_POINTOFS_MASK \ - (((1 << 3) - 1) << 31 - 12) -/* local mask */ #define GX_BP_LINEPTWIDTH_POINTOFS_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_LINEPTWIDTH_POINTOFS_SHIFT 19 - -/* get value */ #define GX_BP_GET_LINEPTWIDTH_POINTOFS(reg) \ - GX_BITGET((reg), 10, 3) -/* set value */ #define GX_BP_SET_LINEPTWIDTH_POINTOFS(reg, x) \ - ((reg) = GX_BITSET((reg), 10, 3, x)) - -// ADJUST_AR [9:9] (1) - Interlacing: adjust for pixels having aspect ratio of -// 1/2 -/* start bit */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_B 9 -/* end bit */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_E 9 -/* bit size */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_SZ 1 - -/* raw mask */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_MASK \ - (((1 << 1) - 1) << 31 - 9) -/* local mask */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_SHIFT 22 - -/* get value */ #define GX_BP_GET_LINEPTWIDTH_ADJUST_AR(reg) \ - GX_BITGET((reg), 9, 1) -/* set value */ #define GX_BP_SET_LINEPTWIDTH_ADJUST_AR(reg, x) \ - ((reg) = GX_BITSET((reg), 9, 1, x)) + /* start bit */ #define GX_BP_LINEPTWIDTH_POINTOFS_B 10 + /* end bit */ #define GX_BP_LINEPTWIDTH_POINTOFS_E 12 + /* bit size */ #define GX_BP_LINEPTWIDTH_POINTOFS_SZ 3 + + /* raw mask */ #define GX_BP_LINEPTWIDTH_POINTOFS_MASK (((1 << 3) - 1) << 31 - 12) + /* local mask */ #define GX_BP_LINEPTWIDTH_POINTOFS_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_LINEPTWIDTH_POINTOFS_SHIFT 19 + + /* get value */ #define GX_BP_GET_LINEPTWIDTH_POINTOFS(reg) GX_BITGET((reg), 10, 3) + /* set value */ #define GX_BP_SET_LINEPTWIDTH_POINTOFS(reg, x) ((reg) = GX_BITSET((reg), 10, 3, x)) + +// ADJUST_AR [9:9] (1) - Interlacing: adjust for pixels having aspect ratio of 1/2 + /* start bit */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_B 9 + /* end bit */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_E 9 + /* bit size */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_SZ 1 + + /* raw mask */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_MASK (((1 << 1) - 1) << 31 - 9) + /* local mask */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_LINEPTWIDTH_ADJUST_AR_SHIFT 22 + + /* get value */ #define GX_BP_GET_LINEPTWIDTH_ADJUST_AR(reg) GX_BITGET((reg), 9, 1) + /* set value */ #define GX_BP_SET_LINEPTWIDTH_ADJUST_AR(reg, x) ((reg) = GX_BITSET((reg), 9, 1, x)) + /****************************************************************************** * BP register 0x25 - ras1_ss0 *****************************************************************************/ // S0 [28:31] (4) - S-component scale (stage 0) -/* start bit */ #define GX_BP_RAS1_SS0_S0_B 28 -/* end bit */ #define GX_BP_RAS1_SS0_S0_E 31 -/* bit size */ #define GX_BP_RAS1_SS0_S0_SZ 4 + /* start bit */ #define GX_BP_RAS1_SS0_S0_B 28 + /* end bit */ #define GX_BP_RAS1_SS0_S0_E 31 + /* bit size */ #define GX_BP_RAS1_SS0_S0_SZ 4 -/* raw mask */ #define GX_BP_RAS1_SS0_S0_MASK (((1 << 4) - 1) << 31 - 31) -/* local mask */ #define GX_BP_RAS1_SS0_S0_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_RAS1_SS0_S0_SHIFT 0 + /* raw mask */ #define GX_BP_RAS1_SS0_S0_MASK (((1 << 4) - 1) << 31 - 31) + /* local mask */ #define GX_BP_RAS1_SS0_S0_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_RAS1_SS0_S0_SHIFT 0 -/* get value */ #define GX_BP_GET_RAS1_SS0_S0(reg) GX_BITGET((reg), 28, 4) -/* set value */ #define GX_BP_SET_RAS1_SS0_S0(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 4, x)) + /* get value */ #define GX_BP_GET_RAS1_SS0_S0(reg) GX_BITGET((reg), 28, 4) + /* set value */ #define GX_BP_SET_RAS1_SS0_S0(reg, x) ((reg) = GX_BITSET((reg), 28, 4, x)) // T0 [24:27] (4) - T-component scale (stage 0) -/* start bit */ #define GX_BP_RAS1_SS0_T0_B 24 -/* end bit */ #define GX_BP_RAS1_SS0_T0_E 27 -/* bit size */ #define GX_BP_RAS1_SS0_T0_SZ 4 + /* start bit */ #define GX_BP_RAS1_SS0_T0_B 24 + /* end bit */ #define GX_BP_RAS1_SS0_T0_E 27 + /* bit size */ #define GX_BP_RAS1_SS0_T0_SZ 4 -/* raw mask */ #define GX_BP_RAS1_SS0_T0_MASK (((1 << 4) - 1) << 31 - 27) -/* local mask */ #define GX_BP_RAS1_SS0_T0_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_RAS1_SS0_T0_SHIFT 4 + /* raw mask */ #define GX_BP_RAS1_SS0_T0_MASK (((1 << 4) - 1) << 31 - 27) + /* local mask */ #define GX_BP_RAS1_SS0_T0_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_RAS1_SS0_T0_SHIFT 4 -/* get value */ #define GX_BP_GET_RAS1_SS0_T0(reg) GX_BITGET((reg), 24, 4) -/* set value */ #define GX_BP_SET_RAS1_SS0_T0(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 4, x)) + /* get value */ #define GX_BP_GET_RAS1_SS0_T0(reg) GX_BITGET((reg), 24, 4) + /* set value */ #define GX_BP_SET_RAS1_SS0_T0(reg, x) ((reg) = GX_BITSET((reg), 24, 4, x)) // S1 [20:23] (4) - S-component scale (stage 1) -/* start bit */ #define GX_BP_RAS1_SS0_S1_B 20 -/* end bit */ #define GX_BP_RAS1_SS0_S1_E 23 -/* bit size */ #define GX_BP_RAS1_SS0_S1_SZ 4 + /* start bit */ #define GX_BP_RAS1_SS0_S1_B 20 + /* end bit */ #define GX_BP_RAS1_SS0_S1_E 23 + /* bit size */ #define GX_BP_RAS1_SS0_S1_SZ 4 -/* raw mask */ #define GX_BP_RAS1_SS0_S1_MASK (((1 << 4) - 1) << 31 - 23) -/* local mask */ #define GX_BP_RAS1_SS0_S1_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_RAS1_SS0_S1_SHIFT 8 + /* raw mask */ #define GX_BP_RAS1_SS0_S1_MASK (((1 << 4) - 1) << 31 - 23) + /* local mask */ #define GX_BP_RAS1_SS0_S1_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_RAS1_SS0_S1_SHIFT 8 -/* get value */ #define GX_BP_GET_RAS1_SS0_S1(reg) GX_BITGET((reg), 20, 4) -/* set value */ #define GX_BP_SET_RAS1_SS0_S1(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 4, x)) + /* get value */ #define GX_BP_GET_RAS1_SS0_S1(reg) GX_BITGET((reg), 20, 4) + /* set value */ #define GX_BP_SET_RAS1_SS0_S1(reg, x) ((reg) = GX_BITSET((reg), 20, 4, x)) // T1 [16:19] (4) - T-component scale (stage 1) -/* start bit */ #define GX_BP_RAS1_SS0_T1_B 16 -/* end bit */ #define GX_BP_RAS1_SS0_T1_E 19 -/* bit size */ #define GX_BP_RAS1_SS0_T1_SZ 4 + /* start bit */ #define GX_BP_RAS1_SS0_T1_B 16 + /* end bit */ #define GX_BP_RAS1_SS0_T1_E 19 + /* bit size */ #define GX_BP_RAS1_SS0_T1_SZ 4 -/* raw mask */ #define GX_BP_RAS1_SS0_T1_MASK (((1 << 4) - 1) << 31 - 19) -/* local mask */ #define GX_BP_RAS1_SS0_T1_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_RAS1_SS0_T1_SHIFT 12 + /* raw mask */ #define GX_BP_RAS1_SS0_T1_MASK (((1 << 4) - 1) << 31 - 19) + /* local mask */ #define GX_BP_RAS1_SS0_T1_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_RAS1_SS0_T1_SHIFT 12 + + /* get value */ #define GX_BP_GET_RAS1_SS0_T1(reg) GX_BITGET((reg), 16, 4) + /* set value */ #define GX_BP_SET_RAS1_SS0_T1(reg, x) ((reg) = GX_BITSET((reg), 16, 4, x)) -/* get value */ #define GX_BP_GET_RAS1_SS0_T1(reg) GX_BITGET((reg), 16, 4) -/* set value */ #define GX_BP_SET_RAS1_SS0_T1(reg, x) \ - ((reg) = GX_BITSET((reg), 16, 4, x)) /****************************************************************************** * BP register 0x26 - ras1_ss1 *****************************************************************************/ // S2 [28:31] (4) - S-component scale (stage 2) -/* start bit */ #define GX_BP_RAS1_SS1_S2_B 28 -/* end bit */ #define GX_BP_RAS1_SS1_S2_E 31 -/* bit size */ #define GX_BP_RAS1_SS1_S2_SZ 4 + /* start bit */ #define GX_BP_RAS1_SS1_S2_B 28 + /* end bit */ #define GX_BP_RAS1_SS1_S2_E 31 + /* bit size */ #define GX_BP_RAS1_SS1_S2_SZ 4 -/* raw mask */ #define GX_BP_RAS1_SS1_S2_MASK (((1 << 4) - 1) << 31 - 31) -/* local mask */ #define GX_BP_RAS1_SS1_S2_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_RAS1_SS1_S2_SHIFT 0 + /* raw mask */ #define GX_BP_RAS1_SS1_S2_MASK (((1 << 4) - 1) << 31 - 31) + /* local mask */ #define GX_BP_RAS1_SS1_S2_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_RAS1_SS1_S2_SHIFT 0 -/* get value */ #define GX_BP_GET_RAS1_SS1_S2(reg) GX_BITGET((reg), 28, 4) -/* set value */ #define GX_BP_SET_RAS1_SS1_S2(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 4, x)) + /* get value */ #define GX_BP_GET_RAS1_SS1_S2(reg) GX_BITGET((reg), 28, 4) + /* set value */ #define GX_BP_SET_RAS1_SS1_S2(reg, x) ((reg) = GX_BITSET((reg), 28, 4, x)) // T2 [24:27] (4) - T-component scale (stage 2) -/* start bit */ #define GX_BP_RAS1_SS1_T2_B 24 -/* end bit */ #define GX_BP_RAS1_SS1_T2_E 27 -/* bit size */ #define GX_BP_RAS1_SS1_T2_SZ 4 + /* start bit */ #define GX_BP_RAS1_SS1_T2_B 24 + /* end bit */ #define GX_BP_RAS1_SS1_T2_E 27 + /* bit size */ #define GX_BP_RAS1_SS1_T2_SZ 4 -/* raw mask */ #define GX_BP_RAS1_SS1_T2_MASK (((1 << 4) - 1) << 31 - 27) -/* local mask */ #define GX_BP_RAS1_SS1_T2_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_RAS1_SS1_T2_SHIFT 4 + /* raw mask */ #define GX_BP_RAS1_SS1_T2_MASK (((1 << 4) - 1) << 31 - 27) + /* local mask */ #define GX_BP_RAS1_SS1_T2_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_RAS1_SS1_T2_SHIFT 4 -/* get value */ #define GX_BP_GET_RAS1_SS1_T2(reg) GX_BITGET((reg), 24, 4) -/* set value */ #define GX_BP_SET_RAS1_SS1_T2(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 4, x)) + /* get value */ #define GX_BP_GET_RAS1_SS1_T2(reg) GX_BITGET((reg), 24, 4) + /* set value */ #define GX_BP_SET_RAS1_SS1_T2(reg, x) ((reg) = GX_BITSET((reg), 24, 4, x)) // S3 [20:23] (4) - S-component scale (stage 3) -/* start bit */ #define GX_BP_RAS1_SS1_S3_B 20 -/* end bit */ #define GX_BP_RAS1_SS1_S3_E 23 -/* bit size */ #define GX_BP_RAS1_SS1_S3_SZ 4 + /* start bit */ #define GX_BP_RAS1_SS1_S3_B 20 + /* end bit */ #define GX_BP_RAS1_SS1_S3_E 23 + /* bit size */ #define GX_BP_RAS1_SS1_S3_SZ 4 -/* raw mask */ #define GX_BP_RAS1_SS1_S3_MASK (((1 << 4) - 1) << 31 - 23) -/* local mask */ #define GX_BP_RAS1_SS1_S3_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_RAS1_SS1_S3_SHIFT 8 + /* raw mask */ #define GX_BP_RAS1_SS1_S3_MASK (((1 << 4) - 1) << 31 - 23) + /* local mask */ #define GX_BP_RAS1_SS1_S3_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_RAS1_SS1_S3_SHIFT 8 -/* get value */ #define GX_BP_GET_RAS1_SS1_S3(reg) GX_BITGET((reg), 20, 4) -/* set value */ #define GX_BP_SET_RAS1_SS1_S3(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 4, x)) + /* get value */ #define GX_BP_GET_RAS1_SS1_S3(reg) GX_BITGET((reg), 20, 4) + /* set value */ #define GX_BP_SET_RAS1_SS1_S3(reg, x) ((reg) = GX_BITSET((reg), 20, 4, x)) // T3 [16:19] (4) - T-component scale (stage 3) -/* start bit */ #define GX_BP_RAS1_SS1_T3_B 16 -/* end bit */ #define GX_BP_RAS1_SS1_T3_E 19 -/* bit size */ #define GX_BP_RAS1_SS1_T3_SZ 4 + /* start bit */ #define GX_BP_RAS1_SS1_T3_B 16 + /* end bit */ #define GX_BP_RAS1_SS1_T3_E 19 + /* bit size */ #define GX_BP_RAS1_SS1_T3_SZ 4 + + /* raw mask */ #define GX_BP_RAS1_SS1_T3_MASK (((1 << 4) - 1) << 31 - 19) + /* local mask */ #define GX_BP_RAS1_SS1_T3_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_RAS1_SS1_T3_SHIFT 12 -/* raw mask */ #define GX_BP_RAS1_SS1_T3_MASK (((1 << 4) - 1) << 31 - 19) -/* local mask */ #define GX_BP_RAS1_SS1_T3_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_RAS1_SS1_T3_SHIFT 12 + /* get value */ #define GX_BP_GET_RAS1_SS1_T3(reg) GX_BITGET((reg), 16, 4) + /* set value */ #define GX_BP_SET_RAS1_SS1_T3(reg, x) ((reg) = GX_BITSET((reg), 16, 4, x)) -/* get value */ #define GX_BP_GET_RAS1_SS1_T3(reg) GX_BITGET((reg), 16, 4) -/* set value */ #define GX_BP_SET_RAS1_SS1_T3(reg, x) \ - ((reg) = GX_BITSET((reg), 16, 4, x)) /****************************************************************************** * BP register 0x27 - ras1_iref *****************************************************************************/ // MAP0 [29:31] (3) - Texmap id (stage 0) -/* start bit */ #define GX_BP_RAS1_IREF_MAP0_B 29 -/* end bit */ #define GX_BP_RAS1_IREF_MAP0_E 31 -/* bit size */ #define GX_BP_RAS1_IREF_MAP0_SZ 3 + /* start bit */ #define GX_BP_RAS1_IREF_MAP0_B 29 + /* end bit */ #define GX_BP_RAS1_IREF_MAP0_E 31 + /* bit size */ #define GX_BP_RAS1_IREF_MAP0_SZ 3 -/* raw mask */ #define GX_BP_RAS1_IREF_MAP0_MASK (((1 << 3) - 1) << 31 - 31) -/* local mask */ #define GX_BP_RAS1_IREF_MAP0_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_IREF_MAP0_SHIFT 0 + /* raw mask */ #define GX_BP_RAS1_IREF_MAP0_MASK (((1 << 3) - 1) << 31 - 31) + /* local mask */ #define GX_BP_RAS1_IREF_MAP0_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_IREF_MAP0_SHIFT 0 -/* get value */ #define GX_BP_GET_RAS1_IREF_MAP0(reg) GX_BITGET((reg), 29, 3) -/* set value */ #define GX_BP_SET_RAS1_IREF_MAP0(reg, x) \ - ((reg) = GX_BITSET((reg), 29, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_IREF_MAP0(reg) GX_BITGET((reg), 29, 3) + /* set value */ #define GX_BP_SET_RAS1_IREF_MAP0(reg, x) ((reg) = GX_BITSET((reg), 29, 3, x)) // TXC0 [26:28] (3) - Texcoord ID (stage 0) -/* start bit */ #define GX_BP_RAS1_IREF_TXC0_B 26 -/* end bit */ #define GX_BP_RAS1_IREF_TXC0_E 28 -/* bit size */ #define GX_BP_RAS1_IREF_TXC0_SZ 3 + /* start bit */ #define GX_BP_RAS1_IREF_TXC0_B 26 + /* end bit */ #define GX_BP_RAS1_IREF_TXC0_E 28 + /* bit size */ #define GX_BP_RAS1_IREF_TXC0_SZ 3 -/* raw mask */ #define GX_BP_RAS1_IREF_TXC0_MASK (((1 << 3) - 1) << 31 - 28) -/* local mask */ #define GX_BP_RAS1_IREF_TXC0_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_IREF_TXC0_SHIFT 3 + /* raw mask */ #define GX_BP_RAS1_IREF_TXC0_MASK (((1 << 3) - 1) << 31 - 28) + /* local mask */ #define GX_BP_RAS1_IREF_TXC0_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_IREF_TXC0_SHIFT 3 -/* get value */ #define GX_BP_GET_RAS1_IREF_TXC0(reg) GX_BITGET((reg), 26, 3) -/* set value */ #define GX_BP_SET_RAS1_IREF_TXC0(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_IREF_TXC0(reg) GX_BITGET((reg), 26, 3) + /* set value */ #define GX_BP_SET_RAS1_IREF_TXC0(reg, x) ((reg) = GX_BITSET((reg), 26, 3, x)) // MAP1 [23:25] (3) - Texmap id (stage 1) -/* start bit */ #define GX_BP_RAS1_IREF_MAP1_B 23 -/* end bit */ #define GX_BP_RAS1_IREF_MAP1_E 25 -/* bit size */ #define GX_BP_RAS1_IREF_MAP1_SZ 3 + /* start bit */ #define GX_BP_RAS1_IREF_MAP1_B 23 + /* end bit */ #define GX_BP_RAS1_IREF_MAP1_E 25 + /* bit size */ #define GX_BP_RAS1_IREF_MAP1_SZ 3 -/* raw mask */ #define GX_BP_RAS1_IREF_MAP1_MASK (((1 << 3) - 1) << 31 - 25) -/* local mask */ #define GX_BP_RAS1_IREF_MAP1_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_IREF_MAP1_SHIFT 6 + /* raw mask */ #define GX_BP_RAS1_IREF_MAP1_MASK (((1 << 3) - 1) << 31 - 25) + /* local mask */ #define GX_BP_RAS1_IREF_MAP1_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_IREF_MAP1_SHIFT 6 -/* get value */ #define GX_BP_GET_RAS1_IREF_MAP1(reg) GX_BITGET((reg), 23, 3) -/* set value */ #define GX_BP_SET_RAS1_IREF_MAP1(reg, x) \ - ((reg) = GX_BITSET((reg), 23, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_IREF_MAP1(reg) GX_BITGET((reg), 23, 3) + /* set value */ #define GX_BP_SET_RAS1_IREF_MAP1(reg, x) ((reg) = GX_BITSET((reg), 23, 3, x)) // TXC1 [20:22] (3) - Texcoord ID (stage 1) -/* start bit */ #define GX_BP_RAS1_IREF_TXC1_B 20 -/* end bit */ #define GX_BP_RAS1_IREF_TXC1_E 22 -/* bit size */ #define GX_BP_RAS1_IREF_TXC1_SZ 3 + /* start bit */ #define GX_BP_RAS1_IREF_TXC1_B 20 + /* end bit */ #define GX_BP_RAS1_IREF_TXC1_E 22 + /* bit size */ #define GX_BP_RAS1_IREF_TXC1_SZ 3 -/* raw mask */ #define GX_BP_RAS1_IREF_TXC1_MASK (((1 << 3) - 1) << 31 - 22) -/* local mask */ #define GX_BP_RAS1_IREF_TXC1_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_IREF_TXC1_SHIFT 9 + /* raw mask */ #define GX_BP_RAS1_IREF_TXC1_MASK (((1 << 3) - 1) << 31 - 22) + /* local mask */ #define GX_BP_RAS1_IREF_TXC1_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_IREF_TXC1_SHIFT 9 -/* get value */ #define GX_BP_GET_RAS1_IREF_TXC1(reg) GX_BITGET((reg), 20, 3) -/* set value */ #define GX_BP_SET_RAS1_IREF_TXC1(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_IREF_TXC1(reg) GX_BITGET((reg), 20, 3) + /* set value */ #define GX_BP_SET_RAS1_IREF_TXC1(reg, x) ((reg) = GX_BITSET((reg), 20, 3, x)) // MAP2 [17:19] (3) - Texmap id (stage 2) -/* start bit */ #define GX_BP_RAS1_IREF_MAP2_B 17 -/* end bit */ #define GX_BP_RAS1_IREF_MAP2_E 19 -/* bit size */ #define GX_BP_RAS1_IREF_MAP2_SZ 3 + /* start bit */ #define GX_BP_RAS1_IREF_MAP2_B 17 + /* end bit */ #define GX_BP_RAS1_IREF_MAP2_E 19 + /* bit size */ #define GX_BP_RAS1_IREF_MAP2_SZ 3 -/* raw mask */ #define GX_BP_RAS1_IREF_MAP2_MASK (((1 << 3) - 1) << 31 - 19) -/* local mask */ #define GX_BP_RAS1_IREF_MAP2_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_IREF_MAP2_SHIFT 12 + /* raw mask */ #define GX_BP_RAS1_IREF_MAP2_MASK (((1 << 3) - 1) << 31 - 19) + /* local mask */ #define GX_BP_RAS1_IREF_MAP2_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_IREF_MAP2_SHIFT 12 -/* get value */ #define GX_BP_GET_RAS1_IREF_MAP2(reg) GX_BITGET((reg), 17, 3) -/* set value */ #define GX_BP_SET_RAS1_IREF_MAP2(reg, x) \ - ((reg) = GX_BITSET((reg), 17, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_IREF_MAP2(reg) GX_BITGET((reg), 17, 3) + /* set value */ #define GX_BP_SET_RAS1_IREF_MAP2(reg, x) ((reg) = GX_BITSET((reg), 17, 3, x)) // TXC2 [14:16] (3) - Texcoord ID (stage 2) -/* start bit */ #define GX_BP_RAS1_IREF_TXC2_B 14 -/* end bit */ #define GX_BP_RAS1_IREF_TXC2_E 16 -/* bit size */ #define GX_BP_RAS1_IREF_TXC2_SZ 3 + /* start bit */ #define GX_BP_RAS1_IREF_TXC2_B 14 + /* end bit */ #define GX_BP_RAS1_IREF_TXC2_E 16 + /* bit size */ #define GX_BP_RAS1_IREF_TXC2_SZ 3 -/* raw mask */ #define GX_BP_RAS1_IREF_TXC2_MASK (((1 << 3) - 1) << 31 - 16) -/* local mask */ #define GX_BP_RAS1_IREF_TXC2_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_IREF_TXC2_SHIFT 15 + /* raw mask */ #define GX_BP_RAS1_IREF_TXC2_MASK (((1 << 3) - 1) << 31 - 16) + /* local mask */ #define GX_BP_RAS1_IREF_TXC2_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_IREF_TXC2_SHIFT 15 -/* get value */ #define GX_BP_GET_RAS1_IREF_TXC2(reg) GX_BITGET((reg), 14, 3) -/* set value */ #define GX_BP_SET_RAS1_IREF_TXC2(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_IREF_TXC2(reg) GX_BITGET((reg), 14, 3) + /* set value */ #define GX_BP_SET_RAS1_IREF_TXC2(reg, x) ((reg) = GX_BITSET((reg), 14, 3, x)) // MAP3 [11:13] (3) - Texmap id (stage 3) -/* start bit */ #define GX_BP_RAS1_IREF_MAP3_B 11 -/* end bit */ #define GX_BP_RAS1_IREF_MAP3_E 13 -/* bit size */ #define GX_BP_RAS1_IREF_MAP3_SZ 3 + /* start bit */ #define GX_BP_RAS1_IREF_MAP3_B 11 + /* end bit */ #define GX_BP_RAS1_IREF_MAP3_E 13 + /* bit size */ #define GX_BP_RAS1_IREF_MAP3_SZ 3 -/* raw mask */ #define GX_BP_RAS1_IREF_MAP3_MASK (((1 << 3) - 1) << 31 - 13) -/* local mask */ #define GX_BP_RAS1_IREF_MAP3_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_IREF_MAP3_SHIFT 18 + /* raw mask */ #define GX_BP_RAS1_IREF_MAP3_MASK (((1 << 3) - 1) << 31 - 13) + /* local mask */ #define GX_BP_RAS1_IREF_MAP3_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_IREF_MAP3_SHIFT 18 -/* get value */ #define GX_BP_GET_RAS1_IREF_MAP3(reg) GX_BITGET((reg), 11, 3) -/* set value */ #define GX_BP_SET_RAS1_IREF_MAP3(reg, x) \ - ((reg) = GX_BITSET((reg), 11, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_IREF_MAP3(reg) GX_BITGET((reg), 11, 3) + /* set value */ #define GX_BP_SET_RAS1_IREF_MAP3(reg, x) ((reg) = GX_BITSET((reg), 11, 3, x)) // TXC3 [8:10] (3) - Texcoord ID (stage 3) -/* start bit */ #define GX_BP_RAS1_IREF_TXC3_B 8 -/* end bit */ #define GX_BP_RAS1_IREF_TXC3_E 10 -/* bit size */ #define GX_BP_RAS1_IREF_TXC3_SZ 3 + /* start bit */ #define GX_BP_RAS1_IREF_TXC3_B 8 + /* end bit */ #define GX_BP_RAS1_IREF_TXC3_E 10 + /* bit size */ #define GX_BP_RAS1_IREF_TXC3_SZ 3 + + /* raw mask */ #define GX_BP_RAS1_IREF_TXC3_MASK (((1 << 3) - 1) << 31 - 10) + /* local mask */ #define GX_BP_RAS1_IREF_TXC3_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_IREF_TXC3_SHIFT 21 -/* raw mask */ #define GX_BP_RAS1_IREF_TXC3_MASK (((1 << 3) - 1) << 31 - 10) -/* local mask */ #define GX_BP_RAS1_IREF_TXC3_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_IREF_TXC3_SHIFT 21 + /* get value */ #define GX_BP_GET_RAS1_IREF_TXC3(reg) GX_BITGET((reg), 8, 3) + /* set value */ #define GX_BP_SET_RAS1_IREF_TXC3(reg, x) ((reg) = GX_BITSET((reg), 8, 3, x)) -/* get value */ #define GX_BP_GET_RAS1_IREF_TXC3(reg) GX_BITGET((reg), 8, 3) -/* set value */ #define GX_BP_SET_RAS1_IREF_TXC3(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 3, x)) /****************************************************************************** * BP structure - ras1_tref *****************************************************************************/ // TEXMAP_EVEN [29:31] (3) -/* start bit */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_B 29 -/* end bit */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_E 31 -/* bit size */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_SZ 3 + /* start bit */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_B 29 + /* end bit */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_E 31 + /* bit size */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_SZ 3 -/* raw mask */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_MASK \ - (((1 << 3) - 1) << 31 - 31) -/* local mask */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_SHIFT 0 + /* raw mask */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_MASK (((1 << 3) - 1) << 31 - 31) + /* local mask */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_TREF_TEXMAP_EVEN_SHIFT 0 -/* get value */ #define GX_BP_GET_RAS1_TREF_TEXMAP_EVEN(reg) \ - GX_BITGET((reg), 29, 3) -/* set value */ #define GX_BP_SET_RAS1_TREF_TEXMAP_EVEN(reg, x) \ - ((reg) = GX_BITSET((reg), 29, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_TREF_TEXMAP_EVEN(reg) GX_BITGET((reg), 29, 3) + /* set value */ #define GX_BP_SET_RAS1_TREF_TEXMAP_EVEN(reg, x) ((reg) = GX_BITSET((reg), 29, 3, x)) // TEXCOORD_EVEN [26:28] (3) -/* start bit */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_B 26 -/* end bit */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_E 28 -/* bit size */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_SZ 3 + /* start bit */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_B 26 + /* end bit */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_E 28 + /* bit size */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_SZ 3 -/* raw mask */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_MASK \ - (((1 << 3) - 1) << 31 - 28) -/* local mask */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_SHIFT 3 + /* raw mask */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_MASK (((1 << 3) - 1) << 31 - 28) + /* local mask */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_TREF_TEXCOORD_EVEN_SHIFT 3 -/* get value */ #define GX_BP_GET_RAS1_TREF_TEXCOORD_EVEN(reg) \ - GX_BITGET((reg), 26, 3) -/* set value */ #define GX_BP_SET_RAS1_TREF_TEXCOORD_EVEN(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_TREF_TEXCOORD_EVEN(reg) GX_BITGET((reg), 26, 3) + /* set value */ #define GX_BP_SET_RAS1_TREF_TEXCOORD_EVEN(reg, x) ((reg) = GX_BITSET((reg), 26, 3, x)) // ENABLE_TEX_EVEN [25:25] (1) -/* start bit */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_B 25 -/* end bit */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_E 25 -/* bit size */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_SZ 1 + /* start bit */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_B 25 + /* end bit */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_E 25 + /* bit size */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_SZ 1 -/* raw mask */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_MASK \ - (((1 << 1) - 1) << 31 - 25) -/* local mask */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_SHIFT 6 + /* raw mask */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_MASK (((1 << 1) - 1) << 31 - 25) + /* local mask */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_RAS1_TREF_ENABLE_TEX_EVEN_SHIFT 6 -/* get value */ #define GX_BP_GET_RAS1_TREF_ENABLE_TEX_EVEN(reg) \ - GX_BITGET((reg), 25, 1) -/* set value */ #define GX_BP_SET_RAS1_TREF_ENABLE_TEX_EVEN(reg, x) \ - ((reg) = GX_BITSET((reg), 25, 1, x)) + /* get value */ #define GX_BP_GET_RAS1_TREF_ENABLE_TEX_EVEN(reg) GX_BITGET((reg), 25, 1) + /* set value */ #define GX_BP_SET_RAS1_TREF_ENABLE_TEX_EVEN(reg, x) ((reg) = GX_BITSET((reg), 25, 1, x)) // COLORCHAN_EVEN [22:24] (3) -/* start bit */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_B 22 -/* end bit */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_E 24 -/* bit size */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_SZ 3 + /* start bit */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_B 22 + /* end bit */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_E 24 + /* bit size */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_SZ 3 -/* raw mask */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_MASK \ - (((1 << 3) - 1) << 31 - 24) -/* local mask */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_SHIFT 7 + /* raw mask */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_MASK (((1 << 3) - 1) << 31 - 24) + /* local mask */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_TREF_COLORCHAN_EVEN_SHIFT 7 -/* get value */ #define GX_BP_GET_RAS1_TREF_COLORCHAN_EVEN(reg) \ - GX_BITGET((reg), 22, 3) -/* set value */ #define GX_BP_SET_RAS1_TREF_COLORCHAN_EVEN(reg, x) \ - ((reg) = GX_BITSET((reg), 22, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_TREF_COLORCHAN_EVEN(reg) GX_BITGET((reg), 22, 3) + /* set value */ #define GX_BP_SET_RAS1_TREF_COLORCHAN_EVEN(reg, x) ((reg) = GX_BITSET((reg), 22, 3, x)) // TEXMAP_ODD [17:19] (3) -/* start bit */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_B 17 -/* end bit */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_E 19 -/* bit size */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_SZ 3 + /* start bit */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_B 17 + /* end bit */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_E 19 + /* bit size */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_SZ 3 -/* raw mask */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_MASK \ - (((1 << 3) - 1) << 31 - 19) -/* local mask */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_SHIFT 12 + /* raw mask */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_MASK (((1 << 3) - 1) << 31 - 19) + /* local mask */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_TREF_TEXMAP_ODD_SHIFT 12 -/* get value */ #define GX_BP_GET_RAS1_TREF_TEXMAP_ODD(reg) \ - GX_BITGET((reg), 17, 3) -/* set value */ #define GX_BP_SET_RAS1_TREF_TEXMAP_ODD(reg, x) \ - ((reg) = GX_BITSET((reg), 17, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_TREF_TEXMAP_ODD(reg) GX_BITGET((reg), 17, 3) + /* set value */ #define GX_BP_SET_RAS1_TREF_TEXMAP_ODD(reg, x) ((reg) = GX_BITSET((reg), 17, 3, x)) // TEXCOORD_ODD [14:16] (3) -/* start bit */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_B 14 -/* end bit */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_E 16 -/* bit size */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_SZ 3 + /* start bit */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_B 14 + /* end bit */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_E 16 + /* bit size */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_SZ 3 -/* raw mask */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_MASK \ - (((1 << 3) - 1) << 31 - 16) -/* local mask */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_SHIFT 15 + /* raw mask */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_MASK (((1 << 3) - 1) << 31 - 16) + /* local mask */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_TREF_TEXCOORD_ODD_SHIFT 15 -/* get value */ #define GX_BP_GET_RAS1_TREF_TEXCOORD_ODD(reg) \ - GX_BITGET((reg), 14, 3) -/* set value */ #define GX_BP_SET_RAS1_TREF_TEXCOORD_ODD(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 3, x)) + /* get value */ #define GX_BP_GET_RAS1_TREF_TEXCOORD_ODD(reg) GX_BITGET((reg), 14, 3) + /* set value */ #define GX_BP_SET_RAS1_TREF_TEXCOORD_ODD(reg, x) ((reg) = GX_BITSET((reg), 14, 3, x)) // ENABLE_TEX_ODD [13:13] (1) -/* start bit */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_B 13 -/* end bit */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_E 13 -/* bit size */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_SZ 1 + /* start bit */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_B 13 + /* end bit */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_E 13 + /* bit size */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_SZ 1 -/* raw mask */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_MASK \ - (((1 << 1) - 1) << 31 - 13) -/* local mask */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_SHIFT 18 + /* raw mask */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_MASK (((1 << 1) - 1) << 31 - 13) + /* local mask */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_RAS1_TREF_ENABLE_TEX_ODD_SHIFT 18 -/* get value */ #define GX_BP_GET_RAS1_TREF_ENABLE_TEX_ODD(reg) \ - GX_BITGET((reg), 13, 1) -/* set value */ #define GX_BP_SET_RAS1_TREF_ENABLE_TEX_ODD(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 1, x)) + /* get value */ #define GX_BP_GET_RAS1_TREF_ENABLE_TEX_ODD(reg) GX_BITGET((reg), 13, 1) + /* set value */ #define GX_BP_SET_RAS1_TREF_ENABLE_TEX_ODD(reg, x) ((reg) = GX_BITSET((reg), 13, 1, x)) // COLORCHAN_ODD [10:12] (3) -/* start bit */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_B 10 -/* end bit */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_E 12 -/* bit size */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_SZ 3 + /* start bit */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_B 10 + /* end bit */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_E 12 + /* bit size */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_SZ 3 -/* raw mask */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_MASK \ - (((1 << 3) - 1) << 31 - 12) -/* local mask */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_SHIFT 19 + /* raw mask */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_MASK (((1 << 3) - 1) << 31 - 12) + /* local mask */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_RAS1_TREF_COLORCHAN_ODD_SHIFT 19 + + /* get value */ #define GX_BP_GET_RAS1_TREF_COLORCHAN_ODD(reg) GX_BITGET((reg), 10, 3) + /* set value */ #define GX_BP_SET_RAS1_TREF_COLORCHAN_ODD(reg, x) ((reg) = GX_BITSET((reg), 10, 3, x)) -/* get value */ #define GX_BP_GET_RAS1_TREF_COLORCHAN_ODD(reg) \ - GX_BITGET((reg), 10, 3) -/* set value */ #define GX_BP_SET_RAS1_TREF_COLORCHAN_ODD(reg, x) \ - ((reg) = GX_BITSET((reg), 10, 3, x)) /****************************************************************************** * BP structure - su_size *****************************************************************************/ // SCALE [16:31] (16) -/* start bit */ #define GX_BP_SU_SIZE_SCALE_B 16 -/* end bit */ #define GX_BP_SU_SIZE_SCALE_E 31 -/* bit size */ #define GX_BP_SU_SIZE_SCALE_SZ 16 + /* start bit */ #define GX_BP_SU_SIZE_SCALE_B 16 + /* end bit */ #define GX_BP_SU_SIZE_SCALE_E 31 + /* bit size */ #define GX_BP_SU_SIZE_SCALE_SZ 16 -/* raw mask */ #define GX_BP_SU_SIZE_SCALE_MASK (((1 << 16) - 1) << 31 - 31) -/* local mask */ #define GX_BP_SU_SIZE_SCALE_LMASK ((1 << 16) - 1) -/* bit shift */ #define GX_BP_SU_SIZE_SCALE_SHIFT 0 + /* raw mask */ #define GX_BP_SU_SIZE_SCALE_MASK (((1 << 16) - 1) << 31 - 31) + /* local mask */ #define GX_BP_SU_SIZE_SCALE_LMASK ((1 << 16) - 1) + /* bit shift */ #define GX_BP_SU_SIZE_SCALE_SHIFT 0 -/* get value */ #define GX_BP_GET_SU_SIZE_SCALE(reg) GX_BITGET((reg), 16, 16) -/* set value */ #define GX_BP_SET_SU_SIZE_SCALE(reg, x) \ - ((reg) = GX_BITSET((reg), 16, 16, x)) + /* get value */ #define GX_BP_GET_SU_SIZE_SCALE(reg) GX_BITGET((reg), 16, 16) + /* set value */ #define GX_BP_SET_SU_SIZE_SCALE(reg, x) ((reg) = GX_BITSET((reg), 16, 16, x)) // RANGEBIAS [15:15] (1) -/* start bit */ #define GX_BP_SU_SIZE_RANGEBIAS_B 15 -/* end bit */ #define GX_BP_SU_SIZE_RANGEBIAS_E 15 -/* bit size */ #define GX_BP_SU_SIZE_RANGEBIAS_SZ 1 + /* start bit */ #define GX_BP_SU_SIZE_RANGEBIAS_B 15 + /* end bit */ #define GX_BP_SU_SIZE_RANGEBIAS_E 15 + /* bit size */ #define GX_BP_SU_SIZE_RANGEBIAS_SZ 1 -/* raw mask */ #define GX_BP_SU_SIZE_RANGEBIAS_MASK \ - (((1 << 1) - 1) << 31 - 15) -/* local mask */ #define GX_BP_SU_SIZE_RANGEBIAS_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_SU_SIZE_RANGEBIAS_SHIFT 16 + /* raw mask */ #define GX_BP_SU_SIZE_RANGEBIAS_MASK (((1 << 1) - 1) << 31 - 15) + /* local mask */ #define GX_BP_SU_SIZE_RANGEBIAS_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_SU_SIZE_RANGEBIAS_SHIFT 16 -/* get value */ #define GX_BP_GET_SU_SIZE_RANGEBIAS(reg) \ - GX_BITGET((reg), 15, 1) -/* set value */ #define GX_BP_SET_SU_SIZE_RANGEBIAS(reg, x) \ - ((reg) = GX_BITSET((reg), 15, 1, x)) + /* get value */ #define GX_BP_GET_SU_SIZE_RANGEBIAS(reg) GX_BITGET((reg), 15, 1) + /* set value */ #define GX_BP_SET_SU_SIZE_RANGEBIAS(reg, x) ((reg) = GX_BITSET((reg), 15, 1, x)) // CYLINDRICWRAP [14:14] (1) -/* start bit */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_B 14 -/* end bit */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_E 14 -/* bit size */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_SZ 1 + /* start bit */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_B 14 + /* end bit */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_E 14 + /* bit size */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_SZ 1 -/* raw mask */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_MASK \ - (((1 << 1) - 1) << 31 - 14) -/* local mask */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_SHIFT 17 + /* raw mask */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_MASK (((1 << 1) - 1) << 31 - 14) + /* local mask */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_SU_SIZE_CYLINDRICWRAP_SHIFT 17 -/* get value */ #define GX_BP_GET_SU_SIZE_CYLINDRICWRAP(reg) \ - GX_BITGET((reg), 14, 1) -/* set value */ #define GX_BP_SET_SU_SIZE_CYLINDRICWRAP(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 1, x)) + /* get value */ #define GX_BP_GET_SU_SIZE_CYLINDRICWRAP(reg) GX_BITGET((reg), 14, 1) + /* set value */ #define GX_BP_SET_SU_SIZE_CYLINDRICWRAP(reg, x) ((reg) = GX_BITSET((reg), 14, 1, x)) // USELINEOFS [13:13] (1) -/* start bit */ #define GX_BP_SU_SIZE_USELINEOFS_B 13 -/* end bit */ #define GX_BP_SU_SIZE_USELINEOFS_E 13 -/* bit size */ #define GX_BP_SU_SIZE_USELINEOFS_SZ 1 + /* start bit */ #define GX_BP_SU_SIZE_USELINEOFS_B 13 + /* end bit */ #define GX_BP_SU_SIZE_USELINEOFS_E 13 + /* bit size */ #define GX_BP_SU_SIZE_USELINEOFS_SZ 1 -/* raw mask */ #define GX_BP_SU_SIZE_USELINEOFS_MASK \ - (((1 << 1) - 1) << 31 - 13) -/* local mask */ #define GX_BP_SU_SIZE_USELINEOFS_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_SU_SIZE_USELINEOFS_SHIFT 18 + /* raw mask */ #define GX_BP_SU_SIZE_USELINEOFS_MASK (((1 << 1) - 1) << 31 - 13) + /* local mask */ #define GX_BP_SU_SIZE_USELINEOFS_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_SU_SIZE_USELINEOFS_SHIFT 18 -/* get value */ #define GX_BP_GET_SU_SIZE_USELINEOFS(reg) \ - GX_BITGET((reg), 13, 1) -/* set value */ #define GX_BP_SET_SU_SIZE_USELINEOFS(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 1, x)) + /* get value */ #define GX_BP_GET_SU_SIZE_USELINEOFS(reg) GX_BITGET((reg), 13, 1) + /* set value */ #define GX_BP_SET_SU_SIZE_USELINEOFS(reg, x) ((reg) = GX_BITSET((reg), 13, 1, x)) // USEPOINTOFS [12:12] (1) -/* start bit */ #define GX_BP_SU_SIZE_USEPOINTOFS_B 12 -/* end bit */ #define GX_BP_SU_SIZE_USEPOINTOFS_E 12 -/* bit size */ #define GX_BP_SU_SIZE_USEPOINTOFS_SZ 1 + /* start bit */ #define GX_BP_SU_SIZE_USEPOINTOFS_B 12 + /* end bit */ #define GX_BP_SU_SIZE_USEPOINTOFS_E 12 + /* bit size */ #define GX_BP_SU_SIZE_USEPOINTOFS_SZ 1 + + /* raw mask */ #define GX_BP_SU_SIZE_USEPOINTOFS_MASK (((1 << 1) - 1) << 31 - 12) + /* local mask */ #define GX_BP_SU_SIZE_USEPOINTOFS_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_SU_SIZE_USEPOINTOFS_SHIFT 19 -/* raw mask */ #define GX_BP_SU_SIZE_USEPOINTOFS_MASK \ - (((1 << 1) - 1) << 31 - 12) -/* local mask */ #define GX_BP_SU_SIZE_USEPOINTOFS_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_SU_SIZE_USEPOINTOFS_SHIFT 19 + /* get value */ #define GX_BP_GET_SU_SIZE_USEPOINTOFS(reg) GX_BITGET((reg), 12, 1) + /* set value */ #define GX_BP_SET_SU_SIZE_USEPOINTOFS(reg, x) ((reg) = GX_BITSET((reg), 12, 1, x)) -/* get value */ #define GX_BP_GET_SU_SIZE_USEPOINTOFS(reg) \ - GX_BITGET((reg), 12, 1) -/* set value */ #define GX_BP_SET_SU_SIZE_USEPOINTOFS(reg, x) \ - ((reg) = GX_BITSET((reg), 12, 1, x)) /****************************************************************************** * BP register 0x40 - ZMode *****************************************************************************/ // TEST_ENABLE [31:31] (1) -/* start bit */ #define GX_BP_ZMODE_TEST_ENABLE_B 31 -/* end bit */ #define GX_BP_ZMODE_TEST_ENABLE_E 31 -/* bit size */ #define GX_BP_ZMODE_TEST_ENABLE_SZ 1 + /* start bit */ #define GX_BP_ZMODE_TEST_ENABLE_B 31 + /* end bit */ #define GX_BP_ZMODE_TEST_ENABLE_E 31 + /* bit size */ #define GX_BP_ZMODE_TEST_ENABLE_SZ 1 -/* raw mask */ #define GX_BP_ZMODE_TEST_ENABLE_MASK \ - (((1 << 1) - 1) << 31 - 31) -/* local mask */ #define GX_BP_ZMODE_TEST_ENABLE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_ZMODE_TEST_ENABLE_SHIFT 0 + /* raw mask */ #define GX_BP_ZMODE_TEST_ENABLE_MASK (((1 << 1) - 1) << 31 - 31) + /* local mask */ #define GX_BP_ZMODE_TEST_ENABLE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_ZMODE_TEST_ENABLE_SHIFT 0 -/* get value */ #define GX_BP_GET_ZMODE_TEST_ENABLE(reg) \ - GX_BITGET((reg), 31, 1) -/* set value */ #define GX_BP_SET_ZMODE_TEST_ENABLE(reg, x) \ - ((reg) = GX_BITSET((reg), 31, 1, x)) + /* get value */ #define GX_BP_GET_ZMODE_TEST_ENABLE(reg) GX_BITGET((reg), 31, 1) + /* set value */ #define GX_BP_SET_ZMODE_TEST_ENABLE(reg, x) ((reg) = GX_BITSET((reg), 31, 1, x)) // COMPARE [28:30] (3) -/* start bit */ #define GX_BP_ZMODE_COMPARE_B 28 -/* end bit */ #define GX_BP_ZMODE_COMPARE_E 30 -/* bit size */ #define GX_BP_ZMODE_COMPARE_SZ 3 + /* start bit */ #define GX_BP_ZMODE_COMPARE_B 28 + /* end bit */ #define GX_BP_ZMODE_COMPARE_E 30 + /* bit size */ #define GX_BP_ZMODE_COMPARE_SZ 3 -/* raw mask */ #define GX_BP_ZMODE_COMPARE_MASK (((1 << 3) - 1) << 31 - 30) -/* local mask */ #define GX_BP_ZMODE_COMPARE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_ZMODE_COMPARE_SHIFT 1 + /* raw mask */ #define GX_BP_ZMODE_COMPARE_MASK (((1 << 3) - 1) << 31 - 30) + /* local mask */ #define GX_BP_ZMODE_COMPARE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_ZMODE_COMPARE_SHIFT 1 -/* get value */ #define GX_BP_GET_ZMODE_COMPARE(reg) GX_BITGET((reg), 28, 3) -/* set value */ #define GX_BP_SET_ZMODE_COMPARE(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 3, x)) + /* get value */ #define GX_BP_GET_ZMODE_COMPARE(reg) GX_BITGET((reg), 28, 3) + /* set value */ #define GX_BP_SET_ZMODE_COMPARE(reg, x) ((reg) = GX_BITSET((reg), 28, 3, x)) // UPDATE_ENABLE [27:27] (1) -/* start bit */ #define GX_BP_ZMODE_UPDATE_ENABLE_B 27 -/* end bit */ #define GX_BP_ZMODE_UPDATE_ENABLE_E 27 -/* bit size */ #define GX_BP_ZMODE_UPDATE_ENABLE_SZ 1 + /* start bit */ #define GX_BP_ZMODE_UPDATE_ENABLE_B 27 + /* end bit */ #define GX_BP_ZMODE_UPDATE_ENABLE_E 27 + /* bit size */ #define GX_BP_ZMODE_UPDATE_ENABLE_SZ 1 + + /* raw mask */ #define GX_BP_ZMODE_UPDATE_ENABLE_MASK (((1 << 1) - 1) << 31 - 27) + /* local mask */ #define GX_BP_ZMODE_UPDATE_ENABLE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_ZMODE_UPDATE_ENABLE_SHIFT 4 -/* raw mask */ #define GX_BP_ZMODE_UPDATE_ENABLE_MASK \ - (((1 << 1) - 1) << 31 - 27) -/* local mask */ #define GX_BP_ZMODE_UPDATE_ENABLE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_ZMODE_UPDATE_ENABLE_SHIFT 4 + /* get value */ #define GX_BP_GET_ZMODE_UPDATE_ENABLE(reg) GX_BITGET((reg), 27, 1) + /* set value */ #define GX_BP_SET_ZMODE_UPDATE_ENABLE(reg, x) ((reg) = GX_BITSET((reg), 27, 1, x)) -/* get value */ #define GX_BP_GET_ZMODE_UPDATE_ENABLE(reg) \ - GX_BITGET((reg), 27, 1) -/* set value */ #define GX_BP_SET_ZMODE_UPDATE_ENABLE(reg, x) \ - ((reg) = GX_BITSET((reg), 27, 1, x)) /****************************************************************************** * BP register 0x41 - BlendMode *****************************************************************************/ // BLEND_ENABLE [31:31] (1) -/* start bit */ #define GX_BP_BLENDMODE_BLEND_ENABLE_B 31 -/* end bit */ #define GX_BP_BLENDMODE_BLEND_ENABLE_E 31 -/* bit size */ #define GX_BP_BLENDMODE_BLEND_ENABLE_SZ 1 + /* start bit */ #define GX_BP_BLENDMODE_BLEND_ENABLE_B 31 + /* end bit */ #define GX_BP_BLENDMODE_BLEND_ENABLE_E 31 + /* bit size */ #define GX_BP_BLENDMODE_BLEND_ENABLE_SZ 1 -/* raw mask */ #define GX_BP_BLENDMODE_BLEND_ENABLE_MASK \ - (((1 << 1) - 1) << 31 - 31) -/* local mask */ #define GX_BP_BLENDMODE_BLEND_ENABLE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_BLENDMODE_BLEND_ENABLE_SHIFT 0 + /* raw mask */ #define GX_BP_BLENDMODE_BLEND_ENABLE_MASK (((1 << 1) - 1) << 31 - 31) + /* local mask */ #define GX_BP_BLENDMODE_BLEND_ENABLE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_BLENDMODE_BLEND_ENABLE_SHIFT 0 -/* get value */ #define GX_BP_GET_BLENDMODE_BLEND_ENABLE(reg) \ - GX_BITGET((reg), 31, 1) -/* set value */ #define GX_BP_SET_BLENDMODE_BLEND_ENABLE(reg, x) \ - ((reg) = GX_BITSET((reg), 31, 1, x)) + /* get value */ #define GX_BP_GET_BLENDMODE_BLEND_ENABLE(reg) GX_BITGET((reg), 31, 1) + /* set value */ #define GX_BP_SET_BLENDMODE_BLEND_ENABLE(reg, x) ((reg) = GX_BITSET((reg), 31, 1, x)) // LOGIC_OP_ENABLE [30:30] (1) -/* start bit */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_B 30 -/* end bit */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_E 30 -/* bit size */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_SZ 1 + /* start bit */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_B 30 + /* end bit */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_E 30 + /* bit size */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_SZ 1 -/* raw mask */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_MASK \ - (((1 << 1) - 1) << 31 - 30) -/* local mask */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_SHIFT 1 + /* raw mask */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_MASK (((1 << 1) - 1) << 31 - 30) + /* local mask */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_BLENDMODE_LOGIC_OP_ENABLE_SHIFT 1 -/* get value */ #define GX_BP_GET_BLENDMODE_LOGIC_OP_ENABLE(reg) \ - GX_BITGET((reg), 30, 1) -/* set value */ #define GX_BP_SET_BLENDMODE_LOGIC_OP_ENABLE(reg, x) \ - ((reg) = GX_BITSET((reg), 30, 1, x)) + /* get value */ #define GX_BP_GET_BLENDMODE_LOGIC_OP_ENABLE(reg) GX_BITGET((reg), 30, 1) + /* set value */ #define GX_BP_SET_BLENDMODE_LOGIC_OP_ENABLE(reg, x) ((reg) = GX_BITSET((reg), 30, 1, x)) // DITHER [29:29] (1) -/* start bit */ #define GX_BP_BLENDMODE_DITHER_B 29 -/* end bit */ #define GX_BP_BLENDMODE_DITHER_E 29 -/* bit size */ #define GX_BP_BLENDMODE_DITHER_SZ 1 + /* start bit */ #define GX_BP_BLENDMODE_DITHER_B 29 + /* end bit */ #define GX_BP_BLENDMODE_DITHER_E 29 + /* bit size */ #define GX_BP_BLENDMODE_DITHER_SZ 1 -/* raw mask */ #define GX_BP_BLENDMODE_DITHER_MASK (((1 << 1) - 1) << 31 - 29) -/* local mask */ #define GX_BP_BLENDMODE_DITHER_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_BLENDMODE_DITHER_SHIFT 2 + /* raw mask */ #define GX_BP_BLENDMODE_DITHER_MASK (((1 << 1) - 1) << 31 - 29) + /* local mask */ #define GX_BP_BLENDMODE_DITHER_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_BLENDMODE_DITHER_SHIFT 2 -/* get value */ #define GX_BP_GET_BLENDMODE_DITHER(reg) GX_BITGET((reg), 29, 1) -/* set value */ #define GX_BP_SET_BLENDMODE_DITHER(reg, x) \ - ((reg) = GX_BITSET((reg), 29, 1, x)) + /* get value */ #define GX_BP_GET_BLENDMODE_DITHER(reg) GX_BITGET((reg), 29, 1) + /* set value */ #define GX_BP_SET_BLENDMODE_DITHER(reg, x) ((reg) = GX_BITSET((reg), 29, 1, x)) // COLOR_UPDATE [28:28] (1) -/* start bit */ #define GX_BP_BLENDMODE_COLOR_UPDATE_B 28 -/* end bit */ #define GX_BP_BLENDMODE_COLOR_UPDATE_E 28 -/* bit size */ #define GX_BP_BLENDMODE_COLOR_UPDATE_SZ 1 + /* start bit */ #define GX_BP_BLENDMODE_COLOR_UPDATE_B 28 + /* end bit */ #define GX_BP_BLENDMODE_COLOR_UPDATE_E 28 + /* bit size */ #define GX_BP_BLENDMODE_COLOR_UPDATE_SZ 1 -/* raw mask */ #define GX_BP_BLENDMODE_COLOR_UPDATE_MASK \ - (((1 << 1) - 1) << 31 - 28) -/* local mask */ #define GX_BP_BLENDMODE_COLOR_UPDATE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_BLENDMODE_COLOR_UPDATE_SHIFT 3 + /* raw mask */ #define GX_BP_BLENDMODE_COLOR_UPDATE_MASK (((1 << 1) - 1) << 31 - 28) + /* local mask */ #define GX_BP_BLENDMODE_COLOR_UPDATE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_BLENDMODE_COLOR_UPDATE_SHIFT 3 -/* get value */ #define GX_BP_GET_BLENDMODE_COLOR_UPDATE(reg) \ - GX_BITGET((reg), 28, 1) -/* set value */ #define GX_BP_SET_BLENDMODE_COLOR_UPDATE(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 1, x)) + /* get value */ #define GX_BP_GET_BLENDMODE_COLOR_UPDATE(reg) GX_BITGET((reg), 28, 1) + /* set value */ #define GX_BP_SET_BLENDMODE_COLOR_UPDATE(reg, x) ((reg) = GX_BITSET((reg), 28, 1, x)) // ALPHA_UPDATE [27:27] (1) -/* start bit */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_B 27 -/* end bit */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_E 27 -/* bit size */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_SZ 1 + /* start bit */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_B 27 + /* end bit */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_E 27 + /* bit size */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_SZ 1 -/* raw mask */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_MASK \ - (((1 << 1) - 1) << 31 - 27) -/* local mask */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_SHIFT 4 + /* raw mask */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_MASK (((1 << 1) - 1) << 31 - 27) + /* local mask */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_BLENDMODE_ALPHA_UPDATE_SHIFT 4 -/* get value */ #define GX_BP_GET_BLENDMODE_ALPHA_UPDATE(reg) \ - GX_BITGET((reg), 27, 1) -/* set value */ #define GX_BP_SET_BLENDMODE_ALPHA_UPDATE(reg, x) \ - ((reg) = GX_BITSET((reg), 27, 1, x)) + /* get value */ #define GX_BP_GET_BLENDMODE_ALPHA_UPDATE(reg) GX_BITGET((reg), 27, 1) + /* set value */ #define GX_BP_SET_BLENDMODE_ALPHA_UPDATE(reg, x) ((reg) = GX_BITSET((reg), 27, 1, x)) // DST_FACTOR [24:26] (3) -/* start bit */ #define GX_BP_BLENDMODE_DST_FACTOR_B 24 -/* end bit */ #define GX_BP_BLENDMODE_DST_FACTOR_E 26 -/* bit size */ #define GX_BP_BLENDMODE_DST_FACTOR_SZ 3 + /* start bit */ #define GX_BP_BLENDMODE_DST_FACTOR_B 24 + /* end bit */ #define GX_BP_BLENDMODE_DST_FACTOR_E 26 + /* bit size */ #define GX_BP_BLENDMODE_DST_FACTOR_SZ 3 -/* raw mask */ #define GX_BP_BLENDMODE_DST_FACTOR_MASK \ - (((1 << 3) - 1) << 31 - 26) -/* local mask */ #define GX_BP_BLENDMODE_DST_FACTOR_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_BLENDMODE_DST_FACTOR_SHIFT 5 + /* raw mask */ #define GX_BP_BLENDMODE_DST_FACTOR_MASK (((1 << 3) - 1) << 31 - 26) + /* local mask */ #define GX_BP_BLENDMODE_DST_FACTOR_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_BLENDMODE_DST_FACTOR_SHIFT 5 -/* get value */ #define GX_BP_GET_BLENDMODE_DST_FACTOR(reg) \ - GX_BITGET((reg), 24, 3) -/* set value */ #define GX_BP_SET_BLENDMODE_DST_FACTOR(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 3, x)) + /* get value */ #define GX_BP_GET_BLENDMODE_DST_FACTOR(reg) GX_BITGET((reg), 24, 3) + /* set value */ #define GX_BP_SET_BLENDMODE_DST_FACTOR(reg, x) ((reg) = GX_BITSET((reg), 24, 3, x)) // SRC_FACTOR [21:23] (3) -/* start bit */ #define GX_BP_BLENDMODE_SRC_FACTOR_B 21 -/* end bit */ #define GX_BP_BLENDMODE_SRC_FACTOR_E 23 -/* bit size */ #define GX_BP_BLENDMODE_SRC_FACTOR_SZ 3 + /* start bit */ #define GX_BP_BLENDMODE_SRC_FACTOR_B 21 + /* end bit */ #define GX_BP_BLENDMODE_SRC_FACTOR_E 23 + /* bit size */ #define GX_BP_BLENDMODE_SRC_FACTOR_SZ 3 -/* raw mask */ #define GX_BP_BLENDMODE_SRC_FACTOR_MASK \ - (((1 << 3) - 1) << 31 - 23) -/* local mask */ #define GX_BP_BLENDMODE_SRC_FACTOR_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_BLENDMODE_SRC_FACTOR_SHIFT 8 + /* raw mask */ #define GX_BP_BLENDMODE_SRC_FACTOR_MASK (((1 << 3) - 1) << 31 - 23) + /* local mask */ #define GX_BP_BLENDMODE_SRC_FACTOR_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_BLENDMODE_SRC_FACTOR_SHIFT 8 -/* get value */ #define GX_BP_GET_BLENDMODE_SRC_FACTOR(reg) \ - GX_BITGET((reg), 21, 3) -/* set value */ #define GX_BP_SET_BLENDMODE_SRC_FACTOR(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 3, x)) + /* get value */ #define GX_BP_GET_BLENDMODE_SRC_FACTOR(reg) GX_BITGET((reg), 21, 3) + /* set value */ #define GX_BP_SET_BLENDMODE_SRC_FACTOR(reg, x) ((reg) = GX_BITSET((reg), 21, 3, x)) // SUBTRACT [20:20] (1) -/* start bit */ #define GX_BP_BLENDMODE_SUBTRACT_B 20 -/* end bit */ #define GX_BP_BLENDMODE_SUBTRACT_E 20 -/* bit size */ #define GX_BP_BLENDMODE_SUBTRACT_SZ 1 + /* start bit */ #define GX_BP_BLENDMODE_SUBTRACT_B 20 + /* end bit */ #define GX_BP_BLENDMODE_SUBTRACT_E 20 + /* bit size */ #define GX_BP_BLENDMODE_SUBTRACT_SZ 1 -/* raw mask */ #define GX_BP_BLENDMODE_SUBTRACT_MASK \ - (((1 << 1) - 1) << 31 - 20) -/* local mask */ #define GX_BP_BLENDMODE_SUBTRACT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_BLENDMODE_SUBTRACT_SHIFT 11 + /* raw mask */ #define GX_BP_BLENDMODE_SUBTRACT_MASK (((1 << 1) - 1) << 31 - 20) + /* local mask */ #define GX_BP_BLENDMODE_SUBTRACT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_BLENDMODE_SUBTRACT_SHIFT 11 -/* get value */ #define GX_BP_GET_BLENDMODE_SUBTRACT(reg) \ - GX_BITGET((reg), 20, 1) -/* set value */ #define GX_BP_SET_BLENDMODE_SUBTRACT(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 1, x)) + /* get value */ #define GX_BP_GET_BLENDMODE_SUBTRACT(reg) GX_BITGET((reg), 20, 1) + /* set value */ #define GX_BP_SET_BLENDMODE_SUBTRACT(reg, x) ((reg) = GX_BITSET((reg), 20, 1, x)) // LOGIC_MODE [16:19] (4) -/* start bit */ #define GX_BP_BLENDMODE_LOGIC_MODE_B 16 -/* end bit */ #define GX_BP_BLENDMODE_LOGIC_MODE_E 19 -/* bit size */ #define GX_BP_BLENDMODE_LOGIC_MODE_SZ 4 + /* start bit */ #define GX_BP_BLENDMODE_LOGIC_MODE_B 16 + /* end bit */ #define GX_BP_BLENDMODE_LOGIC_MODE_E 19 + /* bit size */ #define GX_BP_BLENDMODE_LOGIC_MODE_SZ 4 -/* raw mask */ #define GX_BP_BLENDMODE_LOGIC_MODE_MASK \ - (((1 << 4) - 1) << 31 - 19) -/* local mask */ #define GX_BP_BLENDMODE_LOGIC_MODE_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_BLENDMODE_LOGIC_MODE_SHIFT 12 + /* raw mask */ #define GX_BP_BLENDMODE_LOGIC_MODE_MASK (((1 << 4) - 1) << 31 - 19) + /* local mask */ #define GX_BP_BLENDMODE_LOGIC_MODE_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_BLENDMODE_LOGIC_MODE_SHIFT 12 + + /* get value */ #define GX_BP_GET_BLENDMODE_LOGIC_MODE(reg) GX_BITGET((reg), 16, 4) + /* set value */ #define GX_BP_SET_BLENDMODE_LOGIC_MODE(reg, x) ((reg) = GX_BITSET((reg), 16, 4, x)) -/* get value */ #define GX_BP_GET_BLENDMODE_LOGIC_MODE(reg) \ - GX_BITGET((reg), 16, 4) -/* set value */ #define GX_BP_SET_BLENDMODE_LOGIC_MODE(reg, x) \ - ((reg) = GX_BITSET((reg), 16, 4, x)) /****************************************************************************** * BP register 0x42 - DstAlpha *****************************************************************************/ // ALPHA [24:31] (8) -/* start bit */ #define GX_BP_DSTALPHA_ALPHA_B 24 -/* end bit */ #define GX_BP_DSTALPHA_ALPHA_E 31 -/* bit size */ #define GX_BP_DSTALPHA_ALPHA_SZ 8 + /* start bit */ #define GX_BP_DSTALPHA_ALPHA_B 24 + /* end bit */ #define GX_BP_DSTALPHA_ALPHA_E 31 + /* bit size */ #define GX_BP_DSTALPHA_ALPHA_SZ 8 -/* raw mask */ #define GX_BP_DSTALPHA_ALPHA_MASK (((1 << 8) - 1) << 31 - 31) -/* local mask */ #define GX_BP_DSTALPHA_ALPHA_LMASK ((1 << 8) - 1) -/* bit shift */ #define GX_BP_DSTALPHA_ALPHA_SHIFT 0 + /* raw mask */ #define GX_BP_DSTALPHA_ALPHA_MASK (((1 << 8) - 1) << 31 - 31) + /* local mask */ #define GX_BP_DSTALPHA_ALPHA_LMASK ((1 << 8) - 1) + /* bit shift */ #define GX_BP_DSTALPHA_ALPHA_SHIFT 0 -/* get value */ #define GX_BP_GET_DSTALPHA_ALPHA(reg) GX_BITGET((reg), 24, 8) -/* set value */ #define GX_BP_SET_DSTALPHA_ALPHA(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 8, x)) + /* get value */ #define GX_BP_GET_DSTALPHA_ALPHA(reg) GX_BITGET((reg), 24, 8) + /* set value */ #define GX_BP_SET_DSTALPHA_ALPHA(reg, x) ((reg) = GX_BITSET((reg), 24, 8, x)) // ENABLE [23:23] (1) -/* start bit */ #define GX_BP_DSTALPHA_ENABLE_B 23 -/* end bit */ #define GX_BP_DSTALPHA_ENABLE_E 23 -/* bit size */ #define GX_BP_DSTALPHA_ENABLE_SZ 1 + /* start bit */ #define GX_BP_DSTALPHA_ENABLE_B 23 + /* end bit */ #define GX_BP_DSTALPHA_ENABLE_E 23 + /* bit size */ #define GX_BP_DSTALPHA_ENABLE_SZ 1 -/* raw mask */ #define GX_BP_DSTALPHA_ENABLE_MASK (((1 << 1) - 1) << 31 - 23) -/* local mask */ #define GX_BP_DSTALPHA_ENABLE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_DSTALPHA_ENABLE_SHIFT 8 + /* raw mask */ #define GX_BP_DSTALPHA_ENABLE_MASK (((1 << 1) - 1) << 31 - 23) + /* local mask */ #define GX_BP_DSTALPHA_ENABLE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_DSTALPHA_ENABLE_SHIFT 8 -/* get value */ #define GX_BP_GET_DSTALPHA_ENABLE(reg) GX_BITGET((reg), 23, 1) -/* set value */ #define GX_BP_SET_DSTALPHA_ENABLE(reg, x) \ - ((reg) = GX_BITSET((reg), 23, 1, x)) + /* get value */ #define GX_BP_GET_DSTALPHA_ENABLE(reg) GX_BITGET((reg), 23, 1) + /* set value */ #define GX_BP_SET_DSTALPHA_ENABLE(reg, x) ((reg) = GX_BITSET((reg), 23, 1, x)) // YUV_FMT [21:22] (2) -/* start bit */ #define GX_BP_DSTALPHA_YUV_FMT_B 21 -/* end bit */ #define GX_BP_DSTALPHA_YUV_FMT_E 22 -/* bit size */ #define GX_BP_DSTALPHA_YUV_FMT_SZ 2 + /* start bit */ #define GX_BP_DSTALPHA_YUV_FMT_B 21 + /* end bit */ #define GX_BP_DSTALPHA_YUV_FMT_E 22 + /* bit size */ #define GX_BP_DSTALPHA_YUV_FMT_SZ 2 + + /* raw mask */ #define GX_BP_DSTALPHA_YUV_FMT_MASK (((1 << 2) - 1) << 31 - 22) + /* local mask */ #define GX_BP_DSTALPHA_YUV_FMT_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_DSTALPHA_YUV_FMT_SHIFT 9 -/* raw mask */ #define GX_BP_DSTALPHA_YUV_FMT_MASK (((1 << 2) - 1) << 31 - 22) -/* local mask */ #define GX_BP_DSTALPHA_YUV_FMT_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_DSTALPHA_YUV_FMT_SHIFT 9 + /* get value */ #define GX_BP_GET_DSTALPHA_YUV_FMT(reg) GX_BITGET((reg), 21, 2) + /* set value */ #define GX_BP_SET_DSTALPHA_YUV_FMT(reg, x) ((reg) = GX_BITSET((reg), 21, 2, x)) -/* get value */ #define GX_BP_GET_DSTALPHA_YUV_FMT(reg) GX_BITGET((reg), 21, 2) -/* set value */ #define GX_BP_SET_DSTALPHA_YUV_FMT(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 2, x)) /****************************************************************************** * BP register 0x43 - ZControl *****************************************************************************/ // PIXEL_FMT [29:31] (3) -/* start bit */ #define GX_BP_ZCONTROL_PIXEL_FMT_B 29 -/* end bit */ #define GX_BP_ZCONTROL_PIXEL_FMT_E 31 -/* bit size */ #define GX_BP_ZCONTROL_PIXEL_FMT_SZ 3 + /* start bit */ #define GX_BP_ZCONTROL_PIXEL_FMT_B 29 + /* end bit */ #define GX_BP_ZCONTROL_PIXEL_FMT_E 31 + /* bit size */ #define GX_BP_ZCONTROL_PIXEL_FMT_SZ 3 -/* raw mask */ #define GX_BP_ZCONTROL_PIXEL_FMT_MASK \ - (((1 << 3) - 1) << 31 - 31) -/* local mask */ #define GX_BP_ZCONTROL_PIXEL_FMT_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_ZCONTROL_PIXEL_FMT_SHIFT 0 + /* raw mask */ #define GX_BP_ZCONTROL_PIXEL_FMT_MASK (((1 << 3) - 1) << 31 - 31) + /* local mask */ #define GX_BP_ZCONTROL_PIXEL_FMT_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_ZCONTROL_PIXEL_FMT_SHIFT 0 -/* get value */ #define GX_BP_GET_ZCONTROL_PIXEL_FMT(reg) \ - GX_BITGET((reg), 29, 3) -/* set value */ #define GX_BP_SET_ZCONTROL_PIXEL_FMT(reg, x) \ - ((reg) = GX_BITSET((reg), 29, 3, x)) + /* get value */ #define GX_BP_GET_ZCONTROL_PIXEL_FMT(reg) GX_BITGET((reg), 29, 3) + /* set value */ #define GX_BP_SET_ZCONTROL_PIXEL_FMT(reg, x) ((reg) = GX_BITSET((reg), 29, 3, x)) // Z_FMT [26:28] (3) -/* start bit */ #define GX_BP_ZCONTROL_Z_FMT_B 26 -/* end bit */ #define GX_BP_ZCONTROL_Z_FMT_E 28 -/* bit size */ #define GX_BP_ZCONTROL_Z_FMT_SZ 3 - -/* raw mask */ #define GX_BP_ZCONTROL_Z_FMT_MASK (((1 << 3) - 1) << 31 - 28) -/* local mask */ #define GX_BP_ZCONTROL_Z_FMT_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_ZCONTROL_Z_FMT_SHIFT 3 - -/* get value */ #define GX_BP_GET_ZCONTROL_Z_FMT(reg) GX_BITGET((reg), 26, 3) -/* set value */ #define GX_BP_SET_ZCONTROL_Z_FMT(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 3, x)) - -// BEFORE_TEX [25:25] (1) - Determines whether Z-buffering occurs before or -// after texturing -/* start bit */ #define GX_BP_ZCONTROL_BEFORE_TEX_B 25 -/* end bit */ #define GX_BP_ZCONTROL_BEFORE_TEX_E 25 -/* bit size */ #define GX_BP_ZCONTROL_BEFORE_TEX_SZ 1 - -/* raw mask */ #define GX_BP_ZCONTROL_BEFORE_TEX_MASK \ - (((1 << 1) - 1) << 31 - 25) -/* local mask */ #define GX_BP_ZCONTROL_BEFORE_TEX_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_ZCONTROL_BEFORE_TEX_SHIFT 6 - -/* get value */ #define GX_BP_GET_ZCONTROL_BEFORE_TEX(reg) \ - GX_BITGET((reg), 25, 1) -/* set value */ #define GX_BP_SET_ZCONTROL_BEFORE_TEX(reg, x) \ - ((reg) = GX_BITSET((reg), 25, 1, x)) + /* start bit */ #define GX_BP_ZCONTROL_Z_FMT_B 26 + /* end bit */ #define GX_BP_ZCONTROL_Z_FMT_E 28 + /* bit size */ #define GX_BP_ZCONTROL_Z_FMT_SZ 3 + + /* raw mask */ #define GX_BP_ZCONTROL_Z_FMT_MASK (((1 << 3) - 1) << 31 - 28) + /* local mask */ #define GX_BP_ZCONTROL_Z_FMT_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_ZCONTROL_Z_FMT_SHIFT 3 + + /* get value */ #define GX_BP_GET_ZCONTROL_Z_FMT(reg) GX_BITGET((reg), 26, 3) + /* set value */ #define GX_BP_SET_ZCONTROL_Z_FMT(reg, x) ((reg) = GX_BITSET((reg), 26, 3, x)) + +// BEFORE_TEX [25:25] (1) - Determines whether Z-buffering occurs before or after texturing + /* start bit */ #define GX_BP_ZCONTROL_BEFORE_TEX_B 25 + /* end bit */ #define GX_BP_ZCONTROL_BEFORE_TEX_E 25 + /* bit size */ #define GX_BP_ZCONTROL_BEFORE_TEX_SZ 1 + + /* raw mask */ #define GX_BP_ZCONTROL_BEFORE_TEX_MASK (((1 << 1) - 1) << 31 - 25) + /* local mask */ #define GX_BP_ZCONTROL_BEFORE_TEX_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_ZCONTROL_BEFORE_TEX_SHIFT 6 + + /* get value */ #define GX_BP_GET_ZCONTROL_BEFORE_TEX(reg) GX_BITGET((reg), 25, 1) + /* set value */ #define GX_BP_SET_ZCONTROL_BEFORE_TEX(reg, x) ((reg) = GX_BITSET((reg), 25, 1, x)) + /****************************************************************************** * BP register 0x44 - FieldMask *****************************************************************************/ // ODD [31:31] (1) - Whether to write odd fields to the EFB -/* start bit */ #define GX_BP_FIELDMASK_ODD_B 31 -/* end bit */ #define GX_BP_FIELDMASK_ODD_E 31 -/* bit size */ #define GX_BP_FIELDMASK_ODD_SZ 1 + /* start bit */ #define GX_BP_FIELDMASK_ODD_B 31 + /* end bit */ #define GX_BP_FIELDMASK_ODD_E 31 + /* bit size */ #define GX_BP_FIELDMASK_ODD_SZ 1 -/* raw mask */ #define GX_BP_FIELDMASK_ODD_MASK (((1 << 1) - 1) << 31 - 31) -/* local mask */ #define GX_BP_FIELDMASK_ODD_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_FIELDMASK_ODD_SHIFT 0 + /* raw mask */ #define GX_BP_FIELDMASK_ODD_MASK (((1 << 1) - 1) << 31 - 31) + /* local mask */ #define GX_BP_FIELDMASK_ODD_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_FIELDMASK_ODD_SHIFT 0 -/* get value */ #define GX_BP_GET_FIELDMASK_ODD(reg) GX_BITGET((reg), 31, 1) -/* set value */ #define GX_BP_SET_FIELDMASK_ODD(reg, x) \ - ((reg) = GX_BITSET((reg), 31, 1, x)) + /* get value */ #define GX_BP_GET_FIELDMASK_ODD(reg) GX_BITGET((reg), 31, 1) + /* set value */ #define GX_BP_SET_FIELDMASK_ODD(reg, x) ((reg) = GX_BITSET((reg), 31, 1, x)) // EVEN [30:30] (1) - Whether to write even fields to the EFB -/* start bit */ #define GX_BP_FIELDMASK_EVEN_B 30 -/* end bit */ #define GX_BP_FIELDMASK_EVEN_E 30 -/* bit size */ #define GX_BP_FIELDMASK_EVEN_SZ 1 + /* start bit */ #define GX_BP_FIELDMASK_EVEN_B 30 + /* end bit */ #define GX_BP_FIELDMASK_EVEN_E 30 + /* bit size */ #define GX_BP_FIELDMASK_EVEN_SZ 1 + + /* raw mask */ #define GX_BP_FIELDMASK_EVEN_MASK (((1 << 1) - 1) << 31 - 30) + /* local mask */ #define GX_BP_FIELDMASK_EVEN_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_FIELDMASK_EVEN_SHIFT 1 -/* raw mask */ #define GX_BP_FIELDMASK_EVEN_MASK (((1 << 1) - 1) << 31 - 30) -/* local mask */ #define GX_BP_FIELDMASK_EVEN_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_FIELDMASK_EVEN_SHIFT 1 + /* get value */ #define GX_BP_GET_FIELDMASK_EVEN(reg) GX_BITGET((reg), 30, 1) + /* set value */ #define GX_BP_SET_FIELDMASK_EVEN(reg, x) ((reg) = GX_BITSET((reg), 30, 1, x)) -/* get value */ #define GX_BP_GET_FIELDMASK_EVEN(reg) GX_BITGET((reg), 30, 1) -/* set value */ #define GX_BP_SET_FIELDMASK_EVEN(reg, x) \ - ((reg) = GX_BITSET((reg), 30, 1, x)) /****************************************************************************** * BP register 0x59 - ScissorOffset *****************************************************************************/ // OX [22:31] (10) -/* start bit */ #define GX_BP_SCISSOROFFSET_OX_B 22 -/* end bit */ #define GX_BP_SCISSOROFFSET_OX_E 31 -/* bit size */ #define GX_BP_SCISSOROFFSET_OX_SZ 10 + /* start bit */ #define GX_BP_SCISSOROFFSET_OX_B 22 + /* end bit */ #define GX_BP_SCISSOROFFSET_OX_E 31 + /* bit size */ #define GX_BP_SCISSOROFFSET_OX_SZ 10 -/* raw mask */ #define GX_BP_SCISSOROFFSET_OX_MASK \ - (((1 << 10) - 1) << 31 - 31) -/* local mask */ #define GX_BP_SCISSOROFFSET_OX_LMASK ((1 << 10) - 1) -/* bit shift */ #define GX_BP_SCISSOROFFSET_OX_SHIFT 0 + /* raw mask */ #define GX_BP_SCISSOROFFSET_OX_MASK (((1 << 10) - 1) << 31 - 31) + /* local mask */ #define GX_BP_SCISSOROFFSET_OX_LMASK ((1 << 10) - 1) + /* bit shift */ #define GX_BP_SCISSOROFFSET_OX_SHIFT 0 -/* get value */ #define GX_BP_GET_SCISSOROFFSET_OX(reg) \ - GX_BITGET((reg), 22, 10) -/* set value */ #define GX_BP_SET_SCISSOROFFSET_OX(reg, x) \ - ((reg) = GX_BITSET((reg), 22, 10, x)) + /* get value */ #define GX_BP_GET_SCISSOROFFSET_OX(reg) GX_BITGET((reg), 22, 10) + /* set value */ #define GX_BP_SET_SCISSOROFFSET_OX(reg, x) ((reg) = GX_BITSET((reg), 22, 10, x)) // OY [12:21] (10) -/* start bit */ #define GX_BP_SCISSOROFFSET_OY_B 12 -/* end bit */ #define GX_BP_SCISSOROFFSET_OY_E 21 -/* bit size */ #define GX_BP_SCISSOROFFSET_OY_SZ 10 + /* start bit */ #define GX_BP_SCISSOROFFSET_OY_B 12 + /* end bit */ #define GX_BP_SCISSOROFFSET_OY_E 21 + /* bit size */ #define GX_BP_SCISSOROFFSET_OY_SZ 10 + + /* raw mask */ #define GX_BP_SCISSOROFFSET_OY_MASK (((1 << 10) - 1) << 31 - 21) + /* local mask */ #define GX_BP_SCISSOROFFSET_OY_LMASK ((1 << 10) - 1) + /* bit shift */ #define GX_BP_SCISSOROFFSET_OY_SHIFT 10 -/* raw mask */ #define GX_BP_SCISSOROFFSET_OY_MASK \ - (((1 << 10) - 1) << 31 - 21) -/* local mask */ #define GX_BP_SCISSOROFFSET_OY_LMASK ((1 << 10) - 1) -/* bit shift */ #define GX_BP_SCISSOROFFSET_OY_SHIFT 10 + /* get value */ #define GX_BP_GET_SCISSOROFFSET_OY(reg) GX_BITGET((reg), 12, 10) + /* set value */ #define GX_BP_SET_SCISSOROFFSET_OY(reg, x) ((reg) = GX_BITSET((reg), 12, 10, x)) -/* get value */ #define GX_BP_GET_SCISSOROFFSET_OY(reg) \ - GX_BITGET((reg), 12, 10) -/* set value */ #define GX_BP_SET_SCISSOROFFSET_OY(reg, x) \ - ((reg) = GX_BITSET((reg), 12, 10, x)) /****************************************************************************** * BP register 0x68 - FieldMode *****************************************************************************/ -// TEX_LOD [31:31] (1) - Adjust vertex tex LOD computation to account for -// interlacing -/* start bit */ #define GX_BP_FIELDMODE_TEX_LOD_B 31 -/* end bit */ #define GX_BP_FIELDMODE_TEX_LOD_E 31 -/* bit size */ #define GX_BP_FIELDMODE_TEX_LOD_SZ 1 - -/* raw mask */ #define GX_BP_FIELDMODE_TEX_LOD_MASK \ - (((1 << 1) - 1) << 31 - 31) -/* local mask */ #define GX_BP_FIELDMODE_TEX_LOD_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_FIELDMODE_TEX_LOD_SHIFT 0 - -/* get value */ #define GX_BP_GET_FIELDMODE_TEX_LOD(reg) \ - GX_BITGET((reg), 31, 1) -/* set value */ #define GX_BP_SET_FIELDMODE_TEX_LOD(reg, x) \ - ((reg) = GX_BITSET((reg), 31, 1, x)) +// TEX_LOD [31:31] (1) - Adjust vertex tex LOD computation to account for interlacing + /* start bit */ #define GX_BP_FIELDMODE_TEX_LOD_B 31 + /* end bit */ #define GX_BP_FIELDMODE_TEX_LOD_E 31 + /* bit size */ #define GX_BP_FIELDMODE_TEX_LOD_SZ 1 + + /* raw mask */ #define GX_BP_FIELDMODE_TEX_LOD_MASK (((1 << 1) - 1) << 31 - 31) + /* local mask */ #define GX_BP_FIELDMODE_TEX_LOD_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_FIELDMODE_TEX_LOD_SHIFT 0 + + /* get value */ #define GX_BP_GET_FIELDMODE_TEX_LOD(reg) GX_BITGET((reg), 31, 1) + /* set value */ #define GX_BP_SET_FIELDMODE_TEX_LOD(reg, x) ((reg) = GX_BITSET((reg), 31, 1, x)) + /****************************************************************************** * BP structure - TevColorCombiner *****************************************************************************/ // D [28:31] (4) -/* start bit */ #define GX_BP_TEVCOLORCOMBINER_D_B 28 -/* end bit */ #define GX_BP_TEVCOLORCOMBINER_D_E 31 -/* bit size */ #define GX_BP_TEVCOLORCOMBINER_D_SZ 4 + /* start bit */ #define GX_BP_TEVCOLORCOMBINER_D_B 28 + /* end bit */ #define GX_BP_TEVCOLORCOMBINER_D_E 31 + /* bit size */ #define GX_BP_TEVCOLORCOMBINER_D_SZ 4 -/* raw mask */ #define GX_BP_TEVCOLORCOMBINER_D_MASK \ - (((1 << 4) - 1) << 31 - 31) -/* local mask */ #define GX_BP_TEVCOLORCOMBINER_D_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_TEVCOLORCOMBINER_D_SHIFT 0 + /* raw mask */ #define GX_BP_TEVCOLORCOMBINER_D_MASK (((1 << 4) - 1) << 31 - 31) + /* local mask */ #define GX_BP_TEVCOLORCOMBINER_D_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_TEVCOLORCOMBINER_D_SHIFT 0 -/* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_D(reg) \ - GX_BITGET((reg), 28, 4) -/* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_D(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 4, x)) + /* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_D(reg) GX_BITGET((reg), 28, 4) + /* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_D(reg, x) ((reg) = GX_BITSET((reg), 28, 4, x)) // C [24:27] (4) -/* start bit */ #define GX_BP_TEVCOLORCOMBINER_C_B 24 -/* end bit */ #define GX_BP_TEVCOLORCOMBINER_C_E 27 -/* bit size */ #define GX_BP_TEVCOLORCOMBINER_C_SZ 4 + /* start bit */ #define GX_BP_TEVCOLORCOMBINER_C_B 24 + /* end bit */ #define GX_BP_TEVCOLORCOMBINER_C_E 27 + /* bit size */ #define GX_BP_TEVCOLORCOMBINER_C_SZ 4 -/* raw mask */ #define GX_BP_TEVCOLORCOMBINER_C_MASK \ - (((1 << 4) - 1) << 31 - 27) -/* local mask */ #define GX_BP_TEVCOLORCOMBINER_C_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_TEVCOLORCOMBINER_C_SHIFT 4 + /* raw mask */ #define GX_BP_TEVCOLORCOMBINER_C_MASK (((1 << 4) - 1) << 31 - 27) + /* local mask */ #define GX_BP_TEVCOLORCOMBINER_C_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_TEVCOLORCOMBINER_C_SHIFT 4 -/* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_C(reg) \ - GX_BITGET((reg), 24, 4) -/* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_C(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 4, x)) + /* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_C(reg) GX_BITGET((reg), 24, 4) + /* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_C(reg, x) ((reg) = GX_BITSET((reg), 24, 4, x)) // B [20:23] (4) -/* start bit */ #define GX_BP_TEVCOLORCOMBINER_B_B 20 -/* end bit */ #define GX_BP_TEVCOLORCOMBINER_B_E 23 -/* bit size */ #define GX_BP_TEVCOLORCOMBINER_B_SZ 4 + /* start bit */ #define GX_BP_TEVCOLORCOMBINER_B_B 20 + /* end bit */ #define GX_BP_TEVCOLORCOMBINER_B_E 23 + /* bit size */ #define GX_BP_TEVCOLORCOMBINER_B_SZ 4 -/* raw mask */ #define GX_BP_TEVCOLORCOMBINER_B_MASK \ - (((1 << 4) - 1) << 31 - 23) -/* local mask */ #define GX_BP_TEVCOLORCOMBINER_B_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_TEVCOLORCOMBINER_B_SHIFT 8 + /* raw mask */ #define GX_BP_TEVCOLORCOMBINER_B_MASK (((1 << 4) - 1) << 31 - 23) + /* local mask */ #define GX_BP_TEVCOLORCOMBINER_B_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_TEVCOLORCOMBINER_B_SHIFT 8 -/* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_B(reg) \ - GX_BITGET((reg), 20, 4) -/* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_B(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 4, x)) + /* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_B(reg) GX_BITGET((reg), 20, 4) + /* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_B(reg, x) ((reg) = GX_BITSET((reg), 20, 4, x)) // A [16:19] (4) -/* start bit */ #define GX_BP_TEVCOLORCOMBINER_A_B 16 -/* end bit */ #define GX_BP_TEVCOLORCOMBINER_A_E 19 -/* bit size */ #define GX_BP_TEVCOLORCOMBINER_A_SZ 4 + /* start bit */ #define GX_BP_TEVCOLORCOMBINER_A_B 16 + /* end bit */ #define GX_BP_TEVCOLORCOMBINER_A_E 19 + /* bit size */ #define GX_BP_TEVCOLORCOMBINER_A_SZ 4 -/* raw mask */ #define GX_BP_TEVCOLORCOMBINER_A_MASK \ - (((1 << 4) - 1) << 31 - 19) -/* local mask */ #define GX_BP_TEVCOLORCOMBINER_A_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_BP_TEVCOLORCOMBINER_A_SHIFT 12 + /* raw mask */ #define GX_BP_TEVCOLORCOMBINER_A_MASK (((1 << 4) - 1) << 31 - 19) + /* local mask */ #define GX_BP_TEVCOLORCOMBINER_A_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_BP_TEVCOLORCOMBINER_A_SHIFT 12 -/* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_A(reg) \ - GX_BITGET((reg), 16, 4) -/* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_A(reg, x) \ - ((reg) = GX_BITSET((reg), 16, 4, x)) + /* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_A(reg) GX_BITGET((reg), 16, 4) + /* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_A(reg, x) ((reg) = GX_BITSET((reg), 16, 4, x)) // BIAS [14:15] (2) -/* start bit */ #define GX_BP_TEVCOLORCOMBINER_BIAS_B 14 -/* end bit */ #define GX_BP_TEVCOLORCOMBINER_BIAS_E 15 -/* bit size */ #define GX_BP_TEVCOLORCOMBINER_BIAS_SZ 2 + /* start bit */ #define GX_BP_TEVCOLORCOMBINER_BIAS_B 14 + /* end bit */ #define GX_BP_TEVCOLORCOMBINER_BIAS_E 15 + /* bit size */ #define GX_BP_TEVCOLORCOMBINER_BIAS_SZ 2 -/* raw mask */ #define GX_BP_TEVCOLORCOMBINER_BIAS_MASK \ - (((1 << 2) - 1) << 31 - 15) -/* local mask */ #define GX_BP_TEVCOLORCOMBINER_BIAS_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_TEVCOLORCOMBINER_BIAS_SHIFT 16 + /* raw mask */ #define GX_BP_TEVCOLORCOMBINER_BIAS_MASK (((1 << 2) - 1) << 31 - 15) + /* local mask */ #define GX_BP_TEVCOLORCOMBINER_BIAS_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_TEVCOLORCOMBINER_BIAS_SHIFT 16 -/* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_BIAS(reg) \ - GX_BITGET((reg), 14, 2) -/* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_BIAS(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 2, x)) + /* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_BIAS(reg) GX_BITGET((reg), 14, 2) + /* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_BIAS(reg, x) ((reg) = GX_BITSET((reg), 14, 2, x)) // OP_OR_COMPARISON [13:13] (1) -/* start bit */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_B 13 -/* end bit */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_E 13 -/* bit size */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_SZ 1 + /* start bit */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_B 13 + /* end bit */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_E 13 + /* bit size */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_SZ 1 -/* raw mask */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_MASK \ - (((1 << 1) - 1) << 31 - 13) -/* local mask */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_LMASK \ - ((1 << 1) - 1) -/* bit shift */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_SHIFT 18 + /* raw mask */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_MASK (((1 << 1) - 1) << 31 - 13) + /* local mask */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_TEVCOLORCOMBINER_OP_OR_COMPARISON_SHIFT 18 -/* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_OP_OR_COMPARISON(reg) \ - GX_BITGET((reg), 13, 1) -/* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_OP_OR_COMPARISON(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 1, x)) + /* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_OP_OR_COMPARISON(reg) GX_BITGET((reg), 13, 1) + /* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_OP_OR_COMPARISON(reg, x) ((reg) = GX_BITSET((reg), 13, 1, x)) // CLAMP [12:12] (1) -/* start bit */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_B 12 -/* end bit */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_E 12 -/* bit size */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_SZ 1 + /* start bit */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_B 12 + /* end bit */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_E 12 + /* bit size */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_SZ 1 -/* raw mask */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_MASK \ - (((1 << 1) - 1) << 31 - 12) -/* local mask */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_SHIFT 19 + /* raw mask */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_MASK (((1 << 1) - 1) << 31 - 12) + /* local mask */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_TEVCOLORCOMBINER_CLAMP_SHIFT 19 -/* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_CLAMP(reg) \ - GX_BITGET((reg), 12, 1) -/* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_CLAMP(reg, x) \ - ((reg) = GX_BITSET((reg), 12, 1, x)) + /* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_CLAMP(reg) GX_BITGET((reg), 12, 1) + /* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_CLAMP(reg, x) ((reg) = GX_BITSET((reg), 12, 1, x)) // SCALE_OR_COMPARE_MODE [10:11] (2) -/* start bit */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_B 10 -/* end bit */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_E 11 -/* bit size */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_SZ 2 - -/* raw mask */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_MASK \ - (((1 << 2) - 1) << 31 - 11) -/* local mask */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_LMASK \ - ((1 << 2) - 1) -/* bit shift */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_SHIFT 20 - -/* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE(reg) \ - GX_BITGET((reg), 10, 2) -/* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE(reg, \ - x) \ - ((reg) = GX_BITSET((reg), 10, 2, x)) + /* start bit */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_B 10 + /* end bit */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_E 11 + /* bit size */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_SZ 2 + + /* raw mask */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_MASK (((1 << 2) - 1) << 31 - 11) + /* local mask */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE_SHIFT 20 + + /* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE(reg) GX_BITGET((reg), 10, 2) + /* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_SCALE_OR_COMPARE_MODE(reg, x) ((reg) = GX_BITSET((reg), 10, 2, x)) // DEST [8:9] (2) -/* start bit */ #define GX_BP_TEVCOLORCOMBINER_DEST_B 8 -/* end bit */ #define GX_BP_TEVCOLORCOMBINER_DEST_E 9 -/* bit size */ #define GX_BP_TEVCOLORCOMBINER_DEST_SZ 2 + /* start bit */ #define GX_BP_TEVCOLORCOMBINER_DEST_B 8 + /* end bit */ #define GX_BP_TEVCOLORCOMBINER_DEST_E 9 + /* bit size */ #define GX_BP_TEVCOLORCOMBINER_DEST_SZ 2 + + /* raw mask */ #define GX_BP_TEVCOLORCOMBINER_DEST_MASK (((1 << 2) - 1) << 31 - 9) + /* local mask */ #define GX_BP_TEVCOLORCOMBINER_DEST_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_TEVCOLORCOMBINER_DEST_SHIFT 22 -/* raw mask */ #define GX_BP_TEVCOLORCOMBINER_DEST_MASK \ - (((1 << 2) - 1) << 31 - 9) -/* local mask */ #define GX_BP_TEVCOLORCOMBINER_DEST_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_TEVCOLORCOMBINER_DEST_SHIFT 22 + /* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_DEST(reg) GX_BITGET((reg), 8, 2) + /* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_DEST(reg, x) ((reg) = GX_BITSET((reg), 8, 2, x)) -/* get value */ #define GX_BP_GET_TEVCOLORCOMBINER_DEST(reg) \ - GX_BITGET((reg), 8, 2) -/* set value */ #define GX_BP_SET_TEVCOLORCOMBINER_DEST(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 2, x)) /****************************************************************************** * BP structure - TevRegLo *****************************************************************************/ // RED [21:31] (11) -/* start bit */ #define GX_BP_TEVREGLO_RED_B 21 -/* end bit */ #define GX_BP_TEVREGLO_RED_E 31 -/* bit size */ #define GX_BP_TEVREGLO_RED_SZ 11 + /* start bit */ #define GX_BP_TEVREGLO_RED_B 21 + /* end bit */ #define GX_BP_TEVREGLO_RED_E 31 + /* bit size */ #define GX_BP_TEVREGLO_RED_SZ 11 -/* raw mask */ #define GX_BP_TEVREGLO_RED_MASK (((1 << 11) - 1) << 31 - 31) -/* local mask */ #define GX_BP_TEVREGLO_RED_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_TEVREGLO_RED_SHIFT 0 + /* raw mask */ #define GX_BP_TEVREGLO_RED_MASK (((1 << 11) - 1) << 31 - 31) + /* local mask */ #define GX_BP_TEVREGLO_RED_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_TEVREGLO_RED_SHIFT 0 -/* get value */ #define GX_BP_GET_TEVREGLO_RED(reg) GX_BITGET((reg), 21, 11) -/* set value */ #define GX_BP_SET_TEVREGLO_RED(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 11, x)) + /* get value */ #define GX_BP_GET_TEVREGLO_RED(reg) GX_BITGET((reg), 21, 11) + /* set value */ #define GX_BP_SET_TEVREGLO_RED(reg, x) ((reg) = GX_BITSET((reg), 21, 11, x)) // ALPHA [9:19] (11) -/* start bit */ #define GX_BP_TEVREGLO_ALPHA_B 9 -/* end bit */ #define GX_BP_TEVREGLO_ALPHA_E 19 -/* bit size */ #define GX_BP_TEVREGLO_ALPHA_SZ 11 + /* start bit */ #define GX_BP_TEVREGLO_ALPHA_B 9 + /* end bit */ #define GX_BP_TEVREGLO_ALPHA_E 19 + /* bit size */ #define GX_BP_TEVREGLO_ALPHA_SZ 11 -/* raw mask */ #define GX_BP_TEVREGLO_ALPHA_MASK (((1 << 11) - 1) << 31 - 19) -/* local mask */ #define GX_BP_TEVREGLO_ALPHA_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_TEVREGLO_ALPHA_SHIFT 12 + /* raw mask */ #define GX_BP_TEVREGLO_ALPHA_MASK (((1 << 11) - 1) << 31 - 19) + /* local mask */ #define GX_BP_TEVREGLO_ALPHA_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_TEVREGLO_ALPHA_SHIFT 12 -/* get value */ #define GX_BP_GET_TEVREGLO_ALPHA(reg) GX_BITGET((reg), 9, 11) -/* set value */ #define GX_BP_SET_TEVREGLO_ALPHA(reg, x) \ - ((reg) = GX_BITSET((reg), 9, 11, x)) + /* get value */ #define GX_BP_GET_TEVREGLO_ALPHA(reg) GX_BITGET((reg), 9, 11) + /* set value */ #define GX_BP_SET_TEVREGLO_ALPHA(reg, x) ((reg) = GX_BITSET((reg), 9, 11, x)) // TYPE [8:8] (1) -/* start bit */ #define GX_BP_TEVREGLO_TYPE_B 8 -/* end bit */ #define GX_BP_TEVREGLO_TYPE_E 8 -/* bit size */ #define GX_BP_TEVREGLO_TYPE_SZ 1 + /* start bit */ #define GX_BP_TEVREGLO_TYPE_B 8 + /* end bit */ #define GX_BP_TEVREGLO_TYPE_E 8 + /* bit size */ #define GX_BP_TEVREGLO_TYPE_SZ 1 -/* raw mask */ #define GX_BP_TEVREGLO_TYPE_MASK (((1 << 1) - 1) << 31 - 8) -/* local mask */ #define GX_BP_TEVREGLO_TYPE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_TEVREGLO_TYPE_SHIFT 23 + /* raw mask */ #define GX_BP_TEVREGLO_TYPE_MASK (((1 << 1) - 1) << 31 - 8) + /* local mask */ #define GX_BP_TEVREGLO_TYPE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_TEVREGLO_TYPE_SHIFT 23 + + /* get value */ #define GX_BP_GET_TEVREGLO_TYPE(reg) GX_BITGET((reg), 8, 1) + /* set value */ #define GX_BP_SET_TEVREGLO_TYPE(reg, x) ((reg) = GX_BITSET((reg), 8, 1, x)) -/* get value */ #define GX_BP_GET_TEVREGLO_TYPE(reg) GX_BITGET((reg), 8, 1) -/* set value */ #define GX_BP_SET_TEVREGLO_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 1, x)) /****************************************************************************** * BP structure - TevRegHi *****************************************************************************/ // BLUE [21:31] (11) -/* start bit */ #define GX_BP_TEVREGHI_BLUE_B 21 -/* end bit */ #define GX_BP_TEVREGHI_BLUE_E 31 -/* bit size */ #define GX_BP_TEVREGHI_BLUE_SZ 11 + /* start bit */ #define GX_BP_TEVREGHI_BLUE_B 21 + /* end bit */ #define GX_BP_TEVREGHI_BLUE_E 31 + /* bit size */ #define GX_BP_TEVREGHI_BLUE_SZ 11 -/* raw mask */ #define GX_BP_TEVREGHI_BLUE_MASK (((1 << 11) - 1) << 31 - 31) -/* local mask */ #define GX_BP_TEVREGHI_BLUE_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_TEVREGHI_BLUE_SHIFT 0 + /* raw mask */ #define GX_BP_TEVREGHI_BLUE_MASK (((1 << 11) - 1) << 31 - 31) + /* local mask */ #define GX_BP_TEVREGHI_BLUE_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_TEVREGHI_BLUE_SHIFT 0 -/* get value */ #define GX_BP_GET_TEVREGHI_BLUE(reg) GX_BITGET((reg), 21, 11) -/* set value */ #define GX_BP_SET_TEVREGHI_BLUE(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 11, x)) + /* get value */ #define GX_BP_GET_TEVREGHI_BLUE(reg) GX_BITGET((reg), 21, 11) + /* set value */ #define GX_BP_SET_TEVREGHI_BLUE(reg, x) ((reg) = GX_BITSET((reg), 21, 11, x)) // GREEN [9:19] (11) -/* start bit */ #define GX_BP_TEVREGHI_GREEN_B 9 -/* end bit */ #define GX_BP_TEVREGHI_GREEN_E 19 -/* bit size */ #define GX_BP_TEVREGHI_GREEN_SZ 11 + /* start bit */ #define GX_BP_TEVREGHI_GREEN_B 9 + /* end bit */ #define GX_BP_TEVREGHI_GREEN_E 19 + /* bit size */ #define GX_BP_TEVREGHI_GREEN_SZ 11 -/* raw mask */ #define GX_BP_TEVREGHI_GREEN_MASK (((1 << 11) - 1) << 31 - 19) -/* local mask */ #define GX_BP_TEVREGHI_GREEN_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_TEVREGHI_GREEN_SHIFT 12 + /* raw mask */ #define GX_BP_TEVREGHI_GREEN_MASK (((1 << 11) - 1) << 31 - 19) + /* local mask */ #define GX_BP_TEVREGHI_GREEN_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_TEVREGHI_GREEN_SHIFT 12 -/* get value */ #define GX_BP_GET_TEVREGHI_GREEN(reg) GX_BITGET((reg), 9, 11) -/* set value */ #define GX_BP_SET_TEVREGHI_GREEN(reg, x) \ - ((reg) = GX_BITSET((reg), 9, 11, x)) + /* get value */ #define GX_BP_GET_TEVREGHI_GREEN(reg) GX_BITGET((reg), 9, 11) + /* set value */ #define GX_BP_SET_TEVREGHI_GREEN(reg, x) ((reg) = GX_BITSET((reg), 9, 11, x)) // TYPE [8:8] (1) -/* start bit */ #define GX_BP_TEVREGHI_TYPE_B 8 -/* end bit */ #define GX_BP_TEVREGHI_TYPE_E 8 -/* bit size */ #define GX_BP_TEVREGHI_TYPE_SZ 1 + /* start bit */ #define GX_BP_TEVREGHI_TYPE_B 8 + /* end bit */ #define GX_BP_TEVREGHI_TYPE_E 8 + /* bit size */ #define GX_BP_TEVREGHI_TYPE_SZ 1 + + /* raw mask */ #define GX_BP_TEVREGHI_TYPE_MASK (((1 << 1) - 1) << 31 - 8) + /* local mask */ #define GX_BP_TEVREGHI_TYPE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_TEVREGHI_TYPE_SHIFT 23 -/* raw mask */ #define GX_BP_TEVREGHI_TYPE_MASK (((1 << 1) - 1) << 31 - 8) -/* local mask */ #define GX_BP_TEVREGHI_TYPE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_TEVREGHI_TYPE_SHIFT 23 + /* get value */ #define GX_BP_GET_TEVREGHI_TYPE(reg) GX_BITGET((reg), 8, 1) + /* set value */ #define GX_BP_SET_TEVREGHI_TYPE(reg, x) ((reg) = GX_BITSET((reg), 8, 1, x)) -/* get value */ #define GX_BP_GET_TEVREGHI_TYPE(reg) GX_BITGET((reg), 8, 1) -/* set value */ #define GX_BP_SET_TEVREGHI_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 1, x)) /****************************************************************************** * BP register 0xE8 - FogRange *****************************************************************************/ // CENTER [22:31] (10) -/* start bit */ #define GX_BP_FOGRANGE_CENTER_B 22 -/* end bit */ #define GX_BP_FOGRANGE_CENTER_E 31 -/* bit size */ #define GX_BP_FOGRANGE_CENTER_SZ 10 + /* start bit */ #define GX_BP_FOGRANGE_CENTER_B 22 + /* end bit */ #define GX_BP_FOGRANGE_CENTER_E 31 + /* bit size */ #define GX_BP_FOGRANGE_CENTER_SZ 10 -/* raw mask */ #define GX_BP_FOGRANGE_CENTER_MASK (((1 << 10) - 1) << 31 - 31) -/* local mask */ #define GX_BP_FOGRANGE_CENTER_LMASK ((1 << 10) - 1) -/* bit shift */ #define GX_BP_FOGRANGE_CENTER_SHIFT 0 + /* raw mask */ #define GX_BP_FOGRANGE_CENTER_MASK (((1 << 10) - 1) << 31 - 31) + /* local mask */ #define GX_BP_FOGRANGE_CENTER_LMASK ((1 << 10) - 1) + /* bit shift */ #define GX_BP_FOGRANGE_CENTER_SHIFT 0 -/* get value */ #define GX_BP_GET_FOGRANGE_CENTER(reg) GX_BITGET((reg), 22, 10) -/* set value */ #define GX_BP_SET_FOGRANGE_CENTER(reg, x) \ - ((reg) = GX_BITSET((reg), 22, 10, x)) + /* get value */ #define GX_BP_GET_FOGRANGE_CENTER(reg) GX_BITGET((reg), 22, 10) + /* set value */ #define GX_BP_SET_FOGRANGE_CENTER(reg, x) ((reg) = GX_BITSET((reg), 22, 10, x)) // ENABLED [21:21] (1) -/* start bit */ #define GX_BP_FOGRANGE_ENABLED_B 21 -/* end bit */ #define GX_BP_FOGRANGE_ENABLED_E 21 -/* bit size */ #define GX_BP_FOGRANGE_ENABLED_SZ 1 + /* start bit */ #define GX_BP_FOGRANGE_ENABLED_B 21 + /* end bit */ #define GX_BP_FOGRANGE_ENABLED_E 21 + /* bit size */ #define GX_BP_FOGRANGE_ENABLED_SZ 1 -/* raw mask */ #define GX_BP_FOGRANGE_ENABLED_MASK (((1 << 1) - 1) << 31 - 21) -/* local mask */ #define GX_BP_FOGRANGE_ENABLED_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_FOGRANGE_ENABLED_SHIFT 10 + /* raw mask */ #define GX_BP_FOGRANGE_ENABLED_MASK (((1 << 1) - 1) << 31 - 21) + /* local mask */ #define GX_BP_FOGRANGE_ENABLED_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_FOGRANGE_ENABLED_SHIFT 10 + + /* get value */ #define GX_BP_GET_FOGRANGE_ENABLED(reg) GX_BITGET((reg), 21, 1) + /* set value */ #define GX_BP_SET_FOGRANGE_ENABLED(reg, x) ((reg) = GX_BITSET((reg), 21, 1, x)) -/* get value */ #define GX_BP_GET_FOGRANGE_ENABLED(reg) GX_BITGET((reg), 21, 1) -/* set value */ #define GX_BP_SET_FOGRANGE_ENABLED(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 1, x)) /****************************************************************************** * BP structure - FogRangeK *****************************************************************************/ // HI [20:31] (12) -/* start bit */ #define GX_BP_FOGRANGEK_HI_B 20 -/* end bit */ #define GX_BP_FOGRANGEK_HI_E 31 -/* bit size */ #define GX_BP_FOGRANGEK_HI_SZ 12 + /* start bit */ #define GX_BP_FOGRANGEK_HI_B 20 + /* end bit */ #define GX_BP_FOGRANGEK_HI_E 31 + /* bit size */ #define GX_BP_FOGRANGEK_HI_SZ 12 -/* raw mask */ #define GX_BP_FOGRANGEK_HI_MASK (((1 << 12) - 1) << 31 - 31) -/* local mask */ #define GX_BP_FOGRANGEK_HI_LMASK ((1 << 12) - 1) -/* bit shift */ #define GX_BP_FOGRANGEK_HI_SHIFT 0 + /* raw mask */ #define GX_BP_FOGRANGEK_HI_MASK (((1 << 12) - 1) << 31 - 31) + /* local mask */ #define GX_BP_FOGRANGEK_HI_LMASK ((1 << 12) - 1) + /* bit shift */ #define GX_BP_FOGRANGEK_HI_SHIFT 0 -/* get value */ #define GX_BP_GET_FOGRANGEK_HI(reg) GX_BITGET((reg), 20, 12) -/* set value */ #define GX_BP_SET_FOGRANGEK_HI(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 12, x)) + /* get value */ #define GX_BP_GET_FOGRANGEK_HI(reg) GX_BITGET((reg), 20, 12) + /* set value */ #define GX_BP_SET_FOGRANGEK_HI(reg, x) ((reg) = GX_BITSET((reg), 20, 12, x)) // LO [8:19] (12) -/* start bit */ #define GX_BP_FOGRANGEK_LO_B 8 -/* end bit */ #define GX_BP_FOGRANGEK_LO_E 19 -/* bit size */ #define GX_BP_FOGRANGEK_LO_SZ 12 + /* start bit */ #define GX_BP_FOGRANGEK_LO_B 8 + /* end bit */ #define GX_BP_FOGRANGEK_LO_E 19 + /* bit size */ #define GX_BP_FOGRANGEK_LO_SZ 12 + + /* raw mask */ #define GX_BP_FOGRANGEK_LO_MASK (((1 << 12) - 1) << 31 - 19) + /* local mask */ #define GX_BP_FOGRANGEK_LO_LMASK ((1 << 12) - 1) + /* bit shift */ #define GX_BP_FOGRANGEK_LO_SHIFT 12 -/* raw mask */ #define GX_BP_FOGRANGEK_LO_MASK (((1 << 12) - 1) << 31 - 19) -/* local mask */ #define GX_BP_FOGRANGEK_LO_LMASK ((1 << 12) - 1) -/* bit shift */ #define GX_BP_FOGRANGEK_LO_SHIFT 12 + /* get value */ #define GX_BP_GET_FOGRANGEK_LO(reg) GX_BITGET((reg), 8, 12) + /* set value */ #define GX_BP_SET_FOGRANGEK_LO(reg, x) ((reg) = GX_BITSET((reg), 8, 12, x)) -/* get value */ #define GX_BP_GET_FOGRANGEK_LO(reg) GX_BITGET((reg), 8, 12) -/* set value */ #define GX_BP_SET_FOGRANGEK_LO(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 12, x)) /****************************************************************************** * BP register 0xEE - FogParam0 *****************************************************************************/ // A_MANT [21:31] (11) -/* start bit */ #define GX_BP_FOGPARAM0_A_MANT_B 21 -/* end bit */ #define GX_BP_FOGPARAM0_A_MANT_E 31 -/* bit size */ #define GX_BP_FOGPARAM0_A_MANT_SZ 11 + /* start bit */ #define GX_BP_FOGPARAM0_A_MANT_B 21 + /* end bit */ #define GX_BP_FOGPARAM0_A_MANT_E 31 + /* bit size */ #define GX_BP_FOGPARAM0_A_MANT_SZ 11 -/* raw mask */ #define GX_BP_FOGPARAM0_A_MANT_MASK \ - (((1 << 11) - 1) << 31 - 31) -/* local mask */ #define GX_BP_FOGPARAM0_A_MANT_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_FOGPARAM0_A_MANT_SHIFT 0 + /* raw mask */ #define GX_BP_FOGPARAM0_A_MANT_MASK (((1 << 11) - 1) << 31 - 31) + /* local mask */ #define GX_BP_FOGPARAM0_A_MANT_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_FOGPARAM0_A_MANT_SHIFT 0 -/* get value */ #define GX_BP_GET_FOGPARAM0_A_MANT(reg) \ - GX_BITGET((reg), 21, 11) -/* set value */ #define GX_BP_SET_FOGPARAM0_A_MANT(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 11, x)) + /* get value */ #define GX_BP_GET_FOGPARAM0_A_MANT(reg) GX_BITGET((reg), 21, 11) + /* set value */ #define GX_BP_SET_FOGPARAM0_A_MANT(reg, x) ((reg) = GX_BITSET((reg), 21, 11, x)) // A_EXP [13:20] (8) -/* start bit */ #define GX_BP_FOGPARAM0_A_EXP_B 13 -/* end bit */ #define GX_BP_FOGPARAM0_A_EXP_E 20 -/* bit size */ #define GX_BP_FOGPARAM0_A_EXP_SZ 8 + /* start bit */ #define GX_BP_FOGPARAM0_A_EXP_B 13 + /* end bit */ #define GX_BP_FOGPARAM0_A_EXP_E 20 + /* bit size */ #define GX_BP_FOGPARAM0_A_EXP_SZ 8 -/* raw mask */ #define GX_BP_FOGPARAM0_A_EXP_MASK (((1 << 8) - 1) << 31 - 20) -/* local mask */ #define GX_BP_FOGPARAM0_A_EXP_LMASK ((1 << 8) - 1) -/* bit shift */ #define GX_BP_FOGPARAM0_A_EXP_SHIFT 11 + /* raw mask */ #define GX_BP_FOGPARAM0_A_EXP_MASK (((1 << 8) - 1) << 31 - 20) + /* local mask */ #define GX_BP_FOGPARAM0_A_EXP_LMASK ((1 << 8) - 1) + /* bit shift */ #define GX_BP_FOGPARAM0_A_EXP_SHIFT 11 -/* get value */ #define GX_BP_GET_FOGPARAM0_A_EXP(reg) GX_BITGET((reg), 13, 8) -/* set value */ #define GX_BP_SET_FOGPARAM0_A_EXP(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 8, x)) + /* get value */ #define GX_BP_GET_FOGPARAM0_A_EXP(reg) GX_BITGET((reg), 13, 8) + /* set value */ #define GX_BP_SET_FOGPARAM0_A_EXP(reg, x) ((reg) = GX_BITSET((reg), 13, 8, x)) // A_SIGN [12:12] (1) -/* start bit */ #define GX_BP_FOGPARAM0_A_SIGN_B 12 -/* end bit */ #define GX_BP_FOGPARAM0_A_SIGN_E 12 -/* bit size */ #define GX_BP_FOGPARAM0_A_SIGN_SZ 1 + /* start bit */ #define GX_BP_FOGPARAM0_A_SIGN_B 12 + /* end bit */ #define GX_BP_FOGPARAM0_A_SIGN_E 12 + /* bit size */ #define GX_BP_FOGPARAM0_A_SIGN_SZ 1 -/* raw mask */ #define GX_BP_FOGPARAM0_A_SIGN_MASK (((1 << 1) - 1) << 31 - 12) -/* local mask */ #define GX_BP_FOGPARAM0_A_SIGN_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_FOGPARAM0_A_SIGN_SHIFT 19 + /* raw mask */ #define GX_BP_FOGPARAM0_A_SIGN_MASK (((1 << 1) - 1) << 31 - 12) + /* local mask */ #define GX_BP_FOGPARAM0_A_SIGN_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_FOGPARAM0_A_SIGN_SHIFT 19 + + /* get value */ #define GX_BP_GET_FOGPARAM0_A_SIGN(reg) GX_BITGET((reg), 12, 1) + /* set value */ #define GX_BP_SET_FOGPARAM0_A_SIGN(reg, x) ((reg) = GX_BITSET((reg), 12, 1, x)) -/* get value */ #define GX_BP_GET_FOGPARAM0_A_SIGN(reg) GX_BITGET((reg), 12, 1) -/* set value */ #define GX_BP_SET_FOGPARAM0_A_SIGN(reg, x) \ - ((reg) = GX_BITSET((reg), 12, 1, x)) /****************************************************************************** * BP register 0xEF - FogParam1 *****************************************************************************/ // B_MAG [8:31] (24) -/* start bit */ #define GX_BP_FOGPARAM1_B_MAG_B 8 -/* end bit */ #define GX_BP_FOGPARAM1_B_MAG_E 31 -/* bit size */ #define GX_BP_FOGPARAM1_B_MAG_SZ 24 + /* start bit */ #define GX_BP_FOGPARAM1_B_MAG_B 8 + /* end bit */ #define GX_BP_FOGPARAM1_B_MAG_E 31 + /* bit size */ #define GX_BP_FOGPARAM1_B_MAG_SZ 24 + + /* raw mask */ #define GX_BP_FOGPARAM1_B_MAG_MASK (((1 << 24) - 1) << 31 - 31) + /* local mask */ #define GX_BP_FOGPARAM1_B_MAG_LMASK ((1 << 24) - 1) + /* bit shift */ #define GX_BP_FOGPARAM1_B_MAG_SHIFT 0 -/* raw mask */ #define GX_BP_FOGPARAM1_B_MAG_MASK (((1 << 24) - 1) << 31 - 31) -/* local mask */ #define GX_BP_FOGPARAM1_B_MAG_LMASK ((1 << 24) - 1) -/* bit shift */ #define GX_BP_FOGPARAM1_B_MAG_SHIFT 0 + /* get value */ #define GX_BP_GET_FOGPARAM1_B_MAG(reg) GX_BITGET((reg), 8, 24) + /* set value */ #define GX_BP_SET_FOGPARAM1_B_MAG(reg, x) ((reg) = GX_BITSET((reg), 8, 24, x)) -/* get value */ #define GX_BP_GET_FOGPARAM1_B_MAG(reg) GX_BITGET((reg), 8, 24) -/* set value */ #define GX_BP_SET_FOGPARAM1_B_MAG(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 24, x)) /****************************************************************************** * BP register 0xF0 - FogParam2 *****************************************************************************/ // B_SHIFT [27:31] (5) -/* start bit */ #define GX_BP_FOGPARAM2_B_SHIFT_B 27 -/* end bit */ #define GX_BP_FOGPARAM2_B_SHIFT_E 31 -/* bit size */ #define GX_BP_FOGPARAM2_B_SHIFT_SZ 5 + /* start bit */ #define GX_BP_FOGPARAM2_B_SHIFT_B 27 + /* end bit */ #define GX_BP_FOGPARAM2_B_SHIFT_E 31 + /* bit size */ #define GX_BP_FOGPARAM2_B_SHIFT_SZ 5 + + /* raw mask */ #define GX_BP_FOGPARAM2_B_SHIFT_MASK (((1 << 5) - 1) << 31 - 31) + /* local mask */ #define GX_BP_FOGPARAM2_B_SHIFT_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_BP_FOGPARAM2_B_SHIFT_SHIFT 0 -/* raw mask */ #define GX_BP_FOGPARAM2_B_SHIFT_MASK \ - (((1 << 5) - 1) << 31 - 31) -/* local mask */ #define GX_BP_FOGPARAM2_B_SHIFT_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_BP_FOGPARAM2_B_SHIFT_SHIFT 0 + /* get value */ #define GX_BP_GET_FOGPARAM2_B_SHIFT(reg) GX_BITGET((reg), 27, 5) + /* set value */ #define GX_BP_SET_FOGPARAM2_B_SHIFT(reg, x) ((reg) = GX_BITSET((reg), 27, 5, x)) -/* get value */ #define GX_BP_GET_FOGPARAM2_B_SHIFT(reg) \ - GX_BITGET((reg), 27, 5) -/* set value */ #define GX_BP_SET_FOGPARAM2_B_SHIFT(reg, x) \ - ((reg) = GX_BITSET((reg), 27, 5, x)) /****************************************************************************** * BP register 0xF1 - FogParam3 *****************************************************************************/ // C_MANT [21:31] (11) -/* start bit */ #define GX_BP_FOGPARAM3_C_MANT_B 21 -/* end bit */ #define GX_BP_FOGPARAM3_C_MANT_E 31 -/* bit size */ #define GX_BP_FOGPARAM3_C_MANT_SZ 11 + /* start bit */ #define GX_BP_FOGPARAM3_C_MANT_B 21 + /* end bit */ #define GX_BP_FOGPARAM3_C_MANT_E 31 + /* bit size */ #define GX_BP_FOGPARAM3_C_MANT_SZ 11 -/* raw mask */ #define GX_BP_FOGPARAM3_C_MANT_MASK \ - (((1 << 11) - 1) << 31 - 31) -/* local mask */ #define GX_BP_FOGPARAM3_C_MANT_LMASK ((1 << 11) - 1) -/* bit shift */ #define GX_BP_FOGPARAM3_C_MANT_SHIFT 0 + /* raw mask */ #define GX_BP_FOGPARAM3_C_MANT_MASK (((1 << 11) - 1) << 31 - 31) + /* local mask */ #define GX_BP_FOGPARAM3_C_MANT_LMASK ((1 << 11) - 1) + /* bit shift */ #define GX_BP_FOGPARAM3_C_MANT_SHIFT 0 -/* get value */ #define GX_BP_GET_FOGPARAM3_C_MANT(reg) \ - GX_BITGET((reg), 21, 11) -/* set value */ #define GX_BP_SET_FOGPARAM3_C_MANT(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 11, x)) + /* get value */ #define GX_BP_GET_FOGPARAM3_C_MANT(reg) GX_BITGET((reg), 21, 11) + /* set value */ #define GX_BP_SET_FOGPARAM3_C_MANT(reg, x) ((reg) = GX_BITSET((reg), 21, 11, x)) // C_EXP [13:20] (8) -/* start bit */ #define GX_BP_FOGPARAM3_C_EXP_B 13 -/* end bit */ #define GX_BP_FOGPARAM3_C_EXP_E 20 -/* bit size */ #define GX_BP_FOGPARAM3_C_EXP_SZ 8 + /* start bit */ #define GX_BP_FOGPARAM3_C_EXP_B 13 + /* end bit */ #define GX_BP_FOGPARAM3_C_EXP_E 20 + /* bit size */ #define GX_BP_FOGPARAM3_C_EXP_SZ 8 -/* raw mask */ #define GX_BP_FOGPARAM3_C_EXP_MASK (((1 << 8) - 1) << 31 - 20) -/* local mask */ #define GX_BP_FOGPARAM3_C_EXP_LMASK ((1 << 8) - 1) -/* bit shift */ #define GX_BP_FOGPARAM3_C_EXP_SHIFT 11 + /* raw mask */ #define GX_BP_FOGPARAM3_C_EXP_MASK (((1 << 8) - 1) << 31 - 20) + /* local mask */ #define GX_BP_FOGPARAM3_C_EXP_LMASK ((1 << 8) - 1) + /* bit shift */ #define GX_BP_FOGPARAM3_C_EXP_SHIFT 11 -/* get value */ #define GX_BP_GET_FOGPARAM3_C_EXP(reg) GX_BITGET((reg), 13, 8) -/* set value */ #define GX_BP_SET_FOGPARAM3_C_EXP(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 8, x)) + /* get value */ #define GX_BP_GET_FOGPARAM3_C_EXP(reg) GX_BITGET((reg), 13, 8) + /* set value */ #define GX_BP_SET_FOGPARAM3_C_EXP(reg, x) ((reg) = GX_BITSET((reg), 13, 8, x)) // C_SIGN [12:12] (1) -/* start bit */ #define GX_BP_FOGPARAM3_C_SIGN_B 12 -/* end bit */ #define GX_BP_FOGPARAM3_C_SIGN_E 12 -/* bit size */ #define GX_BP_FOGPARAM3_C_SIGN_SZ 1 + /* start bit */ #define GX_BP_FOGPARAM3_C_SIGN_B 12 + /* end bit */ #define GX_BP_FOGPARAM3_C_SIGN_E 12 + /* bit size */ #define GX_BP_FOGPARAM3_C_SIGN_SZ 1 -/* raw mask */ #define GX_BP_FOGPARAM3_C_SIGN_MASK (((1 << 1) - 1) << 31 - 12) -/* local mask */ #define GX_BP_FOGPARAM3_C_SIGN_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_FOGPARAM3_C_SIGN_SHIFT 19 + /* raw mask */ #define GX_BP_FOGPARAM3_C_SIGN_MASK (((1 << 1) - 1) << 31 - 12) + /* local mask */ #define GX_BP_FOGPARAM3_C_SIGN_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_FOGPARAM3_C_SIGN_SHIFT 19 -/* get value */ #define GX_BP_GET_FOGPARAM3_C_SIGN(reg) GX_BITGET((reg), 12, 1) -/* set value */ #define GX_BP_SET_FOGPARAM3_C_SIGN(reg, x) \ - ((reg) = GX_BITSET((reg), 12, 1, x)) + /* get value */ #define GX_BP_GET_FOGPARAM3_C_SIGN(reg) GX_BITGET((reg), 12, 1) + /* set value */ #define GX_BP_SET_FOGPARAM3_C_SIGN(reg, x) ((reg) = GX_BITSET((reg), 12, 1, x)) // PROJ [11:11] (1) -/* start bit */ #define GX_BP_FOGPARAM3_PROJ_B 11 -/* end bit */ #define GX_BP_FOGPARAM3_PROJ_E 11 -/* bit size */ #define GX_BP_FOGPARAM3_PROJ_SZ 1 + /* start bit */ #define GX_BP_FOGPARAM3_PROJ_B 11 + /* end bit */ #define GX_BP_FOGPARAM3_PROJ_E 11 + /* bit size */ #define GX_BP_FOGPARAM3_PROJ_SZ 1 -/* raw mask */ #define GX_BP_FOGPARAM3_PROJ_MASK (((1 << 1) - 1) << 31 - 11) -/* local mask */ #define GX_BP_FOGPARAM3_PROJ_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_BP_FOGPARAM3_PROJ_SHIFT 20 + /* raw mask */ #define GX_BP_FOGPARAM3_PROJ_MASK (((1 << 1) - 1) << 31 - 11) + /* local mask */ #define GX_BP_FOGPARAM3_PROJ_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_BP_FOGPARAM3_PROJ_SHIFT 20 -/* get value */ #define GX_BP_GET_FOGPARAM3_PROJ(reg) GX_BITGET((reg), 11, 1) -/* set value */ #define GX_BP_SET_FOGPARAM3_PROJ(reg, x) \ - ((reg) = GX_BITSET((reg), 11, 1, x)) + /* get value */ #define GX_BP_GET_FOGPARAM3_PROJ(reg) GX_BITGET((reg), 11, 1) + /* set value */ #define GX_BP_SET_FOGPARAM3_PROJ(reg, x) ((reg) = GX_BITSET((reg), 11, 1, x)) // FSEL [8:10] (3) -/* start bit */ #define GX_BP_FOGPARAM3_FSEL_B 8 -/* end bit */ #define GX_BP_FOGPARAM3_FSEL_E 10 -/* bit size */ #define GX_BP_FOGPARAM3_FSEL_SZ 3 + /* start bit */ #define GX_BP_FOGPARAM3_FSEL_B 8 + /* end bit */ #define GX_BP_FOGPARAM3_FSEL_E 10 + /* bit size */ #define GX_BP_FOGPARAM3_FSEL_SZ 3 -/* raw mask */ #define GX_BP_FOGPARAM3_FSEL_MASK (((1 << 3) - 1) << 31 - 10) -/* local mask */ #define GX_BP_FOGPARAM3_FSEL_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_FOGPARAM3_FSEL_SHIFT 21 + /* raw mask */ #define GX_BP_FOGPARAM3_FSEL_MASK (((1 << 3) - 1) << 31 - 10) + /* local mask */ #define GX_BP_FOGPARAM3_FSEL_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_FOGPARAM3_FSEL_SHIFT 21 + + /* get value */ #define GX_BP_GET_FOGPARAM3_FSEL(reg) GX_BITGET((reg), 8, 3) + /* set value */ #define GX_BP_SET_FOGPARAM3_FSEL(reg, x) ((reg) = GX_BITSET((reg), 8, 3, x)) -/* get value */ #define GX_BP_GET_FOGPARAM3_FSEL(reg) GX_BITGET((reg), 8, 3) -/* set value */ #define GX_BP_SET_FOGPARAM3_FSEL(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 3, x)) /****************************************************************************** * BP register 0xF2 - FogColor *****************************************************************************/ // RGB [8:31] (24) -/* start bit */ #define GX_BP_FOGCOLOR_RGB_B 8 -/* end bit */ #define GX_BP_FOGCOLOR_RGB_E 31 -/* bit size */ #define GX_BP_FOGCOLOR_RGB_SZ 24 + /* start bit */ #define GX_BP_FOGCOLOR_RGB_B 8 + /* end bit */ #define GX_BP_FOGCOLOR_RGB_E 31 + /* bit size */ #define GX_BP_FOGCOLOR_RGB_SZ 24 + + /* raw mask */ #define GX_BP_FOGCOLOR_RGB_MASK (((1 << 24) - 1) << 31 - 31) + /* local mask */ #define GX_BP_FOGCOLOR_RGB_LMASK ((1 << 24) - 1) + /* bit shift */ #define GX_BP_FOGCOLOR_RGB_SHIFT 0 -/* raw mask */ #define GX_BP_FOGCOLOR_RGB_MASK (((1 << 24) - 1) << 31 - 31) -/* local mask */ #define GX_BP_FOGCOLOR_RGB_LMASK ((1 << 24) - 1) -/* bit shift */ #define GX_BP_FOGCOLOR_RGB_SHIFT 0 + /* get value */ #define GX_BP_GET_FOGCOLOR_RGB(reg) GX_BITGET((reg), 8, 24) + /* set value */ #define GX_BP_SET_FOGCOLOR_RGB(reg, x) ((reg) = GX_BITSET((reg), 8, 24, x)) -/* get value */ #define GX_BP_GET_FOGCOLOR_RGB(reg) GX_BITGET((reg), 8, 24) -/* set value */ #define GX_BP_SET_FOGCOLOR_RGB(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 24, x)) /****************************************************************************** * BP register 0xF3 - AlphaCompare *****************************************************************************/ // REF0 [24:31] (8) -/* start bit */ #define GX_BP_ALPHACOMPARE_REF0_B 24 -/* end bit */ #define GX_BP_ALPHACOMPARE_REF0_E 31 -/* bit size */ #define GX_BP_ALPHACOMPARE_REF0_SZ 8 + /* start bit */ #define GX_BP_ALPHACOMPARE_REF0_B 24 + /* end bit */ #define GX_BP_ALPHACOMPARE_REF0_E 31 + /* bit size */ #define GX_BP_ALPHACOMPARE_REF0_SZ 8 -/* raw mask */ #define GX_BP_ALPHACOMPARE_REF0_MASK \ - (((1 << 8) - 1) << 31 - 31) -/* local mask */ #define GX_BP_ALPHACOMPARE_REF0_LMASK ((1 << 8) - 1) -/* bit shift */ #define GX_BP_ALPHACOMPARE_REF0_SHIFT 0 + /* raw mask */ #define GX_BP_ALPHACOMPARE_REF0_MASK (((1 << 8) - 1) << 31 - 31) + /* local mask */ #define GX_BP_ALPHACOMPARE_REF0_LMASK ((1 << 8) - 1) + /* bit shift */ #define GX_BP_ALPHACOMPARE_REF0_SHIFT 0 -/* get value */ #define GX_BP_GET_ALPHACOMPARE_REF0(reg) \ - GX_BITGET((reg), 24, 8) -/* set value */ #define GX_BP_SET_ALPHACOMPARE_REF0(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 8, x)) + /* get value */ #define GX_BP_GET_ALPHACOMPARE_REF0(reg) GX_BITGET((reg), 24, 8) + /* set value */ #define GX_BP_SET_ALPHACOMPARE_REF0(reg, x) ((reg) = GX_BITSET((reg), 24, 8, x)) // REF1 [16:23] (8) -/* start bit */ #define GX_BP_ALPHACOMPARE_REF1_B 16 -/* end bit */ #define GX_BP_ALPHACOMPARE_REF1_E 23 -/* bit size */ #define GX_BP_ALPHACOMPARE_REF1_SZ 8 + /* start bit */ #define GX_BP_ALPHACOMPARE_REF1_B 16 + /* end bit */ #define GX_BP_ALPHACOMPARE_REF1_E 23 + /* bit size */ #define GX_BP_ALPHACOMPARE_REF1_SZ 8 -/* raw mask */ #define GX_BP_ALPHACOMPARE_REF1_MASK \ - (((1 << 8) - 1) << 31 - 23) -/* local mask */ #define GX_BP_ALPHACOMPARE_REF1_LMASK ((1 << 8) - 1) -/* bit shift */ #define GX_BP_ALPHACOMPARE_REF1_SHIFT 8 + /* raw mask */ #define GX_BP_ALPHACOMPARE_REF1_MASK (((1 << 8) - 1) << 31 - 23) + /* local mask */ #define GX_BP_ALPHACOMPARE_REF1_LMASK ((1 << 8) - 1) + /* bit shift */ #define GX_BP_ALPHACOMPARE_REF1_SHIFT 8 -/* get value */ #define GX_BP_GET_ALPHACOMPARE_REF1(reg) \ - GX_BITGET((reg), 16, 8) -/* set value */ #define GX_BP_SET_ALPHACOMPARE_REF1(reg, x) \ - ((reg) = GX_BITSET((reg), 16, 8, x)) + /* get value */ #define GX_BP_GET_ALPHACOMPARE_REF1(reg) GX_BITGET((reg), 16, 8) + /* set value */ #define GX_BP_SET_ALPHACOMPARE_REF1(reg, x) ((reg) = GX_BITSET((reg), 16, 8, x)) // COMP0 [13:15] (3) -/* start bit */ #define GX_BP_ALPHACOMPARE_COMP0_B 13 -/* end bit */ #define GX_BP_ALPHACOMPARE_COMP0_E 15 -/* bit size */ #define GX_BP_ALPHACOMPARE_COMP0_SZ 3 + /* start bit */ #define GX_BP_ALPHACOMPARE_COMP0_B 13 + /* end bit */ #define GX_BP_ALPHACOMPARE_COMP0_E 15 + /* bit size */ #define GX_BP_ALPHACOMPARE_COMP0_SZ 3 -/* raw mask */ #define GX_BP_ALPHACOMPARE_COMP0_MASK \ - (((1 << 3) - 1) << 31 - 15) -/* local mask */ #define GX_BP_ALPHACOMPARE_COMP0_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_ALPHACOMPARE_COMP0_SHIFT 16 + /* raw mask */ #define GX_BP_ALPHACOMPARE_COMP0_MASK (((1 << 3) - 1) << 31 - 15) + /* local mask */ #define GX_BP_ALPHACOMPARE_COMP0_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_ALPHACOMPARE_COMP0_SHIFT 16 -/* get value */ #define GX_BP_GET_ALPHACOMPARE_COMP0(reg) \ - GX_BITGET((reg), 13, 3) -/* set value */ #define GX_BP_SET_ALPHACOMPARE_COMP0(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 3, x)) + /* get value */ #define GX_BP_GET_ALPHACOMPARE_COMP0(reg) GX_BITGET((reg), 13, 3) + /* set value */ #define GX_BP_SET_ALPHACOMPARE_COMP0(reg, x) ((reg) = GX_BITSET((reg), 13, 3, x)) // COMP1 [10:12] (3) -/* start bit */ #define GX_BP_ALPHACOMPARE_COMP1_B 10 -/* end bit */ #define GX_BP_ALPHACOMPARE_COMP1_E 12 -/* bit size */ #define GX_BP_ALPHACOMPARE_COMP1_SZ 3 + /* start bit */ #define GX_BP_ALPHACOMPARE_COMP1_B 10 + /* end bit */ #define GX_BP_ALPHACOMPARE_COMP1_E 12 + /* bit size */ #define GX_BP_ALPHACOMPARE_COMP1_SZ 3 -/* raw mask */ #define GX_BP_ALPHACOMPARE_COMP1_MASK \ - (((1 << 3) - 1) << 31 - 12) -/* local mask */ #define GX_BP_ALPHACOMPARE_COMP1_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_BP_ALPHACOMPARE_COMP1_SHIFT 19 + /* raw mask */ #define GX_BP_ALPHACOMPARE_COMP1_MASK (((1 << 3) - 1) << 31 - 12) + /* local mask */ #define GX_BP_ALPHACOMPARE_COMP1_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_BP_ALPHACOMPARE_COMP1_SHIFT 19 -/* get value */ #define GX_BP_GET_ALPHACOMPARE_COMP1(reg) \ - GX_BITGET((reg), 10, 3) -/* set value */ #define GX_BP_SET_ALPHACOMPARE_COMP1(reg, x) \ - ((reg) = GX_BITSET((reg), 10, 3, x)) + /* get value */ #define GX_BP_GET_ALPHACOMPARE_COMP1(reg) GX_BITGET((reg), 10, 3) + /* set value */ #define GX_BP_SET_ALPHACOMPARE_COMP1(reg, x) ((reg) = GX_BITSET((reg), 10, 3, x)) // LOGIC [8:9] (2) -/* start bit */ #define GX_BP_ALPHACOMPARE_LOGIC_B 8 -/* end bit */ #define GX_BP_ALPHACOMPARE_LOGIC_E 9 -/* bit size */ #define GX_BP_ALPHACOMPARE_LOGIC_SZ 2 + /* start bit */ #define GX_BP_ALPHACOMPARE_LOGIC_B 8 + /* end bit */ #define GX_BP_ALPHACOMPARE_LOGIC_E 9 + /* bit size */ #define GX_BP_ALPHACOMPARE_LOGIC_SZ 2 + + /* raw mask */ #define GX_BP_ALPHACOMPARE_LOGIC_MASK (((1 << 2) - 1) << 31 - 9) + /* local mask */ #define GX_BP_ALPHACOMPARE_LOGIC_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_ALPHACOMPARE_LOGIC_SHIFT 22 -/* raw mask */ #define GX_BP_ALPHACOMPARE_LOGIC_MASK \ - (((1 << 2) - 1) << 31 - 9) -/* local mask */ #define GX_BP_ALPHACOMPARE_LOGIC_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_ALPHACOMPARE_LOGIC_SHIFT 22 + /* get value */ #define GX_BP_GET_ALPHACOMPARE_LOGIC(reg) GX_BITGET((reg), 8, 2) + /* set value */ #define GX_BP_SET_ALPHACOMPARE_LOGIC(reg, x) ((reg) = GX_BITSET((reg), 8, 2, x)) -/* get value */ #define GX_BP_GET_ALPHACOMPARE_LOGIC(reg) \ - GX_BITGET((reg), 8, 2) -/* set value */ #define GX_BP_SET_ALPHACOMPARE_LOGIC(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 2, x)) /****************************************************************************** * BP structure - TevKSel *****************************************************************************/ // SWAP_RB [30:31] (2) - Odd ksel number: red; even: blue -/* start bit */ #define GX_BP_TEVKSEL_SWAP_RB_B 30 -/* end bit */ #define GX_BP_TEVKSEL_SWAP_RB_E 31 -/* bit size */ #define GX_BP_TEVKSEL_SWAP_RB_SZ 2 + /* start bit */ #define GX_BP_TEVKSEL_SWAP_RB_B 30 + /* end bit */ #define GX_BP_TEVKSEL_SWAP_RB_E 31 + /* bit size */ #define GX_BP_TEVKSEL_SWAP_RB_SZ 2 -/* raw mask */ #define GX_BP_TEVKSEL_SWAP_RB_MASK (((1 << 2) - 1) << 31 - 31) -/* local mask */ #define GX_BP_TEVKSEL_SWAP_RB_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_TEVKSEL_SWAP_RB_SHIFT 0 + /* raw mask */ #define GX_BP_TEVKSEL_SWAP_RB_MASK (((1 << 2) - 1) << 31 - 31) + /* local mask */ #define GX_BP_TEVKSEL_SWAP_RB_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_TEVKSEL_SWAP_RB_SHIFT 0 -/* get value */ #define GX_BP_GET_TEVKSEL_SWAP_RB(reg) GX_BITGET((reg), 30, 2) -/* set value */ #define GX_BP_SET_TEVKSEL_SWAP_RB(reg, x) \ - ((reg) = GX_BITSET((reg), 30, 2, x)) + /* get value */ #define GX_BP_GET_TEVKSEL_SWAP_RB(reg) GX_BITGET((reg), 30, 2) + /* set value */ #define GX_BP_SET_TEVKSEL_SWAP_RB(reg, x) ((reg) = GX_BITSET((reg), 30, 2, x)) // SWAP_GA [28:29] (2) - Odd ksel number: green; even: alpha -/* start bit */ #define GX_BP_TEVKSEL_SWAP_GA_B 28 -/* end bit */ #define GX_BP_TEVKSEL_SWAP_GA_E 29 -/* bit size */ #define GX_BP_TEVKSEL_SWAP_GA_SZ 2 + /* start bit */ #define GX_BP_TEVKSEL_SWAP_GA_B 28 + /* end bit */ #define GX_BP_TEVKSEL_SWAP_GA_E 29 + /* bit size */ #define GX_BP_TEVKSEL_SWAP_GA_SZ 2 -/* raw mask */ #define GX_BP_TEVKSEL_SWAP_GA_MASK (((1 << 2) - 1) << 31 - 29) -/* local mask */ #define GX_BP_TEVKSEL_SWAP_GA_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_BP_TEVKSEL_SWAP_GA_SHIFT 2 + /* raw mask */ #define GX_BP_TEVKSEL_SWAP_GA_MASK (((1 << 2) - 1) << 31 - 29) + /* local mask */ #define GX_BP_TEVKSEL_SWAP_GA_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_BP_TEVKSEL_SWAP_GA_SHIFT 2 -/* get value */ #define GX_BP_GET_TEVKSEL_SWAP_GA(reg) GX_BITGET((reg), 28, 2) -/* set value */ #define GX_BP_SET_TEVKSEL_SWAP_GA(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 2, x)) + /* get value */ #define GX_BP_GET_TEVKSEL_SWAP_GA(reg) GX_BITGET((reg), 28, 2) + /* set value */ #define GX_BP_SET_TEVKSEL_SWAP_GA(reg, x) ((reg) = GX_BITSET((reg), 28, 2, x)) // KCSEL_EVEN [23:27] (5) -/* start bit */ #define GX_BP_TEVKSEL_KCSEL_EVEN_B 23 -/* end bit */ #define GX_BP_TEVKSEL_KCSEL_EVEN_E 27 -/* bit size */ #define GX_BP_TEVKSEL_KCSEL_EVEN_SZ 5 + /* start bit */ #define GX_BP_TEVKSEL_KCSEL_EVEN_B 23 + /* end bit */ #define GX_BP_TEVKSEL_KCSEL_EVEN_E 27 + /* bit size */ #define GX_BP_TEVKSEL_KCSEL_EVEN_SZ 5 -/* raw mask */ #define GX_BP_TEVKSEL_KCSEL_EVEN_MASK \ - (((1 << 5) - 1) << 31 - 27) -/* local mask */ #define GX_BP_TEVKSEL_KCSEL_EVEN_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_BP_TEVKSEL_KCSEL_EVEN_SHIFT 4 + /* raw mask */ #define GX_BP_TEVKSEL_KCSEL_EVEN_MASK (((1 << 5) - 1) << 31 - 27) + /* local mask */ #define GX_BP_TEVKSEL_KCSEL_EVEN_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_BP_TEVKSEL_KCSEL_EVEN_SHIFT 4 -/* get value */ #define GX_BP_GET_TEVKSEL_KCSEL_EVEN(reg) \ - GX_BITGET((reg), 23, 5) -/* set value */ #define GX_BP_SET_TEVKSEL_KCSEL_EVEN(reg, x) \ - ((reg) = GX_BITSET((reg), 23, 5, x)) + /* get value */ #define GX_BP_GET_TEVKSEL_KCSEL_EVEN(reg) GX_BITGET((reg), 23, 5) + /* set value */ #define GX_BP_SET_TEVKSEL_KCSEL_EVEN(reg, x) ((reg) = GX_BITSET((reg), 23, 5, x)) // KASEL_EVEN [18:22] (5) -/* start bit */ #define GX_BP_TEVKSEL_KASEL_EVEN_B 18 -/* end bit */ #define GX_BP_TEVKSEL_KASEL_EVEN_E 22 -/* bit size */ #define GX_BP_TEVKSEL_KASEL_EVEN_SZ 5 + /* start bit */ #define GX_BP_TEVKSEL_KASEL_EVEN_B 18 + /* end bit */ #define GX_BP_TEVKSEL_KASEL_EVEN_E 22 + /* bit size */ #define GX_BP_TEVKSEL_KASEL_EVEN_SZ 5 -/* raw mask */ #define GX_BP_TEVKSEL_KASEL_EVEN_MASK \ - (((1 << 5) - 1) << 31 - 22) -/* local mask */ #define GX_BP_TEVKSEL_KASEL_EVEN_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_BP_TEVKSEL_KASEL_EVEN_SHIFT 9 + /* raw mask */ #define GX_BP_TEVKSEL_KASEL_EVEN_MASK (((1 << 5) - 1) << 31 - 22) + /* local mask */ #define GX_BP_TEVKSEL_KASEL_EVEN_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_BP_TEVKSEL_KASEL_EVEN_SHIFT 9 -/* get value */ #define GX_BP_GET_TEVKSEL_KASEL_EVEN(reg) \ - GX_BITGET((reg), 18, 5) -/* set value */ #define GX_BP_SET_TEVKSEL_KASEL_EVEN(reg, x) \ - ((reg) = GX_BITSET((reg), 18, 5, x)) + /* get value */ #define GX_BP_GET_TEVKSEL_KASEL_EVEN(reg) GX_BITGET((reg), 18, 5) + /* set value */ #define GX_BP_SET_TEVKSEL_KASEL_EVEN(reg, x) ((reg) = GX_BITSET((reg), 18, 5, x)) // KCSEL_ODD [13:17] (5) -/* start bit */ #define GX_BP_TEVKSEL_KCSEL_ODD_B 13 -/* end bit */ #define GX_BP_TEVKSEL_KCSEL_ODD_E 17 -/* bit size */ #define GX_BP_TEVKSEL_KCSEL_ODD_SZ 5 + /* start bit */ #define GX_BP_TEVKSEL_KCSEL_ODD_B 13 + /* end bit */ #define GX_BP_TEVKSEL_KCSEL_ODD_E 17 + /* bit size */ #define GX_BP_TEVKSEL_KCSEL_ODD_SZ 5 -/* raw mask */ #define GX_BP_TEVKSEL_KCSEL_ODD_MASK \ - (((1 << 5) - 1) << 31 - 17) -/* local mask */ #define GX_BP_TEVKSEL_KCSEL_ODD_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_BP_TEVKSEL_KCSEL_ODD_SHIFT 14 + /* raw mask */ #define GX_BP_TEVKSEL_KCSEL_ODD_MASK (((1 << 5) - 1) << 31 - 17) + /* local mask */ #define GX_BP_TEVKSEL_KCSEL_ODD_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_BP_TEVKSEL_KCSEL_ODD_SHIFT 14 -/* get value */ #define GX_BP_GET_TEVKSEL_KCSEL_ODD(reg) \ - GX_BITGET((reg), 13, 5) -/* set value */ #define GX_BP_SET_TEVKSEL_KCSEL_ODD(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 5, x)) + /* get value */ #define GX_BP_GET_TEVKSEL_KCSEL_ODD(reg) GX_BITGET((reg), 13, 5) + /* set value */ #define GX_BP_SET_TEVKSEL_KCSEL_ODD(reg, x) ((reg) = GX_BITSET((reg), 13, 5, x)) // KASEL_ODD [8:12] (5) -/* start bit */ #define GX_BP_TEVKSEL_KASEL_ODD_B 8 -/* end bit */ #define GX_BP_TEVKSEL_KASEL_ODD_E 12 -/* bit size */ #define GX_BP_TEVKSEL_KASEL_ODD_SZ 5 + /* start bit */ #define GX_BP_TEVKSEL_KASEL_ODD_B 8 + /* end bit */ #define GX_BP_TEVKSEL_KASEL_ODD_E 12 + /* bit size */ #define GX_BP_TEVKSEL_KASEL_ODD_SZ 5 + + /* raw mask */ #define GX_BP_TEVKSEL_KASEL_ODD_MASK (((1 << 5) - 1) << 31 - 12) + /* local mask */ #define GX_BP_TEVKSEL_KASEL_ODD_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_BP_TEVKSEL_KASEL_ODD_SHIFT 19 + + /* get value */ #define GX_BP_GET_TEVKSEL_KASEL_ODD(reg) GX_BITGET((reg), 8, 5) + /* set value */ #define GX_BP_SET_TEVKSEL_KASEL_ODD(reg, x) ((reg) = GX_BITSET((reg), 8, 5, x)) -/* raw mask */ #define GX_BP_TEVKSEL_KASEL_ODD_MASK \ - (((1 << 5) - 1) << 31 - 12) -/* local mask */ #define GX_BP_TEVKSEL_KASEL_ODD_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_BP_TEVKSEL_KASEL_ODD_SHIFT 19 -/* get value */ #define GX_BP_GET_TEVKSEL_KASEL_ODD(reg) GX_BITGET((reg), 8, 5) -/* set value */ #define GX_BP_SET_TEVKSEL_KASEL_ODD(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 5, x)) #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/GX/GXHardwareCP.h b/include/revolution/GX/GXHardwareCP.h index cbc72e9..8c7a709 100644 --- a/include/revolution/GX/GXHardwareCP.h +++ b/include/revolution/GX/GXHardwareCP.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_GX_HARDWARE_CP_H #define RVL_SDK_GX_HARDWARE_CP_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif @@ -34,1008 +33,844 @@ typedef enum { * CP register 0x30 - MatrixIndexA *****************************************************************************/ // TEX3 [2:7] (6) -/* start bit */ #define GX_CP_MATRIXINDEXA_TEX3_B 2 -/* end bit */ #define GX_CP_MATRIXINDEXA_TEX3_E 7 -/* bit size */ #define GX_CP_MATRIXINDEXA_TEX3_SZ 6 + /* start bit */ #define GX_CP_MATRIXINDEXA_TEX3_B 2 + /* end bit */ #define GX_CP_MATRIXINDEXA_TEX3_E 7 + /* bit size */ #define GX_CP_MATRIXINDEXA_TEX3_SZ 6 -/* raw mask */ #define GX_CP_MATRIXINDEXA_TEX3_MASK (((1 << 6) - 1) << 31 - 7) -/* local mask */ #define GX_CP_MATRIXINDEXA_TEX3_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_CP_MATRIXINDEXA_TEX3_SHIFT 24 + /* raw mask */ #define GX_CP_MATRIXINDEXA_TEX3_MASK (((1 << 6) - 1) << 31 - 7) + /* local mask */ #define GX_CP_MATRIXINDEXA_TEX3_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_CP_MATRIXINDEXA_TEX3_SHIFT 24 -/* get value */ #define GX_CP_GET_MATRIXINDEXA_TEX3(reg) GX_BITGET((reg), 2, 6) -/* set value */ #define GX_CP_SET_MATRIXINDEXA_TEX3(reg, x) \ - ((reg) = GX_BITSET((reg), 2, 6, x)) + /* get value */ #define GX_CP_GET_MATRIXINDEXA_TEX3(reg) GX_BITGET((reg), 2, 6) + /* set value */ #define GX_CP_SET_MATRIXINDEXA_TEX3(reg, x) ((reg) = GX_BITSET((reg), 2, 6, x)) // TEX2 [8:13] (6) -/* start bit */ #define GX_CP_MATRIXINDEXA_TEX2_B 8 -/* end bit */ #define GX_CP_MATRIXINDEXA_TEX2_E 13 -/* bit size */ #define GX_CP_MATRIXINDEXA_TEX2_SZ 6 + /* start bit */ #define GX_CP_MATRIXINDEXA_TEX2_B 8 + /* end bit */ #define GX_CP_MATRIXINDEXA_TEX2_E 13 + /* bit size */ #define GX_CP_MATRIXINDEXA_TEX2_SZ 6 -/* raw mask */ #define GX_CP_MATRIXINDEXA_TEX2_MASK \ - (((1 << 6) - 1) << 31 - 13) -/* local mask */ #define GX_CP_MATRIXINDEXA_TEX2_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_CP_MATRIXINDEXA_TEX2_SHIFT 18 + /* raw mask */ #define GX_CP_MATRIXINDEXA_TEX2_MASK (((1 << 6) - 1) << 31 - 13) + /* local mask */ #define GX_CP_MATRIXINDEXA_TEX2_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_CP_MATRIXINDEXA_TEX2_SHIFT 18 -/* get value */ #define GX_CP_GET_MATRIXINDEXA_TEX2(reg) GX_BITGET((reg), 8, 6) -/* set value */ #define GX_CP_SET_MATRIXINDEXA_TEX2(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 6, x)) + /* get value */ #define GX_CP_GET_MATRIXINDEXA_TEX2(reg) GX_BITGET((reg), 8, 6) + /* set value */ #define GX_CP_SET_MATRIXINDEXA_TEX2(reg, x) ((reg) = GX_BITSET((reg), 8, 6, x)) // TEX1 [14:19] (6) -/* start bit */ #define GX_CP_MATRIXINDEXA_TEX1_B 14 -/* end bit */ #define GX_CP_MATRIXINDEXA_TEX1_E 19 -/* bit size */ #define GX_CP_MATRIXINDEXA_TEX1_SZ 6 + /* start bit */ #define GX_CP_MATRIXINDEXA_TEX1_B 14 + /* end bit */ #define GX_CP_MATRIXINDEXA_TEX1_E 19 + /* bit size */ #define GX_CP_MATRIXINDEXA_TEX1_SZ 6 -/* raw mask */ #define GX_CP_MATRIXINDEXA_TEX1_MASK \ - (((1 << 6) - 1) << 31 - 19) -/* local mask */ #define GX_CP_MATRIXINDEXA_TEX1_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_CP_MATRIXINDEXA_TEX1_SHIFT 12 + /* raw mask */ #define GX_CP_MATRIXINDEXA_TEX1_MASK (((1 << 6) - 1) << 31 - 19) + /* local mask */ #define GX_CP_MATRIXINDEXA_TEX1_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_CP_MATRIXINDEXA_TEX1_SHIFT 12 -/* get value */ #define GX_CP_GET_MATRIXINDEXA_TEX1(reg) \ - GX_BITGET((reg), 14, 6) -/* set value */ #define GX_CP_SET_MATRIXINDEXA_TEX1(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 6, x)) + /* get value */ #define GX_CP_GET_MATRIXINDEXA_TEX1(reg) GX_BITGET((reg), 14, 6) + /* set value */ #define GX_CP_SET_MATRIXINDEXA_TEX1(reg, x) ((reg) = GX_BITSET((reg), 14, 6, x)) // TEX0 [20:25] (6) -/* start bit */ #define GX_CP_MATRIXINDEXA_TEX0_B 20 -/* end bit */ #define GX_CP_MATRIXINDEXA_TEX0_E 25 -/* bit size */ #define GX_CP_MATRIXINDEXA_TEX0_SZ 6 + /* start bit */ #define GX_CP_MATRIXINDEXA_TEX0_B 20 + /* end bit */ #define GX_CP_MATRIXINDEXA_TEX0_E 25 + /* bit size */ #define GX_CP_MATRIXINDEXA_TEX0_SZ 6 -/* raw mask */ #define GX_CP_MATRIXINDEXA_TEX0_MASK \ - (((1 << 6) - 1) << 31 - 25) -/* local mask */ #define GX_CP_MATRIXINDEXA_TEX0_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_CP_MATRIXINDEXA_TEX0_SHIFT 6 + /* raw mask */ #define GX_CP_MATRIXINDEXA_TEX0_MASK (((1 << 6) - 1) << 31 - 25) + /* local mask */ #define GX_CP_MATRIXINDEXA_TEX0_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_CP_MATRIXINDEXA_TEX0_SHIFT 6 -/* get value */ #define GX_CP_GET_MATRIXINDEXA_TEX0(reg) \ - GX_BITGET((reg), 20, 6) -/* set value */ #define GX_CP_SET_MATRIXINDEXA_TEX0(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 6, x)) + /* get value */ #define GX_CP_GET_MATRIXINDEXA_TEX0(reg) GX_BITGET((reg), 20, 6) + /* set value */ #define GX_CP_SET_MATRIXINDEXA_TEX0(reg, x) ((reg) = GX_BITSET((reg), 20, 6, x)) // POSNRM [26:31] (6) -/* start bit */ #define GX_CP_MATRIXINDEXA_POSNRM_B 26 -/* end bit */ #define GX_CP_MATRIXINDEXA_POSNRM_E 31 -/* bit size */ #define GX_CP_MATRIXINDEXA_POSNRM_SZ 6 + /* start bit */ #define GX_CP_MATRIXINDEXA_POSNRM_B 26 + /* end bit */ #define GX_CP_MATRIXINDEXA_POSNRM_E 31 + /* bit size */ #define GX_CP_MATRIXINDEXA_POSNRM_SZ 6 -/* raw mask */ #define GX_CP_MATRIXINDEXA_POSNRM_MASK \ - (((1 << 6) - 1) << 31 - 31) -/* local mask */ #define GX_CP_MATRIXINDEXA_POSNRM_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_CP_MATRIXINDEXA_POSNRM_SHIFT 0 + /* raw mask */ #define GX_CP_MATRIXINDEXA_POSNRM_MASK (((1 << 6) - 1) << 31 - 31) + /* local mask */ #define GX_CP_MATRIXINDEXA_POSNRM_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_CP_MATRIXINDEXA_POSNRM_SHIFT 0 + + /* get value */ #define GX_CP_GET_MATRIXINDEXA_POSNRM(reg) GX_BITGET((reg), 26, 6) + /* set value */ #define GX_CP_SET_MATRIXINDEXA_POSNRM(reg, x) ((reg) = GX_BITSET((reg), 26, 6, x)) -/* get value */ #define GX_CP_GET_MATRIXINDEXA_POSNRM(reg) \ - GX_BITGET((reg), 26, 6) -/* set value */ #define GX_CP_SET_MATRIXINDEXA_POSNRM(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 6, x)) /****************************************************************************** * CP register 0x40 - MatrixIndexB *****************************************************************************/ // TEX7 [8:13] (6) -/* start bit */ #define GX_CP_MATRIXINDEXB_TEX7_B 8 -/* end bit */ #define GX_CP_MATRIXINDEXB_TEX7_E 13 -/* bit size */ #define GX_CP_MATRIXINDEXB_TEX7_SZ 6 + /* start bit */ #define GX_CP_MATRIXINDEXB_TEX7_B 8 + /* end bit */ #define GX_CP_MATRIXINDEXB_TEX7_E 13 + /* bit size */ #define GX_CP_MATRIXINDEXB_TEX7_SZ 6 -/* raw mask */ #define GX_CP_MATRIXINDEXB_TEX7_MASK \ - (((1 << 6) - 1) << 31 - 13) -/* local mask */ #define GX_CP_MATRIXINDEXB_TEX7_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_CP_MATRIXINDEXB_TEX7_SHIFT 18 + /* raw mask */ #define GX_CP_MATRIXINDEXB_TEX7_MASK (((1 << 6) - 1) << 31 - 13) + /* local mask */ #define GX_CP_MATRIXINDEXB_TEX7_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_CP_MATRIXINDEXB_TEX7_SHIFT 18 -/* get value */ #define GX_CP_GET_MATRIXINDEXB_TEX7(reg) GX_BITGET((reg), 8, 6) -/* set value */ #define GX_CP_SET_MATRIXINDEXB_TEX7(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 6, x)) + /* get value */ #define GX_CP_GET_MATRIXINDEXB_TEX7(reg) GX_BITGET((reg), 8, 6) + /* set value */ #define GX_CP_SET_MATRIXINDEXB_TEX7(reg, x) ((reg) = GX_BITSET((reg), 8, 6, x)) // TEX6 [14:19] (6) -/* start bit */ #define GX_CP_MATRIXINDEXB_TEX6_B 14 -/* end bit */ #define GX_CP_MATRIXINDEXB_TEX6_E 19 -/* bit size */ #define GX_CP_MATRIXINDEXB_TEX6_SZ 6 + /* start bit */ #define GX_CP_MATRIXINDEXB_TEX6_B 14 + /* end bit */ #define GX_CP_MATRIXINDEXB_TEX6_E 19 + /* bit size */ #define GX_CP_MATRIXINDEXB_TEX6_SZ 6 -/* raw mask */ #define GX_CP_MATRIXINDEXB_TEX6_MASK \ - (((1 << 6) - 1) << 31 - 19) -/* local mask */ #define GX_CP_MATRIXINDEXB_TEX6_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_CP_MATRIXINDEXB_TEX6_SHIFT 12 + /* raw mask */ #define GX_CP_MATRIXINDEXB_TEX6_MASK (((1 << 6) - 1) << 31 - 19) + /* local mask */ #define GX_CP_MATRIXINDEXB_TEX6_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_CP_MATRIXINDEXB_TEX6_SHIFT 12 -/* get value */ #define GX_CP_GET_MATRIXINDEXB_TEX6(reg) \ - GX_BITGET((reg), 14, 6) -/* set value */ #define GX_CP_SET_MATRIXINDEXB_TEX6(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 6, x)) + /* get value */ #define GX_CP_GET_MATRIXINDEXB_TEX6(reg) GX_BITGET((reg), 14, 6) + /* set value */ #define GX_CP_SET_MATRIXINDEXB_TEX6(reg, x) ((reg) = GX_BITSET((reg), 14, 6, x)) // TEX5 [20:25] (6) -/* start bit */ #define GX_CP_MATRIXINDEXB_TEX5_B 20 -/* end bit */ #define GX_CP_MATRIXINDEXB_TEX5_E 25 -/* bit size */ #define GX_CP_MATRIXINDEXB_TEX5_SZ 6 + /* start bit */ #define GX_CP_MATRIXINDEXB_TEX5_B 20 + /* end bit */ #define GX_CP_MATRIXINDEXB_TEX5_E 25 + /* bit size */ #define GX_CP_MATRIXINDEXB_TEX5_SZ 6 -/* raw mask */ #define GX_CP_MATRIXINDEXB_TEX5_MASK \ - (((1 << 6) - 1) << 31 - 25) -/* local mask */ #define GX_CP_MATRIXINDEXB_TEX5_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_CP_MATRIXINDEXB_TEX5_SHIFT 6 + /* raw mask */ #define GX_CP_MATRIXINDEXB_TEX5_MASK (((1 << 6) - 1) << 31 - 25) + /* local mask */ #define GX_CP_MATRIXINDEXB_TEX5_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_CP_MATRIXINDEXB_TEX5_SHIFT 6 -/* get value */ #define GX_CP_GET_MATRIXINDEXB_TEX5(reg) \ - GX_BITGET((reg), 20, 6) -/* set value */ #define GX_CP_SET_MATRIXINDEXB_TEX5(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 6, x)) + /* get value */ #define GX_CP_GET_MATRIXINDEXB_TEX5(reg) GX_BITGET((reg), 20, 6) + /* set value */ #define GX_CP_SET_MATRIXINDEXB_TEX5(reg, x) ((reg) = GX_BITSET((reg), 20, 6, x)) // TEX4 [26:31] (6) -/* start bit */ #define GX_CP_MATRIXINDEXB_TEX4_B 26 -/* end bit */ #define GX_CP_MATRIXINDEXB_TEX4_E 31 -/* bit size */ #define GX_CP_MATRIXINDEXB_TEX4_SZ 6 + /* start bit */ #define GX_CP_MATRIXINDEXB_TEX4_B 26 + /* end bit */ #define GX_CP_MATRIXINDEXB_TEX4_E 31 + /* bit size */ #define GX_CP_MATRIXINDEXB_TEX4_SZ 6 + + /* raw mask */ #define GX_CP_MATRIXINDEXB_TEX4_MASK (((1 << 6) - 1) << 31 - 31) + /* local mask */ #define GX_CP_MATRIXINDEXB_TEX4_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_CP_MATRIXINDEXB_TEX4_SHIFT 0 -/* raw mask */ #define GX_CP_MATRIXINDEXB_TEX4_MASK \ - (((1 << 6) - 1) << 31 - 31) -/* local mask */ #define GX_CP_MATRIXINDEXB_TEX4_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_CP_MATRIXINDEXB_TEX4_SHIFT 0 + /* get value */ #define GX_CP_GET_MATRIXINDEXB_TEX4(reg) GX_BITGET((reg), 26, 6) + /* set value */ #define GX_CP_SET_MATRIXINDEXB_TEX4(reg, x) ((reg) = GX_BITSET((reg), 26, 6, x)) -/* get value */ #define GX_CP_GET_MATRIXINDEXB_TEX4(reg) \ - GX_BITGET((reg), 26, 6) -/* set value */ #define GX_CP_SET_MATRIXINDEXB_TEX4(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 6, x)) /****************************************************************************** * CP register 0x50 - VCD_Lo *****************************************************************************/ // POSMATIDX [31:31] (1) -/* start bit */ #define GX_CP_VCD_LO_POSMATIDX_B 31 -/* end bit */ #define GX_CP_VCD_LO_POSMATIDX_E 31 -/* bit size */ #define GX_CP_VCD_LO_POSMATIDX_SZ 1 + /* start bit */ #define GX_CP_VCD_LO_POSMATIDX_B 31 + /* end bit */ #define GX_CP_VCD_LO_POSMATIDX_E 31 + /* bit size */ #define GX_CP_VCD_LO_POSMATIDX_SZ 1 -/* raw mask */ #define GX_CP_VCD_LO_POSMATIDX_MASK (((1 << 1) - 1) << 31 - 31) -/* local mask */ #define GX_CP_VCD_LO_POSMATIDX_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VCD_LO_POSMATIDX_SHIFT 0 + /* raw mask */ #define GX_CP_VCD_LO_POSMATIDX_MASK (((1 << 1) - 1) << 31 - 31) + /* local mask */ #define GX_CP_VCD_LO_POSMATIDX_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VCD_LO_POSMATIDX_SHIFT 0 -/* get value */ #define GX_CP_GET_VCD_LO_POSMATIDX(reg) GX_BITGET((reg), 31, 1) -/* set value */ #define GX_CP_SET_VCD_LO_POSMATIDX(reg, x) \ - ((reg) = GX_BITSET((reg), 31, 1, x)) + /* get value */ #define GX_CP_GET_VCD_LO_POSMATIDX(reg) GX_BITGET((reg), 31, 1) + /* set value */ #define GX_CP_SET_VCD_LO_POSMATIDX(reg, x) ((reg) = GX_BITSET((reg), 31, 1, x)) // TEX0MATIDX [30:30] (1) -/* start bit */ #define GX_CP_VCD_LO_TEX0MATIDX_B 30 -/* end bit */ #define GX_CP_VCD_LO_TEX0MATIDX_E 30 -/* bit size */ #define GX_CP_VCD_LO_TEX0MATIDX_SZ 1 + /* start bit */ #define GX_CP_VCD_LO_TEX0MATIDX_B 30 + /* end bit */ #define GX_CP_VCD_LO_TEX0MATIDX_E 30 + /* bit size */ #define GX_CP_VCD_LO_TEX0MATIDX_SZ 1 -/* raw mask */ #define GX_CP_VCD_LO_TEX0MATIDX_MASK \ - (((1 << 1) - 1) << 31 - 30) -/* local mask */ #define GX_CP_VCD_LO_TEX0MATIDX_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VCD_LO_TEX0MATIDX_SHIFT 1 + /* raw mask */ #define GX_CP_VCD_LO_TEX0MATIDX_MASK (((1 << 1) - 1) << 31 - 30) + /* local mask */ #define GX_CP_VCD_LO_TEX0MATIDX_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VCD_LO_TEX0MATIDX_SHIFT 1 -/* get value */ #define GX_CP_GET_VCD_LO_TEX0MATIDX(reg) \ - GX_BITGET((reg), 30, 1) -/* set value */ #define GX_CP_SET_VCD_LO_TEX0MATIDX(reg, x) \ - ((reg) = GX_BITSET((reg), 30, 1, x)) + /* get value */ #define GX_CP_GET_VCD_LO_TEX0MATIDX(reg) GX_BITGET((reg), 30, 1) + /* set value */ #define GX_CP_SET_VCD_LO_TEX0MATIDX(reg, x) ((reg) = GX_BITSET((reg), 30, 1, x)) // TEX1MATIDX [29:29] (1) -/* start bit */ #define GX_CP_VCD_LO_TEX1MATIDX_B 29 -/* end bit */ #define GX_CP_VCD_LO_TEX1MATIDX_E 29 -/* bit size */ #define GX_CP_VCD_LO_TEX1MATIDX_SZ 1 + /* start bit */ #define GX_CP_VCD_LO_TEX1MATIDX_B 29 + /* end bit */ #define GX_CP_VCD_LO_TEX1MATIDX_E 29 + /* bit size */ #define GX_CP_VCD_LO_TEX1MATIDX_SZ 1 -/* raw mask */ #define GX_CP_VCD_LO_TEX1MATIDX_MASK \ - (((1 << 1) - 1) << 31 - 29) -/* local mask */ #define GX_CP_VCD_LO_TEX1MATIDX_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VCD_LO_TEX1MATIDX_SHIFT 2 + /* raw mask */ #define GX_CP_VCD_LO_TEX1MATIDX_MASK (((1 << 1) - 1) << 31 - 29) + /* local mask */ #define GX_CP_VCD_LO_TEX1MATIDX_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VCD_LO_TEX1MATIDX_SHIFT 2 -/* get value */ #define GX_CP_GET_VCD_LO_TEX1MATIDX(reg) \ - GX_BITGET((reg), 29, 1) -/* set value */ #define GX_CP_SET_VCD_LO_TEX1MATIDX(reg, x) \ - ((reg) = GX_BITSET((reg), 29, 1, x)) + /* get value */ #define GX_CP_GET_VCD_LO_TEX1MATIDX(reg) GX_BITGET((reg), 29, 1) + /* set value */ #define GX_CP_SET_VCD_LO_TEX1MATIDX(reg, x) ((reg) = GX_BITSET((reg), 29, 1, x)) // TEX2MATIDX [28:28] (1) -/* start bit */ #define GX_CP_VCD_LO_TEX2MATIDX_B 28 -/* end bit */ #define GX_CP_VCD_LO_TEX2MATIDX_E 28 -/* bit size */ #define GX_CP_VCD_LO_TEX2MATIDX_SZ 1 + /* start bit */ #define GX_CP_VCD_LO_TEX2MATIDX_B 28 + /* end bit */ #define GX_CP_VCD_LO_TEX2MATIDX_E 28 + /* bit size */ #define GX_CP_VCD_LO_TEX2MATIDX_SZ 1 -/* raw mask */ #define GX_CP_VCD_LO_TEX2MATIDX_MASK \ - (((1 << 1) - 1) << 31 - 28) -/* local mask */ #define GX_CP_VCD_LO_TEX2MATIDX_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VCD_LO_TEX2MATIDX_SHIFT 3 + /* raw mask */ #define GX_CP_VCD_LO_TEX2MATIDX_MASK (((1 << 1) - 1) << 31 - 28) + /* local mask */ #define GX_CP_VCD_LO_TEX2MATIDX_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VCD_LO_TEX2MATIDX_SHIFT 3 -/* get value */ #define GX_CP_GET_VCD_LO_TEX2MATIDX(reg) \ - GX_BITGET((reg), 28, 1) -/* set value */ #define GX_CP_SET_VCD_LO_TEX2MATIDX(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 1, x)) + /* get value */ #define GX_CP_GET_VCD_LO_TEX2MATIDX(reg) GX_BITGET((reg), 28, 1) + /* set value */ #define GX_CP_SET_VCD_LO_TEX2MATIDX(reg, x) ((reg) = GX_BITSET((reg), 28, 1, x)) // TEX3MATIDX [27:27] (1) -/* start bit */ #define GX_CP_VCD_LO_TEX3MATIDX_B 27 -/* end bit */ #define GX_CP_VCD_LO_TEX3MATIDX_E 27 -/* bit size */ #define GX_CP_VCD_LO_TEX3MATIDX_SZ 1 + /* start bit */ #define GX_CP_VCD_LO_TEX3MATIDX_B 27 + /* end bit */ #define GX_CP_VCD_LO_TEX3MATIDX_E 27 + /* bit size */ #define GX_CP_VCD_LO_TEX3MATIDX_SZ 1 -/* raw mask */ #define GX_CP_VCD_LO_TEX3MATIDX_MASK \ - (((1 << 1) - 1) << 31 - 27) -/* local mask */ #define GX_CP_VCD_LO_TEX3MATIDX_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VCD_LO_TEX3MATIDX_SHIFT 4 + /* raw mask */ #define GX_CP_VCD_LO_TEX3MATIDX_MASK (((1 << 1) - 1) << 31 - 27) + /* local mask */ #define GX_CP_VCD_LO_TEX3MATIDX_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VCD_LO_TEX3MATIDX_SHIFT 4 -/* get value */ #define GX_CP_GET_VCD_LO_TEX3MATIDX(reg) \ - GX_BITGET((reg), 27, 1) -/* set value */ #define GX_CP_SET_VCD_LO_TEX3MATIDX(reg, x) \ - ((reg) = GX_BITSET((reg), 27, 1, x)) + /* get value */ #define GX_CP_GET_VCD_LO_TEX3MATIDX(reg) GX_BITGET((reg), 27, 1) + /* set value */ #define GX_CP_SET_VCD_LO_TEX3MATIDX(reg, x) ((reg) = GX_BITSET((reg), 27, 1, x)) // TEX4MATIDX [26:26] (1) -/* start bit */ #define GX_CP_VCD_LO_TEX4MATIDX_B 26 -/* end bit */ #define GX_CP_VCD_LO_TEX4MATIDX_E 26 -/* bit size */ #define GX_CP_VCD_LO_TEX4MATIDX_SZ 1 + /* start bit */ #define GX_CP_VCD_LO_TEX4MATIDX_B 26 + /* end bit */ #define GX_CP_VCD_LO_TEX4MATIDX_E 26 + /* bit size */ #define GX_CP_VCD_LO_TEX4MATIDX_SZ 1 -/* raw mask */ #define GX_CP_VCD_LO_TEX4MATIDX_MASK \ - (((1 << 1) - 1) << 31 - 26) -/* local mask */ #define GX_CP_VCD_LO_TEX4MATIDX_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VCD_LO_TEX4MATIDX_SHIFT 5 + /* raw mask */ #define GX_CP_VCD_LO_TEX4MATIDX_MASK (((1 << 1) - 1) << 31 - 26) + /* local mask */ #define GX_CP_VCD_LO_TEX4MATIDX_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VCD_LO_TEX4MATIDX_SHIFT 5 -/* get value */ #define GX_CP_GET_VCD_LO_TEX4MATIDX(reg) \ - GX_BITGET((reg), 26, 1) -/* set value */ #define GX_CP_SET_VCD_LO_TEX4MATIDX(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 1, x)) + /* get value */ #define GX_CP_GET_VCD_LO_TEX4MATIDX(reg) GX_BITGET((reg), 26, 1) + /* set value */ #define GX_CP_SET_VCD_LO_TEX4MATIDX(reg, x) ((reg) = GX_BITSET((reg), 26, 1, x)) // TEX5MATIDX [25:25] (1) -/* start bit */ #define GX_CP_VCD_LO_TEX5MATIDX_B 25 -/* end bit */ #define GX_CP_VCD_LO_TEX5MATIDX_E 25 -/* bit size */ #define GX_CP_VCD_LO_TEX5MATIDX_SZ 1 + /* start bit */ #define GX_CP_VCD_LO_TEX5MATIDX_B 25 + /* end bit */ #define GX_CP_VCD_LO_TEX5MATIDX_E 25 + /* bit size */ #define GX_CP_VCD_LO_TEX5MATIDX_SZ 1 -/* raw mask */ #define GX_CP_VCD_LO_TEX5MATIDX_MASK \ - (((1 << 1) - 1) << 31 - 25) -/* local mask */ #define GX_CP_VCD_LO_TEX5MATIDX_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VCD_LO_TEX5MATIDX_SHIFT 6 + /* raw mask */ #define GX_CP_VCD_LO_TEX5MATIDX_MASK (((1 << 1) - 1) << 31 - 25) + /* local mask */ #define GX_CP_VCD_LO_TEX5MATIDX_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VCD_LO_TEX5MATIDX_SHIFT 6 -/* get value */ #define GX_CP_GET_VCD_LO_TEX5MATIDX(reg) \ - GX_BITGET((reg), 25, 1) -/* set value */ #define GX_CP_SET_VCD_LO_TEX5MATIDX(reg, x) \ - ((reg) = GX_BITSET((reg), 25, 1, x)) + /* get value */ #define GX_CP_GET_VCD_LO_TEX5MATIDX(reg) GX_BITGET((reg), 25, 1) + /* set value */ #define GX_CP_SET_VCD_LO_TEX5MATIDX(reg, x) ((reg) = GX_BITSET((reg), 25, 1, x)) // TEX6MATIDX [24:24] (1) -/* start bit */ #define GX_CP_VCD_LO_TEX6MATIDX_B 24 -/* end bit */ #define GX_CP_VCD_LO_TEX6MATIDX_E 24 -/* bit size */ #define GX_CP_VCD_LO_TEX6MATIDX_SZ 1 + /* start bit */ #define GX_CP_VCD_LO_TEX6MATIDX_B 24 + /* end bit */ #define GX_CP_VCD_LO_TEX6MATIDX_E 24 + /* bit size */ #define GX_CP_VCD_LO_TEX6MATIDX_SZ 1 -/* raw mask */ #define GX_CP_VCD_LO_TEX6MATIDX_MASK \ - (((1 << 1) - 1) << 31 - 24) -/* local mask */ #define GX_CP_VCD_LO_TEX6MATIDX_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VCD_LO_TEX6MATIDX_SHIFT 7 + /* raw mask */ #define GX_CP_VCD_LO_TEX6MATIDX_MASK (((1 << 1) - 1) << 31 - 24) + /* local mask */ #define GX_CP_VCD_LO_TEX6MATIDX_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VCD_LO_TEX6MATIDX_SHIFT 7 -/* get value */ #define GX_CP_GET_VCD_LO_TEX6MATIDX(reg) \ - GX_BITGET((reg), 24, 1) -/* set value */ #define GX_CP_SET_VCD_LO_TEX6MATIDX(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 1, x)) + /* get value */ #define GX_CP_GET_VCD_LO_TEX6MATIDX(reg) GX_BITGET((reg), 24, 1) + /* set value */ #define GX_CP_SET_VCD_LO_TEX6MATIDX(reg, x) ((reg) = GX_BITSET((reg), 24, 1, x)) // TEX7MATIDX [23:23] (1) -/* start bit */ #define GX_CP_VCD_LO_TEX7MATIDX_B 23 -/* end bit */ #define GX_CP_VCD_LO_TEX7MATIDX_E 23 -/* bit size */ #define GX_CP_VCD_LO_TEX7MATIDX_SZ 1 + /* start bit */ #define GX_CP_VCD_LO_TEX7MATIDX_B 23 + /* end bit */ #define GX_CP_VCD_LO_TEX7MATIDX_E 23 + /* bit size */ #define GX_CP_VCD_LO_TEX7MATIDX_SZ 1 -/* raw mask */ #define GX_CP_VCD_LO_TEX7MATIDX_MASK \ - (((1 << 1) - 1) << 31 - 23) -/* local mask */ #define GX_CP_VCD_LO_TEX7MATIDX_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VCD_LO_TEX7MATIDX_SHIFT 8 + /* raw mask */ #define GX_CP_VCD_LO_TEX7MATIDX_MASK (((1 << 1) - 1) << 31 - 23) + /* local mask */ #define GX_CP_VCD_LO_TEX7MATIDX_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VCD_LO_TEX7MATIDX_SHIFT 8 -/* get value */ #define GX_CP_GET_VCD_LO_TEX7MATIDX(reg) \ - GX_BITGET((reg), 23, 1) -/* set value */ #define GX_CP_SET_VCD_LO_TEX7MATIDX(reg, x) \ - ((reg) = GX_BITSET((reg), 23, 1, x)) + /* get value */ #define GX_CP_GET_VCD_LO_TEX7MATIDX(reg) GX_BITGET((reg), 23, 1) + /* set value */ #define GX_CP_SET_VCD_LO_TEX7MATIDX(reg, x) ((reg) = GX_BITSET((reg), 23, 1, x)) // POSITION [21:22] (2) -/* start bit */ #define GX_CP_VCD_LO_POSITION_B 21 -/* end bit */ #define GX_CP_VCD_LO_POSITION_E 22 -/* bit size */ #define GX_CP_VCD_LO_POSITION_SZ 2 + /* start bit */ #define GX_CP_VCD_LO_POSITION_B 21 + /* end bit */ #define GX_CP_VCD_LO_POSITION_E 22 + /* bit size */ #define GX_CP_VCD_LO_POSITION_SZ 2 -/* raw mask */ #define GX_CP_VCD_LO_POSITION_MASK (((1 << 2) - 1) << 31 - 22) -/* local mask */ #define GX_CP_VCD_LO_POSITION_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_LO_POSITION_SHIFT 9 + /* raw mask */ #define GX_CP_VCD_LO_POSITION_MASK (((1 << 2) - 1) << 31 - 22) + /* local mask */ #define GX_CP_VCD_LO_POSITION_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_LO_POSITION_SHIFT 9 -/* get value */ #define GX_CP_GET_VCD_LO_POSITION(reg) GX_BITGET((reg), 21, 2) -/* set value */ #define GX_CP_SET_VCD_LO_POSITION(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 2, x)) + /* get value */ #define GX_CP_GET_VCD_LO_POSITION(reg) GX_BITGET((reg), 21, 2) + /* set value */ #define GX_CP_SET_VCD_LO_POSITION(reg, x) ((reg) = GX_BITSET((reg), 21, 2, x)) // NORMAL [19:20] (2) -/* start bit */ #define GX_CP_VCD_LO_NORMAL_B 19 -/* end bit */ #define GX_CP_VCD_LO_NORMAL_E 20 -/* bit size */ #define GX_CP_VCD_LO_NORMAL_SZ 2 + /* start bit */ #define GX_CP_VCD_LO_NORMAL_B 19 + /* end bit */ #define GX_CP_VCD_LO_NORMAL_E 20 + /* bit size */ #define GX_CP_VCD_LO_NORMAL_SZ 2 -/* raw mask */ #define GX_CP_VCD_LO_NORMAL_MASK (((1 << 2) - 1) << 31 - 20) -/* local mask */ #define GX_CP_VCD_LO_NORMAL_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_LO_NORMAL_SHIFT 11 + /* raw mask */ #define GX_CP_VCD_LO_NORMAL_MASK (((1 << 2) - 1) << 31 - 20) + /* local mask */ #define GX_CP_VCD_LO_NORMAL_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_LO_NORMAL_SHIFT 11 -/* get value */ #define GX_CP_GET_VCD_LO_NORMAL(reg) GX_BITGET((reg), 19, 2) -/* set value */ #define GX_CP_SET_VCD_LO_NORMAL(reg, x) \ - ((reg) = GX_BITSET((reg), 19, 2, x)) + /* get value */ #define GX_CP_GET_VCD_LO_NORMAL(reg) GX_BITGET((reg), 19, 2) + /* set value */ #define GX_CP_SET_VCD_LO_NORMAL(reg, x) ((reg) = GX_BITSET((reg), 19, 2, x)) // COLORDIFFUSED [17:18] (2) -/* start bit */ #define GX_CP_VCD_LO_COLORDIFFUSED_B 17 -/* end bit */ #define GX_CP_VCD_LO_COLORDIFFUSED_E 18 -/* bit size */ #define GX_CP_VCD_LO_COLORDIFFUSED_SZ 2 + /* start bit */ #define GX_CP_VCD_LO_COLORDIFFUSED_B 17 + /* end bit */ #define GX_CP_VCD_LO_COLORDIFFUSED_E 18 + /* bit size */ #define GX_CP_VCD_LO_COLORDIFFUSED_SZ 2 -/* raw mask */ #define GX_CP_VCD_LO_COLORDIFFUSED_MASK \ - (((1 << 2) - 1) << 31 - 18) -/* local mask */ #define GX_CP_VCD_LO_COLORDIFFUSED_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_LO_COLORDIFFUSED_SHIFT 13 + /* raw mask */ #define GX_CP_VCD_LO_COLORDIFFUSED_MASK (((1 << 2) - 1) << 31 - 18) + /* local mask */ #define GX_CP_VCD_LO_COLORDIFFUSED_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_LO_COLORDIFFUSED_SHIFT 13 -/* get value */ #define GX_CP_GET_VCD_LO_COLORDIFFUSED(reg) \ - GX_BITGET((reg), 17, 2) -/* set value */ #define GX_CP_SET_VCD_LO_COLORDIFFUSED(reg, x) \ - ((reg) = GX_BITSET((reg), 17, 2, x)) + /* get value */ #define GX_CP_GET_VCD_LO_COLORDIFFUSED(reg) GX_BITGET((reg), 17, 2) + /* set value */ #define GX_CP_SET_VCD_LO_COLORDIFFUSED(reg, x) ((reg) = GX_BITSET((reg), 17, 2, x)) // COLORSPECULAR [15:16] (2) -/* start bit */ #define GX_CP_VCD_LO_COLORSPECULAR_B 15 -/* end bit */ #define GX_CP_VCD_LO_COLORSPECULAR_E 16 -/* bit size */ #define GX_CP_VCD_LO_COLORSPECULAR_SZ 2 + /* start bit */ #define GX_CP_VCD_LO_COLORSPECULAR_B 15 + /* end bit */ #define GX_CP_VCD_LO_COLORSPECULAR_E 16 + /* bit size */ #define GX_CP_VCD_LO_COLORSPECULAR_SZ 2 -/* raw mask */ #define GX_CP_VCD_LO_COLORSPECULAR_MASK \ - (((1 << 2) - 1) << 31 - 16) -/* local mask */ #define GX_CP_VCD_LO_COLORSPECULAR_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_LO_COLORSPECULAR_SHIFT 15 + /* raw mask */ #define GX_CP_VCD_LO_COLORSPECULAR_MASK (((1 << 2) - 1) << 31 - 16) + /* local mask */ #define GX_CP_VCD_LO_COLORSPECULAR_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_LO_COLORSPECULAR_SHIFT 15 + + /* get value */ #define GX_CP_GET_VCD_LO_COLORSPECULAR(reg) GX_BITGET((reg), 15, 2) + /* set value */ #define GX_CP_SET_VCD_LO_COLORSPECULAR(reg, x) ((reg) = GX_BITSET((reg), 15, 2, x)) -/* get value */ #define GX_CP_GET_VCD_LO_COLORSPECULAR(reg) \ - GX_BITGET((reg), 15, 2) -/* set value */ #define GX_CP_SET_VCD_LO_COLORSPECULAR(reg, x) \ - ((reg) = GX_BITSET((reg), 15, 2, x)) /****************************************************************************** * CP register 0x60 - VCD_Hi *****************************************************************************/ // TEX0COORD [30:31] (2) -/* start bit */ #define GX_CP_VCD_HI_TEX0COORD_B 30 -/* end bit */ #define GX_CP_VCD_HI_TEX0COORD_E 31 -/* bit size */ #define GX_CP_VCD_HI_TEX0COORD_SZ 2 + /* start bit */ #define GX_CP_VCD_HI_TEX0COORD_B 30 + /* end bit */ #define GX_CP_VCD_HI_TEX0COORD_E 31 + /* bit size */ #define GX_CP_VCD_HI_TEX0COORD_SZ 2 -/* raw mask */ #define GX_CP_VCD_HI_TEX0COORD_MASK (((1 << 2) - 1) << 31 - 31) -/* local mask */ #define GX_CP_VCD_HI_TEX0COORD_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_HI_TEX0COORD_SHIFT 0 + /* raw mask */ #define GX_CP_VCD_HI_TEX0COORD_MASK (((1 << 2) - 1) << 31 - 31) + /* local mask */ #define GX_CP_VCD_HI_TEX0COORD_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_HI_TEX0COORD_SHIFT 0 -/* get value */ #define GX_CP_GET_VCD_HI_TEX0COORD(reg) GX_BITGET((reg), 30, 2) -/* set value */ #define GX_CP_SET_VCD_HI_TEX0COORD(reg, x) \ - ((reg) = GX_BITSET((reg), 30, 2, x)) + /* get value */ #define GX_CP_GET_VCD_HI_TEX0COORD(reg) GX_BITGET((reg), 30, 2) + /* set value */ #define GX_CP_SET_VCD_HI_TEX0COORD(reg, x) ((reg) = GX_BITSET((reg), 30, 2, x)) // TEX1COORD [28:29] (2) -/* start bit */ #define GX_CP_VCD_HI_TEX1COORD_B 28 -/* end bit */ #define GX_CP_VCD_HI_TEX1COORD_E 29 -/* bit size */ #define GX_CP_VCD_HI_TEX1COORD_SZ 2 + /* start bit */ #define GX_CP_VCD_HI_TEX1COORD_B 28 + /* end bit */ #define GX_CP_VCD_HI_TEX1COORD_E 29 + /* bit size */ #define GX_CP_VCD_HI_TEX1COORD_SZ 2 -/* raw mask */ #define GX_CP_VCD_HI_TEX1COORD_MASK (((1 << 2) - 1) << 31 - 29) -/* local mask */ #define GX_CP_VCD_HI_TEX1COORD_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_HI_TEX1COORD_SHIFT 2 + /* raw mask */ #define GX_CP_VCD_HI_TEX1COORD_MASK (((1 << 2) - 1) << 31 - 29) + /* local mask */ #define GX_CP_VCD_HI_TEX1COORD_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_HI_TEX1COORD_SHIFT 2 -/* get value */ #define GX_CP_GET_VCD_HI_TEX1COORD(reg) GX_BITGET((reg), 28, 2) -/* set value */ #define GX_CP_SET_VCD_HI_TEX1COORD(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 2, x)) + /* get value */ #define GX_CP_GET_VCD_HI_TEX1COORD(reg) GX_BITGET((reg), 28, 2) + /* set value */ #define GX_CP_SET_VCD_HI_TEX1COORD(reg, x) ((reg) = GX_BITSET((reg), 28, 2, x)) // TEX2COORD [26:27] (2) -/* start bit */ #define GX_CP_VCD_HI_TEX2COORD_B 26 -/* end bit */ #define GX_CP_VCD_HI_TEX2COORD_E 27 -/* bit size */ #define GX_CP_VCD_HI_TEX2COORD_SZ 2 + /* start bit */ #define GX_CP_VCD_HI_TEX2COORD_B 26 + /* end bit */ #define GX_CP_VCD_HI_TEX2COORD_E 27 + /* bit size */ #define GX_CP_VCD_HI_TEX2COORD_SZ 2 -/* raw mask */ #define GX_CP_VCD_HI_TEX2COORD_MASK (((1 << 2) - 1) << 31 - 27) -/* local mask */ #define GX_CP_VCD_HI_TEX2COORD_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_HI_TEX2COORD_SHIFT 4 + /* raw mask */ #define GX_CP_VCD_HI_TEX2COORD_MASK (((1 << 2) - 1) << 31 - 27) + /* local mask */ #define GX_CP_VCD_HI_TEX2COORD_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_HI_TEX2COORD_SHIFT 4 -/* get value */ #define GX_CP_GET_VCD_HI_TEX2COORD(reg) GX_BITGET((reg), 26, 2) -/* set value */ #define GX_CP_SET_VCD_HI_TEX2COORD(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 2, x)) + /* get value */ #define GX_CP_GET_VCD_HI_TEX2COORD(reg) GX_BITGET((reg), 26, 2) + /* set value */ #define GX_CP_SET_VCD_HI_TEX2COORD(reg, x) ((reg) = GX_BITSET((reg), 26, 2, x)) // TEX3COORD [24:25] (2) -/* start bit */ #define GX_CP_VCD_HI_TEX3COORD_B 24 -/* end bit */ #define GX_CP_VCD_HI_TEX3COORD_E 25 -/* bit size */ #define GX_CP_VCD_HI_TEX3COORD_SZ 2 + /* start bit */ #define GX_CP_VCD_HI_TEX3COORD_B 24 + /* end bit */ #define GX_CP_VCD_HI_TEX3COORD_E 25 + /* bit size */ #define GX_CP_VCD_HI_TEX3COORD_SZ 2 -/* raw mask */ #define GX_CP_VCD_HI_TEX3COORD_MASK (((1 << 2) - 1) << 31 - 25) -/* local mask */ #define GX_CP_VCD_HI_TEX3COORD_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_HI_TEX3COORD_SHIFT 6 + /* raw mask */ #define GX_CP_VCD_HI_TEX3COORD_MASK (((1 << 2) - 1) << 31 - 25) + /* local mask */ #define GX_CP_VCD_HI_TEX3COORD_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_HI_TEX3COORD_SHIFT 6 -/* get value */ #define GX_CP_GET_VCD_HI_TEX3COORD(reg) GX_BITGET((reg), 24, 2) -/* set value */ #define GX_CP_SET_VCD_HI_TEX3COORD(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 2, x)) + /* get value */ #define GX_CP_GET_VCD_HI_TEX3COORD(reg) GX_BITGET((reg), 24, 2) + /* set value */ #define GX_CP_SET_VCD_HI_TEX3COORD(reg, x) ((reg) = GX_BITSET((reg), 24, 2, x)) // TEX4COORD [22:23] (2) -/* start bit */ #define GX_CP_VCD_HI_TEX4COORD_B 22 -/* end bit */ #define GX_CP_VCD_HI_TEX4COORD_E 23 -/* bit size */ #define GX_CP_VCD_HI_TEX4COORD_SZ 2 + /* start bit */ #define GX_CP_VCD_HI_TEX4COORD_B 22 + /* end bit */ #define GX_CP_VCD_HI_TEX4COORD_E 23 + /* bit size */ #define GX_CP_VCD_HI_TEX4COORD_SZ 2 -/* raw mask */ #define GX_CP_VCD_HI_TEX4COORD_MASK (((1 << 2) - 1) << 31 - 23) -/* local mask */ #define GX_CP_VCD_HI_TEX4COORD_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_HI_TEX4COORD_SHIFT 8 + /* raw mask */ #define GX_CP_VCD_HI_TEX4COORD_MASK (((1 << 2) - 1) << 31 - 23) + /* local mask */ #define GX_CP_VCD_HI_TEX4COORD_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_HI_TEX4COORD_SHIFT 8 -/* get value */ #define GX_CP_GET_VCD_HI_TEX4COORD(reg) GX_BITGET((reg), 22, 2) -/* set value */ #define GX_CP_SET_VCD_HI_TEX4COORD(reg, x) \ - ((reg) = GX_BITSET((reg), 22, 2, x)) + /* get value */ #define GX_CP_GET_VCD_HI_TEX4COORD(reg) GX_BITGET((reg), 22, 2) + /* set value */ #define GX_CP_SET_VCD_HI_TEX4COORD(reg, x) ((reg) = GX_BITSET((reg), 22, 2, x)) // TEX5COORD [20:21] (2) -/* start bit */ #define GX_CP_VCD_HI_TEX5COORD_B 20 -/* end bit */ #define GX_CP_VCD_HI_TEX5COORD_E 21 -/* bit size */ #define GX_CP_VCD_HI_TEX5COORD_SZ 2 + /* start bit */ #define GX_CP_VCD_HI_TEX5COORD_B 20 + /* end bit */ #define GX_CP_VCD_HI_TEX5COORD_E 21 + /* bit size */ #define GX_CP_VCD_HI_TEX5COORD_SZ 2 -/* raw mask */ #define GX_CP_VCD_HI_TEX5COORD_MASK (((1 << 2) - 1) << 31 - 21) -/* local mask */ #define GX_CP_VCD_HI_TEX5COORD_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_HI_TEX5COORD_SHIFT 10 + /* raw mask */ #define GX_CP_VCD_HI_TEX5COORD_MASK (((1 << 2) - 1) << 31 - 21) + /* local mask */ #define GX_CP_VCD_HI_TEX5COORD_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_HI_TEX5COORD_SHIFT 10 -/* get value */ #define GX_CP_GET_VCD_HI_TEX5COORD(reg) GX_BITGET((reg), 20, 2) -/* set value */ #define GX_CP_SET_VCD_HI_TEX5COORD(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 2, x)) + /* get value */ #define GX_CP_GET_VCD_HI_TEX5COORD(reg) GX_BITGET((reg), 20, 2) + /* set value */ #define GX_CP_SET_VCD_HI_TEX5COORD(reg, x) ((reg) = GX_BITSET((reg), 20, 2, x)) // TEX6COORD [18:19] (2) -/* start bit */ #define GX_CP_VCD_HI_TEX6COORD_B 18 -/* end bit */ #define GX_CP_VCD_HI_TEX6COORD_E 19 -/* bit size */ #define GX_CP_VCD_HI_TEX6COORD_SZ 2 + /* start bit */ #define GX_CP_VCD_HI_TEX6COORD_B 18 + /* end bit */ #define GX_CP_VCD_HI_TEX6COORD_E 19 + /* bit size */ #define GX_CP_VCD_HI_TEX6COORD_SZ 2 -/* raw mask */ #define GX_CP_VCD_HI_TEX6COORD_MASK (((1 << 2) - 1) << 31 - 19) -/* local mask */ #define GX_CP_VCD_HI_TEX6COORD_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_HI_TEX6COORD_SHIFT 12 + /* raw mask */ #define GX_CP_VCD_HI_TEX6COORD_MASK (((1 << 2) - 1) << 31 - 19) + /* local mask */ #define GX_CP_VCD_HI_TEX6COORD_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_HI_TEX6COORD_SHIFT 12 -/* get value */ #define GX_CP_GET_VCD_HI_TEX6COORD(reg) GX_BITGET((reg), 18, 2) -/* set value */ #define GX_CP_SET_VCD_HI_TEX6COORD(reg, x) \ - ((reg) = GX_BITSET((reg), 18, 2, x)) + /* get value */ #define GX_CP_GET_VCD_HI_TEX6COORD(reg) GX_BITGET((reg), 18, 2) + /* set value */ #define GX_CP_SET_VCD_HI_TEX6COORD(reg, x) ((reg) = GX_BITSET((reg), 18, 2, x)) // TEX7COORD [16:17] (2) -/* start bit */ #define GX_CP_VCD_HI_TEX7COORD_B 16 -/* end bit */ #define GX_CP_VCD_HI_TEX7COORD_E 17 -/* bit size */ #define GX_CP_VCD_HI_TEX7COORD_SZ 2 + /* start bit */ #define GX_CP_VCD_HI_TEX7COORD_B 16 + /* end bit */ #define GX_CP_VCD_HI_TEX7COORD_E 17 + /* bit size */ #define GX_CP_VCD_HI_TEX7COORD_SZ 2 + + /* raw mask */ #define GX_CP_VCD_HI_TEX7COORD_MASK (((1 << 2) - 1) << 31 - 17) + /* local mask */ #define GX_CP_VCD_HI_TEX7COORD_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_CP_VCD_HI_TEX7COORD_SHIFT 14 -/* raw mask */ #define GX_CP_VCD_HI_TEX7COORD_MASK (((1 << 2) - 1) << 31 - 17) -/* local mask */ #define GX_CP_VCD_HI_TEX7COORD_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_CP_VCD_HI_TEX7COORD_SHIFT 14 + /* get value */ #define GX_CP_GET_VCD_HI_TEX7COORD(reg) GX_BITGET((reg), 16, 2) + /* set value */ #define GX_CP_SET_VCD_HI_TEX7COORD(reg, x) ((reg) = GX_BITSET((reg), 16, 2, x)) -/* get value */ #define GX_CP_GET_VCD_HI_TEX7COORD(reg) GX_BITGET((reg), 16, 2) -/* set value */ #define GX_CP_SET_VCD_HI_TEX7COORD(reg, x) \ - ((reg) = GX_BITSET((reg), 16, 2, x)) /****************************************************************************** * CP register 0x70 - VAT_group0 *****************************************************************************/ // POS_CNT [31:31] (1) -/* start bit */ #define GX_CP_VAT_GROUP0_POS_CNT_B 31 -/* end bit */ #define GX_CP_VAT_GROUP0_POS_CNT_E 31 -/* bit size */ #define GX_CP_VAT_GROUP0_POS_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP0_POS_CNT_B 31 + /* end bit */ #define GX_CP_VAT_GROUP0_POS_CNT_E 31 + /* bit size */ #define GX_CP_VAT_GROUP0_POS_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP0_POS_CNT_MASK \ - (((1 << 1) - 1) << 31 - 31) -/* local mask */ #define GX_CP_VAT_GROUP0_POS_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_POS_CNT_SHIFT 0 + /* raw mask */ #define GX_CP_VAT_GROUP0_POS_CNT_MASK (((1 << 1) - 1) << 31 - 31) + /* local mask */ #define GX_CP_VAT_GROUP0_POS_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_POS_CNT_SHIFT 0 -/* get value */ #define GX_CP_GET_VAT_GROUP0_POS_CNT(reg) \ - GX_BITGET((reg), 31, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP0_POS_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 31, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_POS_CNT(reg) GX_BITGET((reg), 31, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP0_POS_CNT(reg, x) ((reg) = GX_BITSET((reg), 31, 1, x)) // POS_TYPE [28:30] (3) -/* start bit */ #define GX_CP_VAT_GROUP0_POS_TYPE_B 28 -/* end bit */ #define GX_CP_VAT_GROUP0_POS_TYPE_E 30 -/* bit size */ #define GX_CP_VAT_GROUP0_POS_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP0_POS_TYPE_B 28 + /* end bit */ #define GX_CP_VAT_GROUP0_POS_TYPE_E 30 + /* bit size */ #define GX_CP_VAT_GROUP0_POS_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP0_POS_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 30) -/* local mask */ #define GX_CP_VAT_GROUP0_POS_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_POS_TYPE_SHIFT 1 + /* raw mask */ #define GX_CP_VAT_GROUP0_POS_TYPE_MASK (((1 << 3) - 1) << 31 - 30) + /* local mask */ #define GX_CP_VAT_GROUP0_POS_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_POS_TYPE_SHIFT 1 -/* get value */ #define GX_CP_GET_VAT_GROUP0_POS_TYPE(reg) \ - GX_BITGET((reg), 28, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP0_POS_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_POS_TYPE(reg) GX_BITGET((reg), 28, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP0_POS_TYPE(reg, x) ((reg) = GX_BITSET((reg), 28, 3, x)) // POS_SHIFT [23:27] (5) -/* start bit */ #define GX_CP_VAT_GROUP0_POS_SHIFT_B 23 -/* end bit */ #define GX_CP_VAT_GROUP0_POS_SHIFT_E 27 -/* bit size */ #define GX_CP_VAT_GROUP0_POS_SHIFT_SZ 5 + /* start bit */ #define GX_CP_VAT_GROUP0_POS_SHIFT_B 23 + /* end bit */ #define GX_CP_VAT_GROUP0_POS_SHIFT_E 27 + /* bit size */ #define GX_CP_VAT_GROUP0_POS_SHIFT_SZ 5 -/* raw mask */ #define GX_CP_VAT_GROUP0_POS_SHIFT_MASK \ - (((1 << 5) - 1) << 31 - 27) -/* local mask */ #define GX_CP_VAT_GROUP0_POS_SHIFT_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_POS_SHIFT_SHIFT 4 + /* raw mask */ #define GX_CP_VAT_GROUP0_POS_SHIFT_MASK (((1 << 5) - 1) << 31 - 27) + /* local mask */ #define GX_CP_VAT_GROUP0_POS_SHIFT_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_POS_SHIFT_SHIFT 4 -/* get value */ #define GX_CP_GET_VAT_GROUP0_POS_SHIFT(reg) \ - GX_BITGET((reg), 23, 5) -/* set value */ #define GX_CP_SET_VAT_GROUP0_POS_SHIFT(reg, x) \ - ((reg) = GX_BITSET((reg), 23, 5, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_POS_SHIFT(reg) GX_BITGET((reg), 23, 5) + /* set value */ #define GX_CP_SET_VAT_GROUP0_POS_SHIFT(reg, x) ((reg) = GX_BITSET((reg), 23, 5, x)) // NRM_CNT [22:22] (1) -/* start bit */ #define GX_CP_VAT_GROUP0_NRM_CNT_B 22 -/* end bit */ #define GX_CP_VAT_GROUP0_NRM_CNT_E 22 -/* bit size */ #define GX_CP_VAT_GROUP0_NRM_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP0_NRM_CNT_B 22 + /* end bit */ #define GX_CP_VAT_GROUP0_NRM_CNT_E 22 + /* bit size */ #define GX_CP_VAT_GROUP0_NRM_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP0_NRM_CNT_MASK \ - (((1 << 1) - 1) << 31 - 22) -/* local mask */ #define GX_CP_VAT_GROUP0_NRM_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_NRM_CNT_SHIFT 9 + /* raw mask */ #define GX_CP_VAT_GROUP0_NRM_CNT_MASK (((1 << 1) - 1) << 31 - 22) + /* local mask */ #define GX_CP_VAT_GROUP0_NRM_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_NRM_CNT_SHIFT 9 -/* get value */ #define GX_CP_GET_VAT_GROUP0_NRM_CNT(reg) \ - GX_BITGET((reg), 22, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP0_NRM_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 22, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_NRM_CNT(reg) GX_BITGET((reg), 22, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP0_NRM_CNT(reg, x) ((reg) = GX_BITSET((reg), 22, 1, x)) // NRM_TYPE [19:21] (3) -/* start bit */ #define GX_CP_VAT_GROUP0_NRM_TYPE_B 19 -/* end bit */ #define GX_CP_VAT_GROUP0_NRM_TYPE_E 21 -/* bit size */ #define GX_CP_VAT_GROUP0_NRM_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP0_NRM_TYPE_B 19 + /* end bit */ #define GX_CP_VAT_GROUP0_NRM_TYPE_E 21 + /* bit size */ #define GX_CP_VAT_GROUP0_NRM_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP0_NRM_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 21) -/* local mask */ #define GX_CP_VAT_GROUP0_NRM_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_NRM_TYPE_SHIFT 10 + /* raw mask */ #define GX_CP_VAT_GROUP0_NRM_TYPE_MASK (((1 << 3) - 1) << 31 - 21) + /* local mask */ #define GX_CP_VAT_GROUP0_NRM_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_NRM_TYPE_SHIFT 10 -/* get value */ #define GX_CP_GET_VAT_GROUP0_NRM_TYPE(reg) \ - GX_BITGET((reg), 19, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP0_NRM_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 19, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_NRM_TYPE(reg) GX_BITGET((reg), 19, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP0_NRM_TYPE(reg, x) ((reg) = GX_BITSET((reg), 19, 3, x)) // COLORDIFF_CNT [18:18] (1) -/* start bit */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_B 18 -/* end bit */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_E 18 -/* bit size */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_B 18 + /* end bit */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_E 18 + /* bit size */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_MASK \ - (((1 << 1) - 1) << 31 - 18) -/* local mask */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_SHIFT 13 + /* raw mask */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_MASK (((1 << 1) - 1) << 31 - 18) + /* local mask */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_COLORDIFF_CNT_SHIFT 13 -/* get value */ #define GX_CP_GET_VAT_GROUP0_COLORDIFF_CNT(reg) \ - GX_BITGET((reg), 18, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP0_COLORDIFF_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 18, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_COLORDIFF_CNT(reg) GX_BITGET((reg), 18, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP0_COLORDIFF_CNT(reg, x) ((reg) = GX_BITSET((reg), 18, 1, x)) // COLORDIFF_TYPE [15:17] (3) -/* start bit */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_B 15 -/* end bit */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_E 17 -/* bit size */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_B 15 + /* end bit */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_E 17 + /* bit size */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 17) -/* local mask */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_SHIFT 14 + /* raw mask */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_MASK (((1 << 3) - 1) << 31 - 17) + /* local mask */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_COLORDIFF_TYPE_SHIFT 14 -/* get value */ #define GX_CP_GET_VAT_GROUP0_COLORDIFF_TYPE(reg) \ - GX_BITGET((reg), 15, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP0_COLORDIFF_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 15, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_COLORDIFF_TYPE(reg) GX_BITGET((reg), 15, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP0_COLORDIFF_TYPE(reg, x) ((reg) = GX_BITSET((reg), 15, 3, x)) // COLORSPEC_CNT [14:14] (1) -/* start bit */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_B 14 -/* end bit */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_E 14 -/* bit size */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_B 14 + /* end bit */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_E 14 + /* bit size */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_MASK \ - (((1 << 1) - 1) << 31 - 14) -/* local mask */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_SHIFT 17 + /* raw mask */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_MASK (((1 << 1) - 1) << 31 - 14) + /* local mask */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_COLORSPEC_CNT_SHIFT 17 -/* get value */ #define GX_CP_GET_VAT_GROUP0_COLORSPEC_CNT(reg) \ - GX_BITGET((reg), 14, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP0_COLORSPEC_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_COLORSPEC_CNT(reg) GX_BITGET((reg), 14, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP0_COLORSPEC_CNT(reg, x) ((reg) = GX_BITSET((reg), 14, 1, x)) // COLORSPEC_TYPE [11:13] (3) -/* start bit */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_B 11 -/* end bit */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_E 13 -/* bit size */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_B 11 + /* end bit */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_E 13 + /* bit size */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 13) -/* local mask */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_SHIFT 18 + /* raw mask */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_MASK (((1 << 3) - 1) << 31 - 13) + /* local mask */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_COLORSPEC_TYPE_SHIFT 18 -/* get value */ #define GX_CP_GET_VAT_GROUP0_COLORSPEC_TYPE(reg) \ - GX_BITGET((reg), 11, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP0_COLORSPEC_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 11, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_COLORSPEC_TYPE(reg) GX_BITGET((reg), 11, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP0_COLORSPEC_TYPE(reg, x) ((reg) = GX_BITSET((reg), 11, 3, x)) // TXC0_CNT [10:10] (1) -/* start bit */ #define GX_CP_VAT_GROUP0_TXC0_CNT_B 10 -/* end bit */ #define GX_CP_VAT_GROUP0_TXC0_CNT_E 10 -/* bit size */ #define GX_CP_VAT_GROUP0_TXC0_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP0_TXC0_CNT_B 10 + /* end bit */ #define GX_CP_VAT_GROUP0_TXC0_CNT_E 10 + /* bit size */ #define GX_CP_VAT_GROUP0_TXC0_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP0_TXC0_CNT_MASK \ - (((1 << 1) - 1) << 31 - 10) -/* local mask */ #define GX_CP_VAT_GROUP0_TXC0_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_TXC0_CNT_SHIFT 21 + /* raw mask */ #define GX_CP_VAT_GROUP0_TXC0_CNT_MASK (((1 << 1) - 1) << 31 - 10) + /* local mask */ #define GX_CP_VAT_GROUP0_TXC0_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_TXC0_CNT_SHIFT 21 -/* get value */ #define GX_CP_GET_VAT_GROUP0_TXC0_CNT(reg) \ - GX_BITGET((reg), 10, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP0_TXC0_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 10, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_TXC0_CNT(reg) GX_BITGET((reg), 10, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP0_TXC0_CNT(reg, x) ((reg) = GX_BITSET((reg), 10, 1, x)) // TXC0_TYPE [7:9] (3) -/* start bit */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_B 7 -/* end bit */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_E 9 -/* bit size */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_B 7 + /* end bit */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_E 9 + /* bit size */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 9) -/* local mask */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_SHIFT 22 + /* raw mask */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_MASK (((1 << 3) - 1) << 31 - 9) + /* local mask */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_TXC0_TYPE_SHIFT 22 -/* get value */ #define GX_CP_GET_VAT_GROUP0_TXC0_TYPE(reg) \ - GX_BITGET((reg), 7, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP0_TXC0_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 7, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_TXC0_TYPE(reg) GX_BITGET((reg), 7, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP0_TXC0_TYPE(reg, x) ((reg) = GX_BITSET((reg), 7, 3, x)) // TXC0_SHIFT [2:6] (5) -/* start bit */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_B 2 -/* end bit */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_E 6 -/* bit size */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_SZ 5 + /* start bit */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_B 2 + /* end bit */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_E 6 + /* bit size */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_SZ 5 -/* raw mask */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_MASK \ - (((1 << 5) - 1) << 31 - 6) -/* local mask */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_SHIFT 25 + /* raw mask */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_MASK (((1 << 5) - 1) << 31 - 6) + /* local mask */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_TXC0_SHIFT_SHIFT 25 -/* get value */ #define GX_CP_GET_VAT_GROUP0_TXC0_SHIFT(reg) \ - GX_BITGET((reg), 2, 5) -/* set value */ #define GX_CP_SET_VAT_GROUP0_TXC0_SHIFT(reg, x) \ - ((reg) = GX_BITSET((reg), 2, 5, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP0_TXC0_SHIFT(reg) GX_BITGET((reg), 2, 5) + /* set value */ #define GX_CP_SET_VAT_GROUP0_TXC0_SHIFT(reg, x) ((reg) = GX_BITSET((reg), 2, 5, x)) // BYTEDEQUANT [1:1] (1) -/* start bit */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_B 1 -/* end bit */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_E 1 -/* bit size */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_SZ 1 - -/* raw mask */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_MASK \ - (((1 << 1) - 1) << 31 - 1) -/* local mask */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_SHIFT 30 - -/* get value */ #define GX_CP_GET_VAT_GROUP0_BYTEDEQUANT(reg) \ - GX_BITGET((reg), 1, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP0_BYTEDEQUANT(reg, x) \ - ((reg) = GX_BITSET((reg), 1, 1, x)) - -// NORMALINDEX3 [0:0] (1) - Input will be treated as three staggered indices -// (one per triple biased by component size) into normal table -/* start bit */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_B 0 -/* end bit */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_E 0 -/* bit size */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_SZ 1 - -/* raw mask */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_MASK \ - (((1 << 1) - 1) << 31 - 0) -/* local mask */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_SHIFT 31 - -/* get value */ #define GX_CP_GET_VAT_GROUP0_NORMALINDEX3(reg) \ - GX_BITGET((reg), 0, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP0_NORMALINDEX3(reg, x) \ - ((reg) = GX_BITSET((reg), 0, 1, x)) + /* start bit */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_B 1 + /* end bit */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_E 1 + /* bit size */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_SZ 1 + + /* raw mask */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_MASK (((1 << 1) - 1) << 31 - 1) + /* local mask */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_BYTEDEQUANT_SHIFT 30 + + /* get value */ #define GX_CP_GET_VAT_GROUP0_BYTEDEQUANT(reg) GX_BITGET((reg), 1, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP0_BYTEDEQUANT(reg, x) ((reg) = GX_BITSET((reg), 1, 1, x)) + +// NORMALINDEX3 [0:0] (1) - Input will be treated as three staggered indices (one per triple biased by component size) into normal table + /* start bit */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_B 0 + /* end bit */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_E 0 + /* bit size */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_SZ 1 + + /* raw mask */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_MASK (((1 << 1) - 1) << 31 - 0) + /* local mask */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP0_NORMALINDEX3_SHIFT 31 + + /* get value */ #define GX_CP_GET_VAT_GROUP0_NORMALINDEX3(reg) GX_BITGET((reg), 0, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP0_NORMALINDEX3(reg, x) ((reg) = GX_BITSET((reg), 0, 1, x)) + /****************************************************************************** * CP register 0x80 - VAT_group1 *****************************************************************************/ // TXC1_CNT [31:31] (1) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC1_CNT_B 31 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC1_CNT_E 31 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC1_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC1_CNT_B 31 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC1_CNT_E 31 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC1_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC1_CNT_MASK \ - (((1 << 1) - 1) << 31 - 31) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC1_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC1_CNT_SHIFT 0 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC1_CNT_MASK (((1 << 1) - 1) << 31 - 31) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC1_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC1_CNT_SHIFT 0 -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC1_CNT(reg) \ - GX_BITGET((reg), 31, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC1_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 31, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC1_CNT(reg) GX_BITGET((reg), 31, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC1_CNT(reg, x) ((reg) = GX_BITSET((reg), 31, 1, x)) // TXC1_TYPE [28:30] (3) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_B 28 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_E 30 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_B 28 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_E 30 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 30) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_SHIFT 1 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_MASK (((1 << 3) - 1) << 31 - 30) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC1_TYPE_SHIFT 1 -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC1_TYPE(reg) \ - GX_BITGET((reg), 28, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC1_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC1_TYPE(reg) GX_BITGET((reg), 28, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC1_TYPE(reg, x) ((reg) = GX_BITSET((reg), 28, 3, x)) // TXC1_SHIFT [23:27] (5) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_B 23 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_E 27 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_SZ 5 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_B 23 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_E 27 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_SZ 5 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_MASK \ - (((1 << 5) - 1) << 31 - 27) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_SHIFT 4 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_MASK (((1 << 5) - 1) << 31 - 27) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC1_SHIFT_SHIFT 4 -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC1_SHIFT(reg) \ - GX_BITGET((reg), 23, 5) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC1_SHIFT(reg, x) \ - ((reg) = GX_BITSET((reg), 23, 5, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC1_SHIFT(reg) GX_BITGET((reg), 23, 5) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC1_SHIFT(reg, x) ((reg) = GX_BITSET((reg), 23, 5, x)) // TXC2_CNT [22:22] (1) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC2_CNT_B 22 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC2_CNT_E 22 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC2_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC2_CNT_B 22 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC2_CNT_E 22 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC2_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC2_CNT_MASK \ - (((1 << 1) - 1) << 31 - 22) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC2_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC2_CNT_SHIFT 9 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC2_CNT_MASK (((1 << 1) - 1) << 31 - 22) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC2_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC2_CNT_SHIFT 9 -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC2_CNT(reg) \ - GX_BITGET((reg), 22, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC2_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 22, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC2_CNT(reg) GX_BITGET((reg), 22, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC2_CNT(reg, x) ((reg) = GX_BITSET((reg), 22, 1, x)) // TXC2_TYPE [19:21] (3) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_B 19 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_E 21 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_B 19 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_E 21 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 21) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_SHIFT 10 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_MASK (((1 << 3) - 1) << 31 - 21) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC2_TYPE_SHIFT 10 -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC2_TYPE(reg) \ - GX_BITGET((reg), 19, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC2_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 19, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC2_TYPE(reg) GX_BITGET((reg), 19, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC2_TYPE(reg, x) ((reg) = GX_BITSET((reg), 19, 3, x)) // TXC2_SHIFT [14:18] (5) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_B 14 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_E 18 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_SZ 5 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_B 14 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_E 18 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_SZ 5 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_MASK \ - (((1 << 5) - 1) << 31 - 18) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_SHIFT 13 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_MASK (((1 << 5) - 1) << 31 - 18) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC2_SHIFT_SHIFT 13 -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC2_SHIFT(reg) \ - GX_BITGET((reg), 14, 5) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC2_SHIFT(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 5, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC2_SHIFT(reg) GX_BITGET((reg), 14, 5) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC2_SHIFT(reg, x) ((reg) = GX_BITSET((reg), 14, 5, x)) // TXC3_CNT [13:13] (1) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC3_CNT_B 13 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC3_CNT_E 13 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC3_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC3_CNT_B 13 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC3_CNT_E 13 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC3_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC3_CNT_MASK \ - (((1 << 1) - 1) << 31 - 13) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC3_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC3_CNT_SHIFT 18 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC3_CNT_MASK (((1 << 1) - 1) << 31 - 13) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC3_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC3_CNT_SHIFT 18 -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC3_CNT(reg) \ - GX_BITGET((reg), 13, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC3_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 13, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC3_CNT(reg) GX_BITGET((reg), 13, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC3_CNT(reg, x) ((reg) = GX_BITSET((reg), 13, 1, x)) // TXC3_TYPE [10:12] (3) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_B 10 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_E 12 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_B 10 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_E 12 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 12) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_SHIFT 19 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_MASK (((1 << 3) - 1) << 31 - 12) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC3_TYPE_SHIFT 19 -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC3_TYPE(reg) \ - GX_BITGET((reg), 10, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC3_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 10, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC3_TYPE(reg) GX_BITGET((reg), 10, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC3_TYPE(reg, x) ((reg) = GX_BITSET((reg), 10, 3, x)) // TXC3_SHIFT [5:9] (5) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_B 5 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_E 9 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_SZ 5 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_B 5 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_E 9 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_SZ 5 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_MASK \ - (((1 << 5) - 1) << 31 - 9) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_SHIFT 22 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_MASK (((1 << 5) - 1) << 31 - 9) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC3_SHIFT_SHIFT 22 -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC3_SHIFT(reg) \ - GX_BITGET((reg), 5, 5) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC3_SHIFT(reg, x) \ - ((reg) = GX_BITSET((reg), 5, 5, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC3_SHIFT(reg) GX_BITGET((reg), 5, 5) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC3_SHIFT(reg, x) ((reg) = GX_BITSET((reg), 5, 5, x)) // TXC4_CNT [4:4] (1) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC4_CNT_B 4 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC4_CNT_E 4 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC4_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC4_CNT_B 4 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC4_CNT_E 4 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC4_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC4_CNT_MASK \ - (((1 << 1) - 1) << 31 - 4) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC4_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC4_CNT_SHIFT 27 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC4_CNT_MASK (((1 << 1) - 1) << 31 - 4) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC4_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC4_CNT_SHIFT 27 -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC4_CNT(reg) \ - GX_BITGET((reg), 4, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC4_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 4, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC4_CNT(reg) GX_BITGET((reg), 4, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC4_CNT(reg, x) ((reg) = GX_BITSET((reg), 4, 1, x)) // TXC4_TYPE [1:3] (3) -/* start bit */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_B 1 -/* end bit */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_E 3 -/* bit size */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_B 1 + /* end bit */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_E 3 + /* bit size */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 3) -/* local mask */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_SHIFT 28 + /* raw mask */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_MASK (((1 << 3) - 1) << 31 - 3) + /* local mask */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP1_TXC4_TYPE_SHIFT 28 + + /* get value */ #define GX_CP_GET_VAT_GROUP1_TXC4_TYPE(reg) GX_BITGET((reg), 1, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP1_TXC4_TYPE(reg, x) ((reg) = GX_BITSET((reg), 1, 3, x)) -/* get value */ #define GX_CP_GET_VAT_GROUP1_TXC4_TYPE(reg) \ - GX_BITGET((reg), 1, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP1_TXC4_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 1, 3, x)) /****************************************************************************** * CP register 0x90 - VAT_group2 *****************************************************************************/ // TXC4_SHIFT [27:31] (5) -/* start bit */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_B 27 -/* end bit */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_E 31 -/* bit size */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_SZ 5 + /* start bit */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_B 27 + /* end bit */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_E 31 + /* bit size */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_SZ 5 -/* raw mask */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_MASK \ - (((1 << 5) - 1) << 31 - 31) -/* local mask */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_SHIFT 0 + /* raw mask */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_MASK (((1 << 5) - 1) << 31 - 31) + /* local mask */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP2_TXC4_SHIFT_SHIFT 0 -/* get value */ #define GX_CP_GET_VAT_GROUP2_TXC4_SHIFT(reg) \ - GX_BITGET((reg), 27, 5) -/* set value */ #define GX_CP_SET_VAT_GROUP2_TXC4_SHIFT(reg, x) \ - ((reg) = GX_BITSET((reg), 27, 5, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP2_TXC4_SHIFT(reg) GX_BITGET((reg), 27, 5) + /* set value */ #define GX_CP_SET_VAT_GROUP2_TXC4_SHIFT(reg, x) ((reg) = GX_BITSET((reg), 27, 5, x)) // TXC5_CNT [26:26] (1) -/* start bit */ #define GX_CP_VAT_GROUP2_TXC5_CNT_B 26 -/* end bit */ #define GX_CP_VAT_GROUP2_TXC5_CNT_E 26 -/* bit size */ #define GX_CP_VAT_GROUP2_TXC5_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP2_TXC5_CNT_B 26 + /* end bit */ #define GX_CP_VAT_GROUP2_TXC5_CNT_E 26 + /* bit size */ #define GX_CP_VAT_GROUP2_TXC5_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP2_TXC5_CNT_MASK \ - (((1 << 1) - 1) << 31 - 26) -/* local mask */ #define GX_CP_VAT_GROUP2_TXC5_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP2_TXC5_CNT_SHIFT 5 + /* raw mask */ #define GX_CP_VAT_GROUP2_TXC5_CNT_MASK (((1 << 1) - 1) << 31 - 26) + /* local mask */ #define GX_CP_VAT_GROUP2_TXC5_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP2_TXC5_CNT_SHIFT 5 -/* get value */ #define GX_CP_GET_VAT_GROUP2_TXC5_CNT(reg) \ - GX_BITGET((reg), 26, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP2_TXC5_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP2_TXC5_CNT(reg) GX_BITGET((reg), 26, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP2_TXC5_CNT(reg, x) ((reg) = GX_BITSET((reg), 26, 1, x)) // TXC5_TYPE [23:25] (3) -/* start bit */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_B 23 -/* end bit */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_E 25 -/* bit size */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_B 23 + /* end bit */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_E 25 + /* bit size */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 25) -/* local mask */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_SHIFT 6 + /* raw mask */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_MASK (((1 << 3) - 1) << 31 - 25) + /* local mask */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP2_TXC5_TYPE_SHIFT 6 -/* get value */ #define GX_CP_GET_VAT_GROUP2_TXC5_TYPE(reg) \ - GX_BITGET((reg), 23, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP2_TXC5_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 23, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP2_TXC5_TYPE(reg) GX_BITGET((reg), 23, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP2_TXC5_TYPE(reg, x) ((reg) = GX_BITSET((reg), 23, 3, x)) // TXC5_SHIFT [18:22] (5) -/* start bit */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_B 18 -/* end bit */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_E 22 -/* bit size */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_SZ 5 + /* start bit */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_B 18 + /* end bit */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_E 22 + /* bit size */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_SZ 5 -/* raw mask */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_MASK \ - (((1 << 5) - 1) << 31 - 22) -/* local mask */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_SHIFT 9 + /* raw mask */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_MASK (((1 << 5) - 1) << 31 - 22) + /* local mask */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP2_TXC5_SHIFT_SHIFT 9 -/* get value */ #define GX_CP_GET_VAT_GROUP2_TXC5_SHIFT(reg) \ - GX_BITGET((reg), 18, 5) -/* set value */ #define GX_CP_SET_VAT_GROUP2_TXC5_SHIFT(reg, x) \ - ((reg) = GX_BITSET((reg), 18, 5, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP2_TXC5_SHIFT(reg) GX_BITGET((reg), 18, 5) + /* set value */ #define GX_CP_SET_VAT_GROUP2_TXC5_SHIFT(reg, x) ((reg) = GX_BITSET((reg), 18, 5, x)) // TXC6_CNT [17:17] (1) -/* start bit */ #define GX_CP_VAT_GROUP2_TXC6_CNT_B 17 -/* end bit */ #define GX_CP_VAT_GROUP2_TXC6_CNT_E 17 -/* bit size */ #define GX_CP_VAT_GROUP2_TXC6_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP2_TXC6_CNT_B 17 + /* end bit */ #define GX_CP_VAT_GROUP2_TXC6_CNT_E 17 + /* bit size */ #define GX_CP_VAT_GROUP2_TXC6_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP2_TXC6_CNT_MASK \ - (((1 << 1) - 1) << 31 - 17) -/* local mask */ #define GX_CP_VAT_GROUP2_TXC6_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP2_TXC6_CNT_SHIFT 14 + /* raw mask */ #define GX_CP_VAT_GROUP2_TXC6_CNT_MASK (((1 << 1) - 1) << 31 - 17) + /* local mask */ #define GX_CP_VAT_GROUP2_TXC6_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP2_TXC6_CNT_SHIFT 14 -/* get value */ #define GX_CP_GET_VAT_GROUP2_TXC6_CNT(reg) \ - GX_BITGET((reg), 17, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP2_TXC6_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 17, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP2_TXC6_CNT(reg) GX_BITGET((reg), 17, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP2_TXC6_CNT(reg, x) ((reg) = GX_BITSET((reg), 17, 1, x)) // TXC6_TYPE [14:16] (3) -/* start bit */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_B 14 -/* end bit */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_E 16 -/* bit size */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_B 14 + /* end bit */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_E 16 + /* bit size */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 16) -/* local mask */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_SHIFT 15 + /* raw mask */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_MASK (((1 << 3) - 1) << 31 - 16) + /* local mask */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP2_TXC6_TYPE_SHIFT 15 -/* get value */ #define GX_CP_GET_VAT_GROUP2_TXC6_TYPE(reg) \ - GX_BITGET((reg), 14, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP2_TXC6_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP2_TXC6_TYPE(reg) GX_BITGET((reg), 14, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP2_TXC6_TYPE(reg, x) ((reg) = GX_BITSET((reg), 14, 3, x)) // TXC6_SHIFT [9:13] (5) -/* start bit */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_B 9 -/* end bit */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_E 13 -/* bit size */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_SZ 5 + /* start bit */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_B 9 + /* end bit */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_E 13 + /* bit size */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_SZ 5 -/* raw mask */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_MASK \ - (((1 << 5) - 1) << 31 - 13) -/* local mask */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_SHIFT 18 + /* raw mask */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_MASK (((1 << 5) - 1) << 31 - 13) + /* local mask */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP2_TXC6_SHIFT_SHIFT 18 -/* get value */ #define GX_CP_GET_VAT_GROUP2_TXC6_SHIFT(reg) \ - GX_BITGET((reg), 9, 5) -/* set value */ #define GX_CP_SET_VAT_GROUP2_TXC6_SHIFT(reg, x) \ - ((reg) = GX_BITSET((reg), 9, 5, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP2_TXC6_SHIFT(reg) GX_BITGET((reg), 9, 5) + /* set value */ #define GX_CP_SET_VAT_GROUP2_TXC6_SHIFT(reg, x) ((reg) = GX_BITSET((reg), 9, 5, x)) // TXC7_CNT [8:8] (1) -/* start bit */ #define GX_CP_VAT_GROUP2_TXC7_CNT_B 8 -/* end bit */ #define GX_CP_VAT_GROUP2_TXC7_CNT_E 8 -/* bit size */ #define GX_CP_VAT_GROUP2_TXC7_CNT_SZ 1 + /* start bit */ #define GX_CP_VAT_GROUP2_TXC7_CNT_B 8 + /* end bit */ #define GX_CP_VAT_GROUP2_TXC7_CNT_E 8 + /* bit size */ #define GX_CP_VAT_GROUP2_TXC7_CNT_SZ 1 -/* raw mask */ #define GX_CP_VAT_GROUP2_TXC7_CNT_MASK \ - (((1 << 1) - 1) << 31 - 8) -/* local mask */ #define GX_CP_VAT_GROUP2_TXC7_CNT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP2_TXC7_CNT_SHIFT 23 + /* raw mask */ #define GX_CP_VAT_GROUP2_TXC7_CNT_MASK (((1 << 1) - 1) << 31 - 8) + /* local mask */ #define GX_CP_VAT_GROUP2_TXC7_CNT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP2_TXC7_CNT_SHIFT 23 -/* get value */ #define GX_CP_GET_VAT_GROUP2_TXC7_CNT(reg) \ - GX_BITGET((reg), 8, 1) -/* set value */ #define GX_CP_SET_VAT_GROUP2_TXC7_CNT(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 1, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP2_TXC7_CNT(reg) GX_BITGET((reg), 8, 1) + /* set value */ #define GX_CP_SET_VAT_GROUP2_TXC7_CNT(reg, x) ((reg) = GX_BITSET((reg), 8, 1, x)) // TXC7_TYPE [5:7] (3) -/* start bit */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_B 5 -/* end bit */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_E 7 -/* bit size */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_SZ 3 + /* start bit */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_B 5 + /* end bit */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_E 7 + /* bit size */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_SZ 3 -/* raw mask */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_MASK \ - (((1 << 3) - 1) << 31 - 7) -/* local mask */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_SHIFT 24 + /* raw mask */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_MASK (((1 << 3) - 1) << 31 - 7) + /* local mask */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP2_TXC7_TYPE_SHIFT 24 -/* get value */ #define GX_CP_GET_VAT_GROUP2_TXC7_TYPE(reg) \ - GX_BITGET((reg), 5, 3) -/* set value */ #define GX_CP_SET_VAT_GROUP2_TXC7_TYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 5, 3, x)) + /* get value */ #define GX_CP_GET_VAT_GROUP2_TXC7_TYPE(reg) GX_BITGET((reg), 5, 3) + /* set value */ #define GX_CP_SET_VAT_GROUP2_TXC7_TYPE(reg, x) ((reg) = GX_BITSET((reg), 5, 3, x)) // TXC7_SHIFT [0:4] (5) -/* start bit */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_B 0 -/* end bit */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_E 4 -/* bit size */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_SZ 5 + /* start bit */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_B 0 + /* end bit */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_E 4 + /* bit size */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_SZ 5 + + /* raw mask */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_MASK (((1 << 5) - 1) << 31 - 4) + /* local mask */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_SHIFT 27 -/* raw mask */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_MASK \ - (((1 << 5) - 1) << 31 - 4) -/* local mask */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_CP_VAT_GROUP2_TXC7_SHIFT_SHIFT 27 + /* get value */ #define GX_CP_GET_VAT_GROUP2_TXC7_SHIFT(reg) GX_BITGET((reg), 0, 5) + /* set value */ #define GX_CP_SET_VAT_GROUP2_TXC7_SHIFT(reg, x) ((reg) = GX_BITSET((reg), 0, 5, x)) -/* get value */ #define GX_CP_GET_VAT_GROUP2_TXC7_SHIFT(reg) \ - GX_BITGET((reg), 0, 5) -/* set value */ #define GX_CP_SET_VAT_GROUP2_TXC7_SHIFT(reg, x) \ - ((reg) = GX_BITSET((reg), 0, 5, x)) /****************************************************************************** * CP register 0xA0 - ArrayBase *****************************************************************************/ // BASE [6:31] (26) -/* start bit */ #define GX_CP_ARRAYBASE_BASE_B 6 -/* end bit */ #define GX_CP_ARRAYBASE_BASE_E 31 -/* bit size */ #define GX_CP_ARRAYBASE_BASE_SZ 26 + /* start bit */ #define GX_CP_ARRAYBASE_BASE_B 6 + /* end bit */ #define GX_CP_ARRAYBASE_BASE_E 31 + /* bit size */ #define GX_CP_ARRAYBASE_BASE_SZ 26 -/* raw mask */ #define GX_CP_ARRAYBASE_BASE_MASK (((1 << 26) - 1) << 31 - 31) -/* local mask */ #define GX_CP_ARRAYBASE_BASE_LMASK ((1 << 26) - 1) -/* bit shift */ #define GX_CP_ARRAYBASE_BASE_SHIFT 0 + /* raw mask */ #define GX_CP_ARRAYBASE_BASE_MASK (((1 << 26) - 1) << 31 - 31) + /* local mask */ #define GX_CP_ARRAYBASE_BASE_LMASK ((1 << 26) - 1) + /* bit shift */ #define GX_CP_ARRAYBASE_BASE_SHIFT 0 + + /* get value */ #define GX_CP_GET_ARRAYBASE_BASE(reg) GX_BITGET((reg), 6, 26) + /* set value */ #define GX_CP_SET_ARRAYBASE_BASE(reg, x) ((reg) = GX_BITSET((reg), 6, 26, x)) -/* get value */ #define GX_CP_GET_ARRAYBASE_BASE(reg) GX_BITGET((reg), 6, 26) -/* set value */ #define GX_CP_SET_ARRAYBASE_BASE(reg, x) \ - ((reg) = GX_BITSET((reg), 6, 26, x)) /****************************************************************************** * CP register 0xB0 - ArrayStride *****************************************************************************/ // STRIDE [24:31] (8) -/* start bit */ #define GX_CP_ARRAYSTRIDE_STRIDE_B 24 -/* end bit */ #define GX_CP_ARRAYSTRIDE_STRIDE_E 31 -/* bit size */ #define GX_CP_ARRAYSTRIDE_STRIDE_SZ 8 + /* start bit */ #define GX_CP_ARRAYSTRIDE_STRIDE_B 24 + /* end bit */ #define GX_CP_ARRAYSTRIDE_STRIDE_E 31 + /* bit size */ #define GX_CP_ARRAYSTRIDE_STRIDE_SZ 8 + + /* raw mask */ #define GX_CP_ARRAYSTRIDE_STRIDE_MASK (((1 << 8) - 1) << 31 - 31) + /* local mask */ #define GX_CP_ARRAYSTRIDE_STRIDE_LMASK ((1 << 8) - 1) + /* bit shift */ #define GX_CP_ARRAYSTRIDE_STRIDE_SHIFT 0 + + /* get value */ #define GX_CP_GET_ARRAYSTRIDE_STRIDE(reg) GX_BITGET((reg), 24, 8) + /* set value */ #define GX_CP_SET_ARRAYSTRIDE_STRIDE(reg, x) ((reg) = GX_BITSET((reg), 24, 8, x)) -/* raw mask */ #define GX_CP_ARRAYSTRIDE_STRIDE_MASK \ - (((1 << 8) - 1) << 31 - 31) -/* local mask */ #define GX_CP_ARRAYSTRIDE_STRIDE_LMASK ((1 << 8) - 1) -/* bit shift */ #define GX_CP_ARRAYSTRIDE_STRIDE_SHIFT 0 -/* get value */ #define GX_CP_GET_ARRAYSTRIDE_STRIDE(reg) \ - GX_BITGET((reg), 24, 8) -/* set value */ #define GX_CP_SET_ARRAYSTRIDE_STRIDE(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 8, x)) #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/GX/GXHardwareXF.h b/include/revolution/GX/GXHardwareXF.h index c0aa748..988627d 100644 --- a/include/revolution/GX/GXHardwareXF.h +++ b/include/revolution/GX/GXHardwareXF.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_GX_HARDWARE_XF_H #define RVL_SDK_GX_HARDWARE_XF_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif @@ -76,481 +75,420 @@ typedef enum { * XF register 0x1005 - ClipDisable *****************************************************************************/ // DETECT [31:31] (1) - Disable clipping detection -/* start bit */ #define GX_XF_CLIPDISABLE_DETECT_B 31 -/* end bit */ #define GX_XF_CLIPDISABLE_DETECT_E 31 -/* bit size */ #define GX_XF_CLIPDISABLE_DETECT_SZ 1 + /* start bit */ #define GX_XF_CLIPDISABLE_DETECT_B 31 + /* end bit */ #define GX_XF_CLIPDISABLE_DETECT_E 31 + /* bit size */ #define GX_XF_CLIPDISABLE_DETECT_SZ 1 -/* raw mask */ #define GX_XF_CLIPDISABLE_DETECT_MASK \ - (((1 << 1) - 1) << 31 - 31) -/* local mask */ #define GX_XF_CLIPDISABLE_DETECT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_CLIPDISABLE_DETECT_SHIFT 0 + /* raw mask */ #define GX_XF_CLIPDISABLE_DETECT_MASK (((1 << 1) - 1) << 31 - 31) + /* local mask */ #define GX_XF_CLIPDISABLE_DETECT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_CLIPDISABLE_DETECT_SHIFT 0 -/* get value */ #define GX_XF_GET_CLIPDISABLE_DETECT(reg) \ - GX_BITGET((reg), 31, 1) -/* set value */ #define GX_XF_SET_CLIPDISABLE_DETECT(reg, x) \ - ((reg) = GX_BITSET((reg), 31, 1, x)) + /* get value */ #define GX_XF_GET_CLIPDISABLE_DETECT(reg) GX_BITGET((reg), 31, 1) + /* set value */ #define GX_XF_SET_CLIPDISABLE_DETECT(reg, x) ((reg) = GX_BITSET((reg), 31, 1, x)) // REJECT [30:30] (1) - Disable trivial rejection -/* start bit */ #define GX_XF_CLIPDISABLE_REJECT_B 30 -/* end bit */ #define GX_XF_CLIPDISABLE_REJECT_E 30 -/* bit size */ #define GX_XF_CLIPDISABLE_REJECT_SZ 1 + /* start bit */ #define GX_XF_CLIPDISABLE_REJECT_B 30 + /* end bit */ #define GX_XF_CLIPDISABLE_REJECT_E 30 + /* bit size */ #define GX_XF_CLIPDISABLE_REJECT_SZ 1 -/* raw mask */ #define GX_XF_CLIPDISABLE_REJECT_MASK \ - (((1 << 1) - 1) << 31 - 30) -/* local mask */ #define GX_XF_CLIPDISABLE_REJECT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_CLIPDISABLE_REJECT_SHIFT 1 + /* raw mask */ #define GX_XF_CLIPDISABLE_REJECT_MASK (((1 << 1) - 1) << 31 - 30) + /* local mask */ #define GX_XF_CLIPDISABLE_REJECT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_CLIPDISABLE_REJECT_SHIFT 1 -/* get value */ #define GX_XF_GET_CLIPDISABLE_REJECT(reg) \ - GX_BITGET((reg), 30, 1) -/* set value */ #define GX_XF_SET_CLIPDISABLE_REJECT(reg, x) \ - ((reg) = GX_BITSET((reg), 30, 1, x)) + /* get value */ #define GX_XF_GET_CLIPDISABLE_REJECT(reg) GX_BITGET((reg), 30, 1) + /* set value */ #define GX_XF_SET_CLIPDISABLE_REJECT(reg, x) ((reg) = GX_BITSET((reg), 30, 1, x)) // ACCEL [29:29] (1) - Disable cpoly clipping acceleration -/* start bit */ #define GX_XF_CLIPDISABLE_ACCEL_B 29 -/* end bit */ #define GX_XF_CLIPDISABLE_ACCEL_E 29 -/* bit size */ #define GX_XF_CLIPDISABLE_ACCEL_SZ 1 + /* start bit */ #define GX_XF_CLIPDISABLE_ACCEL_B 29 + /* end bit */ #define GX_XF_CLIPDISABLE_ACCEL_E 29 + /* bit size */ #define GX_XF_CLIPDISABLE_ACCEL_SZ 1 + + /* raw mask */ #define GX_XF_CLIPDISABLE_ACCEL_MASK (((1 << 1) - 1) << 31 - 29) + /* local mask */ #define GX_XF_CLIPDISABLE_ACCEL_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_CLIPDISABLE_ACCEL_SHIFT 2 -/* raw mask */ #define GX_XF_CLIPDISABLE_ACCEL_MASK \ - (((1 << 1) - 1) << 31 - 29) -/* local mask */ #define GX_XF_CLIPDISABLE_ACCEL_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_CLIPDISABLE_ACCEL_SHIFT 2 + /* get value */ #define GX_XF_GET_CLIPDISABLE_ACCEL(reg) GX_BITGET((reg), 29, 1) + /* set value */ #define GX_XF_SET_CLIPDISABLE_ACCEL(reg, x) ((reg) = GX_BITSET((reg), 29, 1, x)) -/* get value */ #define GX_XF_GET_CLIPDISABLE_ACCEL(reg) \ - GX_BITGET((reg), 29, 1) -/* set value */ #define GX_XF_SET_CLIPDISABLE_ACCEL(reg, x) \ - ((reg) = GX_BITSET((reg), 29, 1, x)) /****************************************************************************** * XF register 0x1007 - Perf1 *****************************************************************************/ // TARGET [25:31] (7) - Target performance (Cycles/vertex) -/* start bit */ #define GX_XF_PERF1_TARGET_B 25 -/* end bit */ #define GX_XF_PERF1_TARGET_E 31 -/* bit size */ #define GX_XF_PERF1_TARGET_SZ 7 + /* start bit */ #define GX_XF_PERF1_TARGET_B 25 + /* end bit */ #define GX_XF_PERF1_TARGET_E 31 + /* bit size */ #define GX_XF_PERF1_TARGET_SZ 7 -/* raw mask */ #define GX_XF_PERF1_TARGET_MASK (((1 << 7) - 1) << 31 - 31) -/* local mask */ #define GX_XF_PERF1_TARGET_LMASK ((1 << 7) - 1) -/* bit shift */ #define GX_XF_PERF1_TARGET_SHIFT 0 + /* raw mask */ #define GX_XF_PERF1_TARGET_MASK (((1 << 7) - 1) << 31 - 31) + /* local mask */ #define GX_XF_PERF1_TARGET_LMASK ((1 << 7) - 1) + /* bit shift */ #define GX_XF_PERF1_TARGET_SHIFT 0 + + /* get value */ #define GX_XF_GET_PERF1_TARGET(reg) GX_BITGET((reg), 25, 7) + /* set value */ #define GX_XF_SET_PERF1_TARGET(reg, x) ((reg) = GX_BITSET((reg), 25, 7, x)) -/* get value */ #define GX_XF_GET_PERF1_TARGET(reg) GX_BITGET((reg), 25, 7) -/* set value */ #define GX_XF_SET_PERF1_TARGET(reg, x) \ - ((reg) = GX_BITSET((reg), 25, 7, x)) /****************************************************************************** * XF register 0x1008 - InVertexSpec *****************************************************************************/ // CLR [30:31] (2) -/* start bit */ #define GX_XF_INVERTEXSPEC_CLR_B 30 -/* end bit */ #define GX_XF_INVERTEXSPEC_CLR_E 31 -/* bit size */ #define GX_XF_INVERTEXSPEC_CLR_SZ 2 + /* start bit */ #define GX_XF_INVERTEXSPEC_CLR_B 30 + /* end bit */ #define GX_XF_INVERTEXSPEC_CLR_E 31 + /* bit size */ #define GX_XF_INVERTEXSPEC_CLR_SZ 2 -/* raw mask */ #define GX_XF_INVERTEXSPEC_CLR_MASK (((1 << 2) - 1) << 31 - 31) -/* local mask */ #define GX_XF_INVERTEXSPEC_CLR_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_XF_INVERTEXSPEC_CLR_SHIFT 0 + /* raw mask */ #define GX_XF_INVERTEXSPEC_CLR_MASK (((1 << 2) - 1) << 31 - 31) + /* local mask */ #define GX_XF_INVERTEXSPEC_CLR_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_XF_INVERTEXSPEC_CLR_SHIFT 0 -/* get value */ #define GX_XF_GET_INVERTEXSPEC_CLR(reg) GX_BITGET((reg), 30, 2) -/* set value */ #define GX_XF_SET_INVERTEXSPEC_CLR(reg, x) \ - ((reg) = GX_BITSET((reg), 30, 2, x)) + /* get value */ #define GX_XF_GET_INVERTEXSPEC_CLR(reg) GX_BITGET((reg), 30, 2) + /* set value */ #define GX_XF_SET_INVERTEXSPEC_CLR(reg, x) ((reg) = GX_BITSET((reg), 30, 2, x)) // NRM [28:29] (2) -/* start bit */ #define GX_XF_INVERTEXSPEC_NRM_B 28 -/* end bit */ #define GX_XF_INVERTEXSPEC_NRM_E 29 -/* bit size */ #define GX_XF_INVERTEXSPEC_NRM_SZ 2 + /* start bit */ #define GX_XF_INVERTEXSPEC_NRM_B 28 + /* end bit */ #define GX_XF_INVERTEXSPEC_NRM_E 29 + /* bit size */ #define GX_XF_INVERTEXSPEC_NRM_SZ 2 -/* raw mask */ #define GX_XF_INVERTEXSPEC_NRM_MASK (((1 << 2) - 1) << 31 - 29) -/* local mask */ #define GX_XF_INVERTEXSPEC_NRM_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_XF_INVERTEXSPEC_NRM_SHIFT 2 + /* raw mask */ #define GX_XF_INVERTEXSPEC_NRM_MASK (((1 << 2) - 1) << 31 - 29) + /* local mask */ #define GX_XF_INVERTEXSPEC_NRM_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_XF_INVERTEXSPEC_NRM_SHIFT 2 -/* get value */ #define GX_XF_GET_INVERTEXSPEC_NRM(reg) GX_BITGET((reg), 28, 2) -/* set value */ #define GX_XF_SET_INVERTEXSPEC_NRM(reg, x) \ - ((reg) = GX_BITSET((reg), 28, 2, x)) + /* get value */ #define GX_XF_GET_INVERTEXSPEC_NRM(reg) GX_BITGET((reg), 28, 2) + /* set value */ #define GX_XF_SET_INVERTEXSPEC_NRM(reg, x) ((reg) = GX_BITSET((reg), 28, 2, x)) // TXC [24:27] (4) -/* start bit */ #define GX_XF_INVERTEXSPEC_TXC_B 24 -/* end bit */ #define GX_XF_INVERTEXSPEC_TXC_E 27 -/* bit size */ #define GX_XF_INVERTEXSPEC_TXC_SZ 4 + /* start bit */ #define GX_XF_INVERTEXSPEC_TXC_B 24 + /* end bit */ #define GX_XF_INVERTEXSPEC_TXC_E 27 + /* bit size */ #define GX_XF_INVERTEXSPEC_TXC_SZ 4 + + /* raw mask */ #define GX_XF_INVERTEXSPEC_TXC_MASK (((1 << 4) - 1) << 31 - 27) + /* local mask */ #define GX_XF_INVERTEXSPEC_TXC_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_XF_INVERTEXSPEC_TXC_SHIFT 4 -/* raw mask */ #define GX_XF_INVERTEXSPEC_TXC_MASK (((1 << 4) - 1) << 31 - 27) -/* local mask */ #define GX_XF_INVERTEXSPEC_TXC_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_XF_INVERTEXSPEC_TXC_SHIFT 4 + /* get value */ #define GX_XF_GET_INVERTEXSPEC_TXC(reg) GX_BITGET((reg), 24, 4) + /* set value */ #define GX_XF_SET_INVERTEXSPEC_TXC(reg, x) ((reg) = GX_BITSET((reg), 24, 4, x)) -/* get value */ #define GX_XF_GET_INVERTEXSPEC_TXC(reg) GX_BITGET((reg), 24, 4) -/* set value */ #define GX_XF_SET_INVERTEXSPEC_TXC(reg, x) \ - ((reg) = GX_BITSET((reg), 24, 4, x)) /****************************************************************************** * XF register 0x100E - Color0Cntrl *****************************************************************************/ // MATSRC [31:31] (1) -/* start bit */ #define GX_XF_COLOR0CNTRL_MATSRC_B 31 -/* end bit */ #define GX_XF_COLOR0CNTRL_MATSRC_E 31 -/* bit size */ #define GX_XF_COLOR0CNTRL_MATSRC_SZ 1 + /* start bit */ #define GX_XF_COLOR0CNTRL_MATSRC_B 31 + /* end bit */ #define GX_XF_COLOR0CNTRL_MATSRC_E 31 + /* bit size */ #define GX_XF_COLOR0CNTRL_MATSRC_SZ 1 -/* raw mask */ #define GX_XF_COLOR0CNTRL_MATSRC_MASK \ - (((1 << 1) - 1) << 31 - 31) -/* local mask */ #define GX_XF_COLOR0CNTRL_MATSRC_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_COLOR0CNTRL_MATSRC_SHIFT 0 + /* raw mask */ #define GX_XF_COLOR0CNTRL_MATSRC_MASK (((1 << 1) - 1) << 31 - 31) + /* local mask */ #define GX_XF_COLOR0CNTRL_MATSRC_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_COLOR0CNTRL_MATSRC_SHIFT 0 -/* get value */ #define GX_XF_GET_COLOR0CNTRL_MATSRC(reg) \ - GX_BITGET((reg), 31, 1) -/* set value */ #define GX_XF_SET_COLOR0CNTRL_MATSRC(reg, x) \ - ((reg) = GX_BITSET((reg), 31, 1, x)) + /* get value */ #define GX_XF_GET_COLOR0CNTRL_MATSRC(reg) GX_BITGET((reg), 31, 1) + /* set value */ #define GX_XF_SET_COLOR0CNTRL_MATSRC(reg, x) ((reg) = GX_BITSET((reg), 31, 1, x)) // LIGHT [30:30] (1) -/* start bit */ #define GX_XF_COLOR0CNTRL_LIGHT_B 30 -/* end bit */ #define GX_XF_COLOR0CNTRL_LIGHT_E 30 -/* bit size */ #define GX_XF_COLOR0CNTRL_LIGHT_SZ 1 + /* start bit */ #define GX_XF_COLOR0CNTRL_LIGHT_B 30 + /* end bit */ #define GX_XF_COLOR0CNTRL_LIGHT_E 30 + /* bit size */ #define GX_XF_COLOR0CNTRL_LIGHT_SZ 1 -/* raw mask */ #define GX_XF_COLOR0CNTRL_LIGHT_MASK \ - (((1 << 1) - 1) << 31 - 30) -/* local mask */ #define GX_XF_COLOR0CNTRL_LIGHT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_COLOR0CNTRL_LIGHT_SHIFT 1 + /* raw mask */ #define GX_XF_COLOR0CNTRL_LIGHT_MASK (((1 << 1) - 1) << 31 - 30) + /* local mask */ #define GX_XF_COLOR0CNTRL_LIGHT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_COLOR0CNTRL_LIGHT_SHIFT 1 -/* get value */ #define GX_XF_GET_COLOR0CNTRL_LIGHT(reg) \ - GX_BITGET((reg), 30, 1) -/* set value */ #define GX_XF_SET_COLOR0CNTRL_LIGHT(reg, x) \ - ((reg) = GX_BITSET((reg), 30, 1, x)) + /* get value */ #define GX_XF_GET_COLOR0CNTRL_LIGHT(reg) GX_BITGET((reg), 30, 1) + /* set value */ #define GX_XF_SET_COLOR0CNTRL_LIGHT(reg, x) ((reg) = GX_BITSET((reg), 30, 1, x)) // LMASKLO [26:29] (4) -/* start bit */ #define GX_XF_COLOR0CNTRL_LMASKLO_B 26 -/* end bit */ #define GX_XF_COLOR0CNTRL_LMASKLO_E 29 -/* bit size */ #define GX_XF_COLOR0CNTRL_LMASKLO_SZ 4 + /* start bit */ #define GX_XF_COLOR0CNTRL_LMASKLO_B 26 + /* end bit */ #define GX_XF_COLOR0CNTRL_LMASKLO_E 29 + /* bit size */ #define GX_XF_COLOR0CNTRL_LMASKLO_SZ 4 -/* raw mask */ #define GX_XF_COLOR0CNTRL_LMASKLO_MASK \ - (((1 << 4) - 1) << 31 - 29) -/* local mask */ #define GX_XF_COLOR0CNTRL_LMASKLO_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_XF_COLOR0CNTRL_LMASKLO_SHIFT 2 + /* raw mask */ #define GX_XF_COLOR0CNTRL_LMASKLO_MASK (((1 << 4) - 1) << 31 - 29) + /* local mask */ #define GX_XF_COLOR0CNTRL_LMASKLO_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_XF_COLOR0CNTRL_LMASKLO_SHIFT 2 -/* get value */ #define GX_XF_GET_COLOR0CNTRL_LMASKLO(reg) \ - GX_BITGET((reg), 26, 4) -/* set value */ #define GX_XF_SET_COLOR0CNTRL_LMASKLO(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 4, x)) + /* get value */ #define GX_XF_GET_COLOR0CNTRL_LMASKLO(reg) GX_BITGET((reg), 26, 4) + /* set value */ #define GX_XF_SET_COLOR0CNTRL_LMASKLO(reg, x) ((reg) = GX_BITSET((reg), 26, 4, x)) // AMBSRC [25:25] (1) -/* start bit */ #define GX_XF_COLOR0CNTRL_AMBSRC_B 25 -/* end bit */ #define GX_XF_COLOR0CNTRL_AMBSRC_E 25 -/* bit size */ #define GX_XF_COLOR0CNTRL_AMBSRC_SZ 1 + /* start bit */ #define GX_XF_COLOR0CNTRL_AMBSRC_B 25 + /* end bit */ #define GX_XF_COLOR0CNTRL_AMBSRC_E 25 + /* bit size */ #define GX_XF_COLOR0CNTRL_AMBSRC_SZ 1 -/* raw mask */ #define GX_XF_COLOR0CNTRL_AMBSRC_MASK \ - (((1 << 1) - 1) << 31 - 25) -/* local mask */ #define GX_XF_COLOR0CNTRL_AMBSRC_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_COLOR0CNTRL_AMBSRC_SHIFT 6 + /* raw mask */ #define GX_XF_COLOR0CNTRL_AMBSRC_MASK (((1 << 1) - 1) << 31 - 25) + /* local mask */ #define GX_XF_COLOR0CNTRL_AMBSRC_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_COLOR0CNTRL_AMBSRC_SHIFT 6 -/* get value */ #define GX_XF_GET_COLOR0CNTRL_AMBSRC(reg) \ - GX_BITGET((reg), 25, 1) -/* set value */ #define GX_XF_SET_COLOR0CNTRL_AMBSRC(reg, x) \ - ((reg) = GX_BITSET((reg), 25, 1, x)) + /* get value */ #define GX_XF_GET_COLOR0CNTRL_AMBSRC(reg) GX_BITGET((reg), 25, 1) + /* set value */ #define GX_XF_SET_COLOR0CNTRL_AMBSRC(reg, x) ((reg) = GX_BITSET((reg), 25, 1, x)) // DIFFUSEATTN [23:24] (2) -/* start bit */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_B 23 -/* end bit */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_E 24 -/* bit size */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_SZ 2 + /* start bit */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_B 23 + /* end bit */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_E 24 + /* bit size */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_SZ 2 -/* raw mask */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_MASK \ - (((1 << 2) - 1) << 31 - 24) -/* local mask */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_LMASK ((1 << 2) - 1) -/* bit shift */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_SHIFT 7 + /* raw mask */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_MASK (((1 << 2) - 1) << 31 - 24) + /* local mask */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_LMASK ((1 << 2) - 1) + /* bit shift */ #define GX_XF_COLOR0CNTRL_DIFFUSEATTN_SHIFT 7 -/* get value */ #define GX_XF_GET_COLOR0CNTRL_DIFFUSEATTN(reg) \ - GX_BITGET((reg), 23, 2) -/* set value */ #define GX_XF_SET_COLOR0CNTRL_DIFFUSEATTN(reg, x) \ - ((reg) = GX_BITSET((reg), 23, 2, x)) + /* get value */ #define GX_XF_GET_COLOR0CNTRL_DIFFUSEATTN(reg) GX_BITGET((reg), 23, 2) + /* set value */ #define GX_XF_SET_COLOR0CNTRL_DIFFUSEATTN(reg, x) ((reg) = GX_BITSET((reg), 23, 2, x)) // ATTNENABLE [22:22] (1) -/* start bit */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_B 22 -/* end bit */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_E 22 -/* bit size */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_SZ 1 + /* start bit */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_B 22 + /* end bit */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_E 22 + /* bit size */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_SZ 1 -/* raw mask */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_MASK \ - (((1 << 1) - 1) << 31 - 22) -/* local mask */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_SHIFT 9 + /* raw mask */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_MASK (((1 << 1) - 1) << 31 - 22) + /* local mask */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_COLOR0CNTRL_ATTNENABLE_SHIFT 9 -/* get value */ #define GX_XF_GET_COLOR0CNTRL_ATTNENABLE(reg) \ - GX_BITGET((reg), 22, 1) -/* set value */ #define GX_XF_SET_COLOR0CNTRL_ATTNENABLE(reg, x) \ - ((reg) = GX_BITSET((reg), 22, 1, x)) + /* get value */ #define GX_XF_GET_COLOR0CNTRL_ATTNENABLE(reg) GX_BITGET((reg), 22, 1) + /* set value */ #define GX_XF_SET_COLOR0CNTRL_ATTNENABLE(reg, x) ((reg) = GX_BITSET((reg), 22, 1, x)) // ATTNSELECT [21:21] (1) -/* start bit */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_B 21 -/* end bit */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_E 21 -/* bit size */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_SZ 1 + /* start bit */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_B 21 + /* end bit */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_E 21 + /* bit size */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_SZ 1 -/* raw mask */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_MASK \ - (((1 << 1) - 1) << 31 - 21) -/* local mask */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_SHIFT 10 + /* raw mask */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_MASK (((1 << 1) - 1) << 31 - 21) + /* local mask */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_COLOR0CNTRL_ATTNSELECT_SHIFT 10 -/* get value */ #define GX_XF_GET_COLOR0CNTRL_ATTNSELECT(reg) \ - GX_BITGET((reg), 21, 1) -/* set value */ #define GX_XF_SET_COLOR0CNTRL_ATTNSELECT(reg, x) \ - ((reg) = GX_BITSET((reg), 21, 1, x)) + /* get value */ #define GX_XF_GET_COLOR0CNTRL_ATTNSELECT(reg) GX_BITGET((reg), 21, 1) + /* set value */ #define GX_XF_SET_COLOR0CNTRL_ATTNSELECT(reg, x) ((reg) = GX_BITSET((reg), 21, 1, x)) // LMASKHI [17:20] (4) -/* start bit */ #define GX_XF_COLOR0CNTRL_LMASKHI_B 17 -/* end bit */ #define GX_XF_COLOR0CNTRL_LMASKHI_E 20 -/* bit size */ #define GX_XF_COLOR0CNTRL_LMASKHI_SZ 4 + /* start bit */ #define GX_XF_COLOR0CNTRL_LMASKHI_B 17 + /* end bit */ #define GX_XF_COLOR0CNTRL_LMASKHI_E 20 + /* bit size */ #define GX_XF_COLOR0CNTRL_LMASKHI_SZ 4 + + /* raw mask */ #define GX_XF_COLOR0CNTRL_LMASKHI_MASK (((1 << 4) - 1) << 31 - 20) + /* local mask */ #define GX_XF_COLOR0CNTRL_LMASKHI_LMASK ((1 << 4) - 1) + /* bit shift */ #define GX_XF_COLOR0CNTRL_LMASKHI_SHIFT 11 -/* raw mask */ #define GX_XF_COLOR0CNTRL_LMASKHI_MASK \ - (((1 << 4) - 1) << 31 - 20) -/* local mask */ #define GX_XF_COLOR0CNTRL_LMASKHI_LMASK ((1 << 4) - 1) -/* bit shift */ #define GX_XF_COLOR0CNTRL_LMASKHI_SHIFT 11 + /* get value */ #define GX_XF_GET_COLOR0CNTRL_LMASKHI(reg) GX_BITGET((reg), 17, 4) + /* set value */ #define GX_XF_SET_COLOR0CNTRL_LMASKHI(reg, x) ((reg) = GX_BITSET((reg), 17, 4, x)) -/* get value */ #define GX_XF_GET_COLOR0CNTRL_LMASKHI(reg) \ - GX_BITGET((reg), 17, 4) -/* set value */ #define GX_XF_SET_COLOR0CNTRL_LMASKHI(reg, x) \ - ((reg) = GX_BITSET((reg), 17, 4, x)) /****************************************************************************** * XF register 0x1018 - MatrixIndex0 *****************************************************************************/ // GEOM [26:31] (6) -/* start bit */ #define GX_XF_MATRIXINDEX0_GEOM_B 26 -/* end bit */ #define GX_XF_MATRIXINDEX0_GEOM_E 31 -/* bit size */ #define GX_XF_MATRIXINDEX0_GEOM_SZ 6 + /* start bit */ #define GX_XF_MATRIXINDEX0_GEOM_B 26 + /* end bit */ #define GX_XF_MATRIXINDEX0_GEOM_E 31 + /* bit size */ #define GX_XF_MATRIXINDEX0_GEOM_SZ 6 -/* raw mask */ #define GX_XF_MATRIXINDEX0_GEOM_MASK \ - (((1 << 6) - 1) << 31 - 31) -/* local mask */ #define GX_XF_MATRIXINDEX0_GEOM_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_XF_MATRIXINDEX0_GEOM_SHIFT 0 + /* raw mask */ #define GX_XF_MATRIXINDEX0_GEOM_MASK (((1 << 6) - 1) << 31 - 31) + /* local mask */ #define GX_XF_MATRIXINDEX0_GEOM_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_XF_MATRIXINDEX0_GEOM_SHIFT 0 -/* get value */ #define GX_XF_GET_MATRIXINDEX0_GEOM(reg) \ - GX_BITGET((reg), 26, 6) -/* set value */ #define GX_XF_SET_MATRIXINDEX0_GEOM(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 6, x)) + /* get value */ #define GX_XF_GET_MATRIXINDEX0_GEOM(reg) GX_BITGET((reg), 26, 6) + /* set value */ #define GX_XF_SET_MATRIXINDEX0_GEOM(reg, x) ((reg) = GX_BITSET((reg), 26, 6, x)) // TEX0 [20:25] (6) -/* start bit */ #define GX_XF_MATRIXINDEX0_TEX0_B 20 -/* end bit */ #define GX_XF_MATRIXINDEX0_TEX0_E 25 -/* bit size */ #define GX_XF_MATRIXINDEX0_TEX0_SZ 6 + /* start bit */ #define GX_XF_MATRIXINDEX0_TEX0_B 20 + /* end bit */ #define GX_XF_MATRIXINDEX0_TEX0_E 25 + /* bit size */ #define GX_XF_MATRIXINDEX0_TEX0_SZ 6 -/* raw mask */ #define GX_XF_MATRIXINDEX0_TEX0_MASK \ - (((1 << 6) - 1) << 31 - 25) -/* local mask */ #define GX_XF_MATRIXINDEX0_TEX0_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_XF_MATRIXINDEX0_TEX0_SHIFT 6 + /* raw mask */ #define GX_XF_MATRIXINDEX0_TEX0_MASK (((1 << 6) - 1) << 31 - 25) + /* local mask */ #define GX_XF_MATRIXINDEX0_TEX0_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_XF_MATRIXINDEX0_TEX0_SHIFT 6 -/* get value */ #define GX_XF_GET_MATRIXINDEX0_TEX0(reg) \ - GX_BITGET((reg), 20, 6) -/* set value */ #define GX_XF_SET_MATRIXINDEX0_TEX0(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 6, x)) + /* get value */ #define GX_XF_GET_MATRIXINDEX0_TEX0(reg) GX_BITGET((reg), 20, 6) + /* set value */ #define GX_XF_SET_MATRIXINDEX0_TEX0(reg, x) ((reg) = GX_BITSET((reg), 20, 6, x)) // TEX1 [14:19] (6) -/* start bit */ #define GX_XF_MATRIXINDEX0_TEX1_B 14 -/* end bit */ #define GX_XF_MATRIXINDEX0_TEX1_E 19 -/* bit size */ #define GX_XF_MATRIXINDEX0_TEX1_SZ 6 + /* start bit */ #define GX_XF_MATRIXINDEX0_TEX1_B 14 + /* end bit */ #define GX_XF_MATRIXINDEX0_TEX1_E 19 + /* bit size */ #define GX_XF_MATRIXINDEX0_TEX1_SZ 6 -/* raw mask */ #define GX_XF_MATRIXINDEX0_TEX1_MASK \ - (((1 << 6) - 1) << 31 - 19) -/* local mask */ #define GX_XF_MATRIXINDEX0_TEX1_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_XF_MATRIXINDEX0_TEX1_SHIFT 12 + /* raw mask */ #define GX_XF_MATRIXINDEX0_TEX1_MASK (((1 << 6) - 1) << 31 - 19) + /* local mask */ #define GX_XF_MATRIXINDEX0_TEX1_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_XF_MATRIXINDEX0_TEX1_SHIFT 12 -/* get value */ #define GX_XF_GET_MATRIXINDEX0_TEX1(reg) \ - GX_BITGET((reg), 14, 6) -/* set value */ #define GX_XF_SET_MATRIXINDEX0_TEX1(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 6, x)) + /* get value */ #define GX_XF_GET_MATRIXINDEX0_TEX1(reg) GX_BITGET((reg), 14, 6) + /* set value */ #define GX_XF_SET_MATRIXINDEX0_TEX1(reg, x) ((reg) = GX_BITSET((reg), 14, 6, x)) // TEX2 [8:13] (6) -/* start bit */ #define GX_XF_MATRIXINDEX0_TEX2_B 8 -/* end bit */ #define GX_XF_MATRIXINDEX0_TEX2_E 13 -/* bit size */ #define GX_XF_MATRIXINDEX0_TEX2_SZ 6 + /* start bit */ #define GX_XF_MATRIXINDEX0_TEX2_B 8 + /* end bit */ #define GX_XF_MATRIXINDEX0_TEX2_E 13 + /* bit size */ #define GX_XF_MATRIXINDEX0_TEX2_SZ 6 -/* raw mask */ #define GX_XF_MATRIXINDEX0_TEX2_MASK \ - (((1 << 6) - 1) << 31 - 13) -/* local mask */ #define GX_XF_MATRIXINDEX0_TEX2_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_XF_MATRIXINDEX0_TEX2_SHIFT 18 + /* raw mask */ #define GX_XF_MATRIXINDEX0_TEX2_MASK (((1 << 6) - 1) << 31 - 13) + /* local mask */ #define GX_XF_MATRIXINDEX0_TEX2_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_XF_MATRIXINDEX0_TEX2_SHIFT 18 -/* get value */ #define GX_XF_GET_MATRIXINDEX0_TEX2(reg) GX_BITGET((reg), 8, 6) -/* set value */ #define GX_XF_SET_MATRIXINDEX0_TEX2(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 6, x)) + /* get value */ #define GX_XF_GET_MATRIXINDEX0_TEX2(reg) GX_BITGET((reg), 8, 6) + /* set value */ #define GX_XF_SET_MATRIXINDEX0_TEX2(reg, x) ((reg) = GX_BITSET((reg), 8, 6, x)) // TEX3 [2:7] (6) -/* start bit */ #define GX_XF_MATRIXINDEX0_TEX3_B 2 -/* end bit */ #define GX_XF_MATRIXINDEX0_TEX3_E 7 -/* bit size */ #define GX_XF_MATRIXINDEX0_TEX3_SZ 6 + /* start bit */ #define GX_XF_MATRIXINDEX0_TEX3_B 2 + /* end bit */ #define GX_XF_MATRIXINDEX0_TEX3_E 7 + /* bit size */ #define GX_XF_MATRIXINDEX0_TEX3_SZ 6 -/* raw mask */ #define GX_XF_MATRIXINDEX0_TEX3_MASK (((1 << 6) - 1) << 31 - 7) -/* local mask */ #define GX_XF_MATRIXINDEX0_TEX3_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_XF_MATRIXINDEX0_TEX3_SHIFT 24 + /* raw mask */ #define GX_XF_MATRIXINDEX0_TEX3_MASK (((1 << 6) - 1) << 31 - 7) + /* local mask */ #define GX_XF_MATRIXINDEX0_TEX3_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_XF_MATRIXINDEX0_TEX3_SHIFT 24 + + /* get value */ #define GX_XF_GET_MATRIXINDEX0_TEX3(reg) GX_BITGET((reg), 2, 6) + /* set value */ #define GX_XF_SET_MATRIXINDEX0_TEX3(reg, x) ((reg) = GX_BITSET((reg), 2, 6, x)) -/* get value */ #define GX_XF_GET_MATRIXINDEX0_TEX3(reg) GX_BITGET((reg), 2, 6) -/* set value */ #define GX_XF_SET_MATRIXINDEX0_TEX3(reg, x) \ - ((reg) = GX_BITSET((reg), 2, 6, x)) /****************************************************************************** * XF register 0x1019 - MatrixIndex1 *****************************************************************************/ // TEX4 [26:31] (6) -/* start bit */ #define GX_XF_MATRIXINDEX1_TEX4_B 26 -/* end bit */ #define GX_XF_MATRIXINDEX1_TEX4_E 31 -/* bit size */ #define GX_XF_MATRIXINDEX1_TEX4_SZ 6 + /* start bit */ #define GX_XF_MATRIXINDEX1_TEX4_B 26 + /* end bit */ #define GX_XF_MATRIXINDEX1_TEX4_E 31 + /* bit size */ #define GX_XF_MATRIXINDEX1_TEX4_SZ 6 -/* raw mask */ #define GX_XF_MATRIXINDEX1_TEX4_MASK \ - (((1 << 6) - 1) << 31 - 31) -/* local mask */ #define GX_XF_MATRIXINDEX1_TEX4_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_XF_MATRIXINDEX1_TEX4_SHIFT 0 + /* raw mask */ #define GX_XF_MATRIXINDEX1_TEX4_MASK (((1 << 6) - 1) << 31 - 31) + /* local mask */ #define GX_XF_MATRIXINDEX1_TEX4_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_XF_MATRIXINDEX1_TEX4_SHIFT 0 -/* get value */ #define GX_XF_GET_MATRIXINDEX1_TEX4(reg) \ - GX_BITGET((reg), 26, 6) -/* set value */ #define GX_XF_SET_MATRIXINDEX1_TEX4(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 6, x)) + /* get value */ #define GX_XF_GET_MATRIXINDEX1_TEX4(reg) GX_BITGET((reg), 26, 6) + /* set value */ #define GX_XF_SET_MATRIXINDEX1_TEX4(reg, x) ((reg) = GX_BITSET((reg), 26, 6, x)) // TEX5 [20:25] (6) -/* start bit */ #define GX_XF_MATRIXINDEX1_TEX5_B 20 -/* end bit */ #define GX_XF_MATRIXINDEX1_TEX5_E 25 -/* bit size */ #define GX_XF_MATRIXINDEX1_TEX5_SZ 6 + /* start bit */ #define GX_XF_MATRIXINDEX1_TEX5_B 20 + /* end bit */ #define GX_XF_MATRIXINDEX1_TEX5_E 25 + /* bit size */ #define GX_XF_MATRIXINDEX1_TEX5_SZ 6 -/* raw mask */ #define GX_XF_MATRIXINDEX1_TEX5_MASK \ - (((1 << 6) - 1) << 31 - 25) -/* local mask */ #define GX_XF_MATRIXINDEX1_TEX5_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_XF_MATRIXINDEX1_TEX5_SHIFT 6 + /* raw mask */ #define GX_XF_MATRIXINDEX1_TEX5_MASK (((1 << 6) - 1) << 31 - 25) + /* local mask */ #define GX_XF_MATRIXINDEX1_TEX5_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_XF_MATRIXINDEX1_TEX5_SHIFT 6 -/* get value */ #define GX_XF_GET_MATRIXINDEX1_TEX5(reg) \ - GX_BITGET((reg), 20, 6) -/* set value */ #define GX_XF_SET_MATRIXINDEX1_TEX5(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 6, x)) + /* get value */ #define GX_XF_GET_MATRIXINDEX1_TEX5(reg) GX_BITGET((reg), 20, 6) + /* set value */ #define GX_XF_SET_MATRIXINDEX1_TEX5(reg, x) ((reg) = GX_BITSET((reg), 20, 6, x)) // TEX6 [14:19] (6) -/* start bit */ #define GX_XF_MATRIXINDEX1_TEX6_B 14 -/* end bit */ #define GX_XF_MATRIXINDEX1_TEX6_E 19 -/* bit size */ #define GX_XF_MATRIXINDEX1_TEX6_SZ 6 + /* start bit */ #define GX_XF_MATRIXINDEX1_TEX6_B 14 + /* end bit */ #define GX_XF_MATRIXINDEX1_TEX6_E 19 + /* bit size */ #define GX_XF_MATRIXINDEX1_TEX6_SZ 6 -/* raw mask */ #define GX_XF_MATRIXINDEX1_TEX6_MASK \ - (((1 << 6) - 1) << 31 - 19) -/* local mask */ #define GX_XF_MATRIXINDEX1_TEX6_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_XF_MATRIXINDEX1_TEX6_SHIFT 12 + /* raw mask */ #define GX_XF_MATRIXINDEX1_TEX6_MASK (((1 << 6) - 1) << 31 - 19) + /* local mask */ #define GX_XF_MATRIXINDEX1_TEX6_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_XF_MATRIXINDEX1_TEX6_SHIFT 12 -/* get value */ #define GX_XF_GET_MATRIXINDEX1_TEX6(reg) \ - GX_BITGET((reg), 14, 6) -/* set value */ #define GX_XF_SET_MATRIXINDEX1_TEX6(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 6, x)) + /* get value */ #define GX_XF_GET_MATRIXINDEX1_TEX6(reg) GX_BITGET((reg), 14, 6) + /* set value */ #define GX_XF_SET_MATRIXINDEX1_TEX6(reg, x) ((reg) = GX_BITSET((reg), 14, 6, x)) // TEX7 [8:13] (6) -/* start bit */ #define GX_XF_MATRIXINDEX1_TEX7_B 8 -/* end bit */ #define GX_XF_MATRIXINDEX1_TEX7_E 13 -/* bit size */ #define GX_XF_MATRIXINDEX1_TEX7_SZ 6 + /* start bit */ #define GX_XF_MATRIXINDEX1_TEX7_B 8 + /* end bit */ #define GX_XF_MATRIXINDEX1_TEX7_E 13 + /* bit size */ #define GX_XF_MATRIXINDEX1_TEX7_SZ 6 + + /* raw mask */ #define GX_XF_MATRIXINDEX1_TEX7_MASK (((1 << 6) - 1) << 31 - 13) + /* local mask */ #define GX_XF_MATRIXINDEX1_TEX7_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_XF_MATRIXINDEX1_TEX7_SHIFT 18 -/* raw mask */ #define GX_XF_MATRIXINDEX1_TEX7_MASK \ - (((1 << 6) - 1) << 31 - 13) -/* local mask */ #define GX_XF_MATRIXINDEX1_TEX7_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_XF_MATRIXINDEX1_TEX7_SHIFT 18 + /* get value */ #define GX_XF_GET_MATRIXINDEX1_TEX7(reg) GX_BITGET((reg), 8, 6) + /* set value */ #define GX_XF_SET_MATRIXINDEX1_TEX7(reg, x) ((reg) = GX_BITSET((reg), 8, 6, x)) -/* get value */ #define GX_XF_GET_MATRIXINDEX1_TEX7(reg) GX_BITGET((reg), 8, 6) -/* set value */ #define GX_XF_SET_MATRIXINDEX1_TEX7(reg, x) \ - ((reg) = GX_BITSET((reg), 8, 6, x)) /****************************************************************************** * XF structure - Tex *****************************************************************************/ // PROJTYPE [30:30] (1) -/* start bit */ #define GX_XF_TEX_PROJTYPE_B 30 -/* end bit */ #define GX_XF_TEX_PROJTYPE_E 30 -/* bit size */ #define GX_XF_TEX_PROJTYPE_SZ 1 + /* start bit */ #define GX_XF_TEX_PROJTYPE_B 30 + /* end bit */ #define GX_XF_TEX_PROJTYPE_E 30 + /* bit size */ #define GX_XF_TEX_PROJTYPE_SZ 1 -/* raw mask */ #define GX_XF_TEX_PROJTYPE_MASK (((1 << 1) - 1) << 31 - 30) -/* local mask */ #define GX_XF_TEX_PROJTYPE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_TEX_PROJTYPE_SHIFT 1 + /* raw mask */ #define GX_XF_TEX_PROJTYPE_MASK (((1 << 1) - 1) << 31 - 30) + /* local mask */ #define GX_XF_TEX_PROJTYPE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_TEX_PROJTYPE_SHIFT 1 -/* get value */ #define GX_XF_GET_TEX_PROJTYPE(reg) GX_BITGET((reg), 30, 1) -/* set value */ #define GX_XF_SET_TEX_PROJTYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 30, 1, x)) + /* get value */ #define GX_XF_GET_TEX_PROJTYPE(reg) GX_BITGET((reg), 30, 1) + /* set value */ #define GX_XF_SET_TEX_PROJTYPE(reg, x) ((reg) = GX_BITSET((reg), 30, 1, x)) // INPUTFORM [29:29] (1) -/* start bit */ #define GX_XF_TEX_INPUTFORM_B 29 -/* end bit */ #define GX_XF_TEX_INPUTFORM_E 29 -/* bit size */ #define GX_XF_TEX_INPUTFORM_SZ 1 + /* start bit */ #define GX_XF_TEX_INPUTFORM_B 29 + /* end bit */ #define GX_XF_TEX_INPUTFORM_E 29 + /* bit size */ #define GX_XF_TEX_INPUTFORM_SZ 1 -/* raw mask */ #define GX_XF_TEX_INPUTFORM_MASK (((1 << 1) - 1) << 31 - 29) -/* local mask */ #define GX_XF_TEX_INPUTFORM_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_TEX_INPUTFORM_SHIFT 2 + /* raw mask */ #define GX_XF_TEX_INPUTFORM_MASK (((1 << 1) - 1) << 31 - 29) + /* local mask */ #define GX_XF_TEX_INPUTFORM_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_TEX_INPUTFORM_SHIFT 2 -/* get value */ #define GX_XF_GET_TEX_INPUTFORM(reg) GX_BITGET((reg), 29, 1) -/* set value */ #define GX_XF_SET_TEX_INPUTFORM(reg, x) \ - ((reg) = GX_BITSET((reg), 29, 1, x)) + /* get value */ #define GX_XF_GET_TEX_INPUTFORM(reg) GX_BITGET((reg), 29, 1) + /* set value */ #define GX_XF_SET_TEX_INPUTFORM(reg, x) ((reg) = GX_BITSET((reg), 29, 1, x)) // TEXGENTYPE [25:27] (3) -/* start bit */ #define GX_XF_TEX_TEXGENTYPE_B 25 -/* end bit */ #define GX_XF_TEX_TEXGENTYPE_E 27 -/* bit size */ #define GX_XF_TEX_TEXGENTYPE_SZ 3 + /* start bit */ #define GX_XF_TEX_TEXGENTYPE_B 25 + /* end bit */ #define GX_XF_TEX_TEXGENTYPE_E 27 + /* bit size */ #define GX_XF_TEX_TEXGENTYPE_SZ 3 -/* raw mask */ #define GX_XF_TEX_TEXGENTYPE_MASK (((1 << 3) - 1) << 31 - 27) -/* local mask */ #define GX_XF_TEX_TEXGENTYPE_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_XF_TEX_TEXGENTYPE_SHIFT 4 + /* raw mask */ #define GX_XF_TEX_TEXGENTYPE_MASK (((1 << 3) - 1) << 31 - 27) + /* local mask */ #define GX_XF_TEX_TEXGENTYPE_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_XF_TEX_TEXGENTYPE_SHIFT 4 -/* get value */ #define GX_XF_GET_TEX_TEXGENTYPE(reg) GX_BITGET((reg), 25, 3) -/* set value */ #define GX_XF_SET_TEX_TEXGENTYPE(reg, x) \ - ((reg) = GX_BITSET((reg), 25, 3, x)) + /* get value */ #define GX_XF_GET_TEX_TEXGENTYPE(reg) GX_BITGET((reg), 25, 3) + /* set value */ #define GX_XF_SET_TEX_TEXGENTYPE(reg, x) ((reg) = GX_BITSET((reg), 25, 3, x)) // SRCROW [20:24] (5) -/* start bit */ #define GX_XF_TEX_SRCROW_B 20 -/* end bit */ #define GX_XF_TEX_SRCROW_E 24 -/* bit size */ #define GX_XF_TEX_SRCROW_SZ 5 + /* start bit */ #define GX_XF_TEX_SRCROW_B 20 + /* end bit */ #define GX_XF_TEX_SRCROW_E 24 + /* bit size */ #define GX_XF_TEX_SRCROW_SZ 5 -/* raw mask */ #define GX_XF_TEX_SRCROW_MASK (((1 << 5) - 1) << 31 - 24) -/* local mask */ #define GX_XF_TEX_SRCROW_LMASK ((1 << 5) - 1) -/* bit shift */ #define GX_XF_TEX_SRCROW_SHIFT 7 + /* raw mask */ #define GX_XF_TEX_SRCROW_MASK (((1 << 5) - 1) << 31 - 24) + /* local mask */ #define GX_XF_TEX_SRCROW_LMASK ((1 << 5) - 1) + /* bit shift */ #define GX_XF_TEX_SRCROW_SHIFT 7 -/* get value */ #define GX_XF_GET_TEX_SRCROW(reg) GX_BITGET((reg), 20, 5) -/* set value */ #define GX_XF_SET_TEX_SRCROW(reg, x) \ - ((reg) = GX_BITSET((reg), 20, 5, x)) + /* get value */ #define GX_XF_GET_TEX_SRCROW(reg) GX_BITGET((reg), 20, 5) + /* set value */ #define GX_XF_SET_TEX_SRCROW(reg, x) ((reg) = GX_BITSET((reg), 20, 5, x)) // BUMPSRCTEX [17:19] (3) -/* start bit */ #define GX_XF_TEX_BUMPSRCTEX_B 17 -/* end bit */ #define GX_XF_TEX_BUMPSRCTEX_E 19 -/* bit size */ #define GX_XF_TEX_BUMPSRCTEX_SZ 3 + /* start bit */ #define GX_XF_TEX_BUMPSRCTEX_B 17 + /* end bit */ #define GX_XF_TEX_BUMPSRCTEX_E 19 + /* bit size */ #define GX_XF_TEX_BUMPSRCTEX_SZ 3 -/* raw mask */ #define GX_XF_TEX_BUMPSRCTEX_MASK (((1 << 3) - 1) << 31 - 19) -/* local mask */ #define GX_XF_TEX_BUMPSRCTEX_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_XF_TEX_BUMPSRCTEX_SHIFT 12 + /* raw mask */ #define GX_XF_TEX_BUMPSRCTEX_MASK (((1 << 3) - 1) << 31 - 19) + /* local mask */ #define GX_XF_TEX_BUMPSRCTEX_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_XF_TEX_BUMPSRCTEX_SHIFT 12 -/* get value */ #define GX_XF_GET_TEX_BUMPSRCTEX(reg) GX_BITGET((reg), 17, 3) -/* set value */ #define GX_XF_SET_TEX_BUMPSRCTEX(reg, x) \ - ((reg) = GX_BITSET((reg), 17, 3, x)) + /* get value */ #define GX_XF_GET_TEX_BUMPSRCTEX(reg) GX_BITGET((reg), 17, 3) + /* set value */ #define GX_XF_SET_TEX_BUMPSRCTEX(reg, x) ((reg) = GX_BITSET((reg), 17, 3, x)) // BUMPSRCLIGHT [14:16] (3) -/* start bit */ #define GX_XF_TEX_BUMPSRCLIGHT_B 14 -/* end bit */ #define GX_XF_TEX_BUMPSRCLIGHT_E 16 -/* bit size */ #define GX_XF_TEX_BUMPSRCLIGHT_SZ 3 + /* start bit */ #define GX_XF_TEX_BUMPSRCLIGHT_B 14 + /* end bit */ #define GX_XF_TEX_BUMPSRCLIGHT_E 16 + /* bit size */ #define GX_XF_TEX_BUMPSRCLIGHT_SZ 3 + + /* raw mask */ #define GX_XF_TEX_BUMPSRCLIGHT_MASK (((1 << 3) - 1) << 31 - 16) + /* local mask */ #define GX_XF_TEX_BUMPSRCLIGHT_LMASK ((1 << 3) - 1) + /* bit shift */ #define GX_XF_TEX_BUMPSRCLIGHT_SHIFT 15 -/* raw mask */ #define GX_XF_TEX_BUMPSRCLIGHT_MASK (((1 << 3) - 1) << 31 - 16) -/* local mask */ #define GX_XF_TEX_BUMPSRCLIGHT_LMASK ((1 << 3) - 1) -/* bit shift */ #define GX_XF_TEX_BUMPSRCLIGHT_SHIFT 15 + /* get value */ #define GX_XF_GET_TEX_BUMPSRCLIGHT(reg) GX_BITGET((reg), 14, 3) + /* set value */ #define GX_XF_SET_TEX_BUMPSRCLIGHT(reg, x) ((reg) = GX_BITSET((reg), 14, 3, x)) -/* get value */ #define GX_XF_GET_TEX_BUMPSRCLIGHT(reg) GX_BITGET((reg), 14, 3) -/* set value */ #define GX_XF_SET_TEX_BUMPSRCLIGHT(reg, x) \ - ((reg) = GX_BITSET((reg), 14, 3, x)) /****************************************************************************** * XF structure - DualTex *****************************************************************************/ // BASEROW [26:31] (6) - Indicates which is the base row of the transform matrix -/* start bit */ #define GX_XF_DUALTEX_BASEROW_B 26 -/* end bit */ #define GX_XF_DUALTEX_BASEROW_E 31 -/* bit size */ #define GX_XF_DUALTEX_BASEROW_SZ 6 + /* start bit */ #define GX_XF_DUALTEX_BASEROW_B 26 + /* end bit */ #define GX_XF_DUALTEX_BASEROW_E 31 + /* bit size */ #define GX_XF_DUALTEX_BASEROW_SZ 6 -/* raw mask */ #define GX_XF_DUALTEX_BASEROW_MASK (((1 << 6) - 1) << 31 - 31) -/* local mask */ #define GX_XF_DUALTEX_BASEROW_LMASK ((1 << 6) - 1) -/* bit shift */ #define GX_XF_DUALTEX_BASEROW_SHIFT 0 + /* raw mask */ #define GX_XF_DUALTEX_BASEROW_MASK (((1 << 6) - 1) << 31 - 31) + /* local mask */ #define GX_XF_DUALTEX_BASEROW_LMASK ((1 << 6) - 1) + /* bit shift */ #define GX_XF_DUALTEX_BASEROW_SHIFT 0 -/* get value */ #define GX_XF_GET_DUALTEX_BASEROW(reg) GX_BITGET((reg), 26, 6) -/* set value */ #define GX_XF_SET_DUALTEX_BASEROW(reg, x) \ - ((reg) = GX_BITSET((reg), 26, 6, x)) + /* get value */ #define GX_XF_GET_DUALTEX_BASEROW(reg) GX_BITGET((reg), 26, 6) + /* set value */ #define GX_XF_SET_DUALTEX_BASEROW(reg, x) ((reg) = GX_BITSET((reg), 26, 6, x)) // NORMALIZE [23:23] (1) - Normalize texcoord before sending transform -/* start bit */ #define GX_XF_DUALTEX_NORMALIZE_B 23 -/* end bit */ #define GX_XF_DUALTEX_NORMALIZE_E 23 -/* bit size */ #define GX_XF_DUALTEX_NORMALIZE_SZ 1 + /* start bit */ #define GX_XF_DUALTEX_NORMALIZE_B 23 + /* end bit */ #define GX_XF_DUALTEX_NORMALIZE_E 23 + /* bit size */ #define GX_XF_DUALTEX_NORMALIZE_SZ 1 + + /* raw mask */ #define GX_XF_DUALTEX_NORMALIZE_MASK (((1 << 1) - 1) << 31 - 23) + /* local mask */ #define GX_XF_DUALTEX_NORMALIZE_LMASK ((1 << 1) - 1) + /* bit shift */ #define GX_XF_DUALTEX_NORMALIZE_SHIFT 8 + + /* get value */ #define GX_XF_GET_DUALTEX_NORMALIZE(reg) GX_BITGET((reg), 23, 1) + /* set value */ #define GX_XF_SET_DUALTEX_NORMALIZE(reg, x) ((reg) = GX_BITSET((reg), 23, 1, x)) -/* raw mask */ #define GX_XF_DUALTEX_NORMALIZE_MASK \ - (((1 << 1) - 1) << 31 - 23) -/* local mask */ #define GX_XF_DUALTEX_NORMALIZE_LMASK ((1 << 1) - 1) -/* bit shift */ #define GX_XF_DUALTEX_NORMALIZE_SHIFT 8 -/* get value */ #define GX_XF_GET_DUALTEX_NORMALIZE(reg) \ - GX_BITGET((reg), 23, 1) -/* set value */ #define GX_XF_SET_DUALTEX_NORMALIZE(reg, x) \ - ((reg) = GX_BITSET((reg), 23, 1, x)) #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/revolution/GX/GXMisc.h b/include/revolution/GX/GXMisc.h index 410003b..d505d37 100644 --- a/include/revolution/GX/GXMisc.h +++ b/include/revolution/GX/GXMisc.h @@ -6,6 +6,7 @@ extern "C" { #endif typedef void (*GXDrawDoneCallback)(void); +typedef void (*GXDrawSyncCallback)(u16 token); void GXSetMisc(UNKWORD token, UNKWORD val); void GXFlush(void); @@ -13,9 +14,12 @@ void GXResetWriteGatherPipe(void); void GXAbortFrame(void); +void GXSetDrawSync(u16 token); + void GXDrawDone(void); void GXPixModeSync(void); +GXDrawSyncCallback GXSetDrawSyncCallback(GXDrawSyncCallback); GXDrawDoneCallback GXSetDrawDoneCallback(GXDrawDoneCallback); #ifdef __cplusplus diff --git a/include/revolution/GX/GXTransform.h b/include/revolution/GX/GXTransform.h index 6b3661a..3eea75f 100644 --- a/include/revolution/GX/GXTransform.h +++ b/include/revolution/GX/GXTransform.h @@ -17,6 +17,10 @@ typedef enum { GX_FIELD_ODD, } GXInterlaceField; +#if defined(LIBKIWI_PRECOMPILE) +#define static inline +#endif + void GXSetProjection(const Mtx44 proj, GXProjectionType type); void GXSetProjectionv(const f32 proj[GX_PROJECTION_SZ]); void GXGetProjectionv(f32 proj[GX_PROJECTION_SZ]); @@ -44,6 +48,10 @@ static void GXSetViewportv(const f32 view[GX_VIEWPORT_SZ]) { GXSetViewport(view[0], view[1], view[2], view[3], view[4], view[5]); } +#if defined(LIBKIWI_PRECOMPILE) +#undef static +#endif + #ifdef __cplusplus } #endif diff --git a/include/revolution/GX/GXTypes.h b/include/revolution/GX/GXTypes.h index d31bcf7..75b59d1 100644 --- a/include/revolution/GX/GXTypes.h +++ b/include/revolution/GX/GXTypes.h @@ -689,9 +689,9 @@ typedef enum _GXTevKColorSel { typedef enum _GXTevMode { GX_MODULATE, GX_DECAL, + GX_BLEND, GX_REPLACE, - GX_PASSCLR, - GX_BLEND + GX_PASSCLR } GXTevMode; typedef enum _GXTexCoordID { @@ -909,7 +909,7 @@ typedef enum _GXZFmt16 { typedef enum _GXZTexOp { GX_ZT_DISABLE, GX_ZT_ADD, - GZ_ZT_REPLACE, + GX_ZT_REPLACE, GX_MAX_ZTEXOP } GXZTexOp; diff --git a/include/revolution/IPC.h b/include/revolution/IPC.h index 637360b..bbe5e22 100644 --- a/include/revolution/IPC.h +++ b/include/revolution/IPC.h @@ -1,5 +1,5 @@ /** - * References: WiiBrew, Dolphin Emulator + * References: WiiBrew, Dolphin Emulator, fail0verflow */ #ifndef RVL_SDK_PUBLIC_IPC_H diff --git a/include/revolution/IPC/ipcHardware.h b/include/revolution/IPC/ipcHardware.h new file mode 100644 index 0000000..7eee7d2 --- /dev/null +++ b/include/revolution/IPC/ipcHardware.h @@ -0,0 +1,108 @@ +#ifndef RVL_SDK_IPC_HARDWARE_H +#define RVL_SDK_IPC_HARDWARE_H +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + * IPC hardware registers + */ +volatile u32 IPC_HW_REGS_PPC[] : 0xCD000000; +volatile u32 IPC_HW_REGS[] : 0xCD800000; + +/** + * Hardware register indexes + */ +// clang-format off +#define LIST_OF_REGS \ + X(IPC_PPCMSG, 0xCD000000) \ + X(IPC_PPCCTRL, 0xCD000004) \ + X(IPC_ARMMSG, 0xCD000008) \ + X(IPC_ARMCTRL, 0xCD00000C) \ + X(TIMER, 0xCD000010) \ + X(ALARM, 0xCD000014) \ + X(PPCIRQFLAG, 0xCD000030) \ + X(PPCIRQMASK, 0xCD000034) \ + X(ARMIRQFLAG, 0xCD000038) \ + X(ARMIRQMASK, 0xCD00003C) \ + X(MEMMIRR, 0xCD000060) \ + X(AHBPROT, 0xCD000064) \ + X(EXICTRL, 0xCD000070) \ + X(GPIO1BOUT, 0xCD0000C0) \ + X(GPIO1BDIR, 0xCD0000C4) \ + X(GPIO1BIN, 0xCD0000C8) \ + X(GPIO1BINTLVL, 0xCD0000CC) \ + X(GPIO1BINTFLAG, 0xCD0000D0) \ + X(GPIO1BINTENABLE, 0xCD0000D4) \ + X(GPIO1BINMIR, 0xCD0000D8) \ + X(GPIO1ENABLE, 0xCD0000DC) \ + X(GPIO1OUT, 0xCD0000E0) \ + X(GPIO1DIR, 0xCD0000E4) \ + X(GPIO1IN, 0xCD0000E8) \ + X(GPIO1INTLVL, 0xCD0000EC) \ + X(GPIO1INTFLAG, 0xCD0000F0) \ + X(GPIO1INTENABLE, 0xCD0000F4) \ + X(GPIO1INMIR, 0xCD0000F8) \ + X(GPIO1OWNER, 0xCD0000FC) \ + X(DIFLAGS, 0xCD000180) \ + X(RESETS, 0xCD000194) \ + X(CLOCKS, 0xCD0001B4) \ + X(GPIO2OUT, 0xCD0001C8) \ + X(GPIO2DIR, 0xCD0001CC) \ + X(GPIO2IN, 0xCD0001D0) \ + X(OTPCMD, 0xCD0001EC) \ + X(OTPDATA, 0xCD0001F0) \ + X(VERSION, 0xCD000214) +// clang-format on + +/** + * Hardware register indexes (IPC) + */ +#define X(NAME, ADDR) IPC_##NAME = (ADDR - 0xCD000000) / 4, +typedef enum { LIST_OF_REGS } IPCHwReg; +#undef X + +/** + * Hardware register indexes (ACR) + */ +#define X(NAME, ADDR) ACR_##NAME = (ADDR - 0xCD000000), +typedef enum { LIST_OF_REGS } ACRHwReg; +#undef X + +/** + * GPIO register flags + */ +typedef enum { + GPIO_POWER = (1 << 0), + GPIO_SHUTDOWN = (1 << 1), + GPIO_FAN = (1 << 2), + GPIO_DCDC = (1 << 3), + GPIO_DISPIN = (1 << 4), + GPIO_SLOTLED = (1 << 5), + GPIO_EJECTBTN = (1 << 6), + GPIO_SLOTIN = (1 << 7), + GPIO_SENSORBAR = (1 << 8), + GPIO_DOEJECT = (1 << 9), + GPIO_EEP_CS = (1 << 10), + GPIO_EEP_CLK = (1 << 11), + GPIO_EEP_MOSI = (1 << 12), + GPIO_EEP_MISO = (1 << 13), + GPIO_AVE_SCL = (1 << 14), + GPIO_AVE_SDA = (1 << 15), + GPIO_DEBUG0 = (1 << 16), + GPIO_DEBUG1 = (1 << 17), + GPIO_DEBUG2 = (1 << 18), + GPIO_DEBUG3 = (1 << 19), + GPIO_DEBUG4 = (1 << 20), + GPIO_DEBUG5 = (1 << 21), + GPIO_DEBUG6 = (1 << 22), + GPIO_DEBUG7 = (1 << 23), +} GPIOFlag; + +#undef LIST_OF_REGS + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/revolution/IPC/ipcMain.h b/include/revolution/IPC/ipcMain.h index 204d95c..5ac462d 100644 --- a/include/revolution/IPC/ipcMain.h +++ b/include/revolution/IPC/ipcMain.h @@ -1,18 +1,18 @@ #ifndef RVL_SDK_IPC_MAIN_H #define RVL_SDK_IPC_MAIN_H #include + +#include #ifdef __cplusplus extern "C" { #endif -u32 IPC_HW_REGS[] : 0xCD000000; - inline u32 ACRReadReg(u32 reg) { - return IPC_HW_REGS[reg / 4]; + return IPC_HW_REGS_PPC[reg / 4]; } inline void ACRWriteReg(u32 reg, u32 val) { - IPC_HW_REGS[reg / 4] = val; + IPC_HW_REGS_PPC[reg / 4] = val; } void IPCInit(void); diff --git a/include/revolution/IPC/ipcProfile.h b/include/revolution/IPC/ipcProfile.h index 9b9acc6..95f2bf0 100644 --- a/include/revolution/IPC/ipcProfile.h +++ b/include/revolution/IPC/ipcProfile.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_IPC_PROFILE_H #define RVL_SDK_IPC_PROFILE_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/IPC/ipcclt.h b/include/revolution/IPC/ipcclt.h index 37defa1..f73e916 100644 --- a/include/revolution/IPC/ipcclt.h +++ b/include/revolution/IPC/ipcclt.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_IPC_CLT_H #define RVL_SDK_IPC_CLT_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/KPAD.h b/include/revolution/KPAD.h index 1d6e175..3734752 100644 --- a/include/revolution/KPAD.h +++ b/include/revolution/KPAD.h @@ -4,16 +4,8 @@ extern "C" { #endif -//! @addtogroup rvl_kpad -//! @{ - -//! @file -//! @brief Includes all header files of the KPAD library - #include -//! @} - #ifdef __cplusplus } #endif diff --git a/include/revolution/KPAD/KPAD.h b/include/revolution/KPAD/KPAD.h index f960926..928c6f9 100644 --- a/include/revolution/KPAD/KPAD.h +++ b/include/revolution/KPAD/KPAD.h @@ -1,14 +1,13 @@ #ifndef RVL_SDK_KPAD_H #define RVL_SDK_KPAD_H -#ifdef __cplusplus #include #include +#ifdef __cplusplus extern "C" { #endif -//! @addtogroup rvl_kpad -//! @{ +#define KPAD_MAX_SAMPLES 16 typedef enum { KPAD_RESULT_OK = 0, @@ -40,20 +39,15 @@ typedef enum { KPAD_BTN_HOME = (1 << 15), } KPADButton; -typedef struct Vec2 { - f32 x, y; -} Vec2; - -typedef union KPADExStatus { +typedef union KPADEXStatus { // Wii Remote ("free style") struct { Vec2 stick; // at 0x0 Vec acc; // at 0x8 f32 acc_value; // at 0x14 f32 acc_speed; // at 0x18 - } fs; + } fs; // at 0x0 - // Classic Controller struct { u32 hold; // at 0x0 u32 trig; // at 0x4 @@ -62,17 +56,8 @@ typedef union KPADExStatus { Vec2 rstick; // at 0x14 f32 ltrigger; // at 0x1C f32 rtrigger; // at 0x20 - } cl; - - // Balance Board - struct { - f64 tgc_weight; // at 0x0 - f64 weight[4]; // at 0x8 - f64 weight_ave[4]; // at 0x28 - s32 weight_err; // at 0x48 - s32 tgc_weight_err; // at 0x4C - } bl; -} KPADExStatus; + } cl; // at 0x0 +} KPADEXStatus; typedef struct KPADStatus { u32 hold; // at 0x0 @@ -95,12 +80,19 @@ typedef struct KPADStatus { s8 wpad_err; // at 0x5D s8 dpd_valid_fg; // at 0x5E u8 data_format; // at 0x5F - KPADExStatus ex_status; // at 0x60 + KPADEXStatus ex_status; // at 0x60 } KPADStatus; -s32 KPADRead(s32 chan, KPADStatus* status, u32 num); +void KPADSetBtnRepeat(s32 chan, f32, f32); + +void KPADSetPosParam(s32 chan, f32 playRadius, f32 sensitivity); +void KPADSetHoriParam(s32 chan, f32 playRadius, f32 sensitivity); +void KPADSetDistParam(s32 chan, f32 playRadius, f32 sensitivity); +void KPADSetAccParam(s32 chan, f32 playRadius, f32 sensitivity); + +s32 KPADRead(s32 chan, KPADStatus* pSamples, s32 numSamples); -//! @} +void KPADInit(void); #ifdef __cplusplus } diff --git a/include/revolution/MEM/mem_expHeap.h b/include/revolution/MEM/mem_expHeap.h index 62f3749..01a4658 100644 --- a/include/revolution/MEM/mem_expHeap.h +++ b/include/revolution/MEM/mem_expHeap.h @@ -52,6 +52,10 @@ typedef struct MEMiExpHeapHead { }; // at 0x12 } MEMiExpHeapHead; +#if defined(LIBKIWI_PRECOMPILE) +#define static inline +#endif + MEMiHeapHead* MEMCreateExpHeapEx(void* start, u32 size, u16 opt); MEMiHeapHead* MEMDestroyExpHeap(MEMiHeapHead* heap); void* MEMAllocFromExpHeapEx(MEMiHeapHead* heap, u32 size, s32 align); @@ -72,6 +76,10 @@ static u32 MEMGetAllocatableSizeForExpHeap(MEMiHeapHead* heap) { return MEMGetAllocatableSizeForExpHeapEx(heap, 4); } +#if defined(LIBKIWI_PRECOMPILE) +#undef static +#endif + #ifdef __cplusplus } #endif diff --git a/include/revolution/MEM/mem_frameHeap.h b/include/revolution/MEM/mem_frameHeap.h index 9cb5a43..32102e0 100644 --- a/include/revolution/MEM/mem_frameHeap.h +++ b/include/revolution/MEM/mem_frameHeap.h @@ -32,6 +32,10 @@ typedef struct MEMiFrmHeapHead { MEMiFrmHeapState* states; // at 0x8 } MEMiFrmHeapHead; +#if defined(LIBKIWI_PRECOMPILE) +#define static inline +#endif + MEMiHeapHead* MEMCreateFrmHeapEx(void* start, u32 size, u16 opt); MEMiHeapHead* MEMDestroyFrmHeap(MEMiHeapHead* heap); void* MEMAllocFromFrmHeapEx(MEMiHeapHead* heap, u32 size, s32 align); @@ -54,6 +58,10 @@ static u32 MEMGetAllocatableSizeForFrmHeap(MEMiHeapHead* heap) { return MEMGetAllocatableSizeForFrmHeapEx(heap, 4); } +#if defined(LIBKIWI_PRECOMPILE) +#undef static +#endif + #ifdef __cplusplus } #endif diff --git a/include/revolution/MEM/mem_heapCommon.h b/include/revolution/MEM/mem_heapCommon.h index 8d69648..ebd8179 100644 --- a/include/revolution/MEM/mem_heapCommon.h +++ b/include/revolution/MEM/mem_heapCommon.h @@ -34,6 +34,10 @@ typedef struct MEMiHeapHead { }; // at 0x38 } MEMiHeapHead; +#if defined(LIBKIWI_PRECOMPILE) +#define static inline +#endif + void MEMiInitHeapHead(MEMiHeapHead* heap, u32 magic, void* start, void* end, u16 opt); void MEMiFinalizeHeap(MEMiHeapHead* heap); @@ -89,10 +93,18 @@ static void FillAllocMemory(MEMiHeapHead* heap, void* memBlock, u32 size) { } } -static s32 MEMGetHeapTotalSize(MEMiHeapHead* heap) { +static s32 MEMGetHeapTotalSize(const MEMiHeapHead* heap) { return GetOffsetFromPtr(heap, heap->end); } +static void* MEMGetHeapEndAddress(const MEMiHeapHead* heap) { + return heap->end; +} + +#if defined(LIBKIWI_PRECOMPILE) +#undef static +#endif + #ifdef __cplusplus } #endif diff --git a/include/revolution/MTX/mtxtypes.h b/include/revolution/MTX/mtxtypes.h index e8ff668..6188ca4 100644 --- a/include/revolution/MTX/mtxtypes.h +++ b/include/revolution/MTX/mtxtypes.h @@ -12,6 +12,10 @@ typedef struct Vec { f32 x, y, z; } Vec; +typedef struct Vec2 { + f32 x, y; +} Vec2; + typedef struct Quaternion { f32 x, y, z, w; } Quaternion; diff --git a/include/revolution/NAND/NANDCheck.h b/include/revolution/NAND/NANDCheck.h index f507f12..400b60f 100644 --- a/include/revolution/NAND/NANDCheck.h +++ b/include/revolution/NAND/NANDCheck.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_NAND_CHECK_H #define RVL_SDK_NAND_CHECK_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NAND/NANDOpenClose.h b/include/revolution/NAND/NANDOpenClose.h index a7d874d..cdbd43b 100644 --- a/include/revolution/NAND/NANDOpenClose.h +++ b/include/revolution/NAND/NANDOpenClose.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_NAND_OPEN_CLOSE_H #define RVL_SDK_NAND_OPEN_CLOSE_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24Config.h b/include/revolution/NWC24/NWC24Config.h index b59ae74..eaf845f 100644 --- a/include/revolution/NWC24/NWC24Config.h +++ b/include/revolution/NWC24/NWC24Config.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_NWC24_CONFIG_H #define RVL_SDK_NWC24_CONFIG_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24DateParser.h b/include/revolution/NWC24/NWC24DateParser.h index 8bdfc69..26af9d1 100644 --- a/include/revolution/NWC24/NWC24DateParser.h +++ b/include/revolution/NWC24/NWC24DateParser.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_NWC24_DATE_PARSER_H #define RVL_SDK_NWC24_DATE_PARSER_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24Download.h b/include/revolution/NWC24/NWC24Download.h index 3e6abd9..4f1e842 100644 --- a/include/revolution/NWC24/NWC24Download.h +++ b/include/revolution/NWC24/NWC24Download.h @@ -1,10 +1,8 @@ #ifndef RVL_SDK_NWC24_DOWNLOAD_H #define RVL_SDK_NWC24_DOWNLOAD_H -#include - -#include - #include +#include +#include #ifdef __cplusplus extern "C" { #endif @@ -95,8 +93,8 @@ NWC24Err NWC24GetDlTask(NWC24DlTask* task, u16 i); NWC24Err NWC24iOpenDlTaskList(void); NWC24Err NWC24iCloseDlTaskList(void); NWC24DlHeader* NWC24iGetCachedDlHeader(void); -NWC24Err NWC24iCheckHeaderConsistency(NWC24DlHeader* header, BOOL clear) - DECOMP_DONT_INLINE; +NWC24Err NWC24iCheckHeaderConsistency(NWC24DlHeader* header, + BOOL clear) DECOMP_DONT_INLINE; NWC24Err NWC24iLoadDlHeader(void); #ifdef __cplusplus diff --git a/include/revolution/NWC24/NWC24FileApi.h b/include/revolution/NWC24/NWC24FileApi.h index 9215406..82c9e96 100644 --- a/include/revolution/NWC24/NWC24FileApi.h +++ b/include/revolution/NWC24/NWC24FileApi.h @@ -1,11 +1,9 @@ #ifndef RVL_SDK_NWC24_FILE_API_H #define RVL_SDK_NWC24_FILE_API_H -#include - -#include - #include +#include #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24FriendList.h b/include/revolution/NWC24/NWC24FriendList.h index 121ac99..345c799 100644 --- a/include/revolution/NWC24/NWC24FriendList.h +++ b/include/revolution/NWC24/NWC24FriendList.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_NWC24_FRIEND_LIST_H #define RVL_SDK_NWC24_FRIEND_LIST_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24MBoxCtrl.h b/include/revolution/NWC24/NWC24MBoxCtrl.h index f226a15..f8c65d0 100644 --- a/include/revolution/NWC24/NWC24MBoxCtrl.h +++ b/include/revolution/NWC24/NWC24MBoxCtrl.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_NWC24_MBOX_CTRL_H #define RVL_SDK_NWC24_MBOX_CTRL_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24Manage.h b/include/revolution/NWC24/NWC24Manage.h index 74c0865..06693ef 100644 --- a/include/revolution/NWC24/NWC24Manage.h +++ b/include/revolution/NWC24/NWC24Manage.h @@ -1,12 +1,11 @@ #ifndef RVL_SDK_NWC24_MANAGE_H #define RVL_SDK_NWC24_MANAGE_H -#include - #include #include #include #include #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24Parser.h b/include/revolution/NWC24/NWC24Parser.h index 2f742eb..2b9e0e3 100644 --- a/include/revolution/NWC24/NWC24Parser.h +++ b/include/revolution/NWC24/NWC24Parser.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_NWC24_PARSER_H #define RVL_SDK_NWC24_PARSER_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24Schedule.h b/include/revolution/NWC24/NWC24Schedule.h index 3951362..e06716e 100644 --- a/include/revolution/NWC24/NWC24Schedule.h +++ b/include/revolution/NWC24/NWC24Schedule.h @@ -1,9 +1,8 @@ #ifndef RVL_SDK_NWC24_SCHEDULE_H #define RVL_SDK_NWC24_SCHEDULE_H -#include - #include #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24SecretFList.h b/include/revolution/NWC24/NWC24SecretFList.h index 7b9773e..9cffe8b 100644 --- a/include/revolution/NWC24/NWC24SecretFList.h +++ b/include/revolution/NWC24/NWC24SecretFList.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_NWC24_SECRET_FRIEND_LIST_H #define RVL_SDK_NWC24_SECRET_FRIEND_LIST_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24System.h b/include/revolution/NWC24/NWC24System.h index 179dbb0..0b53abe 100644 --- a/include/revolution/NWC24/NWC24System.h +++ b/include/revolution/NWC24/NWC24System.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_NWC24_SYSTEM_H #define RVL_SDK_NWC24_SYSTEM_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NWC24/NWC24Time.h b/include/revolution/NWC24/NWC24Time.h index f741812..6f380d8 100644 --- a/include/revolution/NWC24/NWC24Time.h +++ b/include/revolution/NWC24/NWC24Time.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_NWC24_TIME_H #define RVL_SDK_NWC24_TIME_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/NdevExi2AD/DebuggerDriver.h b/include/revolution/NdevExi2AD/DebuggerDriver.h index 0685a34..c9f3bd5 100644 --- a/include/revolution/NdevExi2AD/DebuggerDriver.h +++ b/include/revolution/NdevExi2AD/DebuggerDriver.h @@ -1,10 +1,8 @@ #ifndef RVL_SDK_NDEV_EXI2_AD_DEBUGGER_DRIVER_H #define RVL_SDK_NDEV_EXI2_AD_DEBUGGER_DRIVER_H -#include - #include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/OS/OS.h b/include/revolution/OS/OS.h index 64f313a..aa54084 100644 --- a/include/revolution/OS/OS.h +++ b/include/revolution/OS/OS.h @@ -1,9 +1,8 @@ #ifndef RVL_SDK_OS_H #define RVL_SDK_OS_H -#include - #include #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/OS/OSError.h b/include/revolution/OS/OSError.h index 6b1cb4b..8e54eff 100644 --- a/include/revolution/OS/OSError.h +++ b/include/revolution/OS/OSError.h @@ -8,7 +8,7 @@ extern "C" { // Forward declarations typedef struct OSContext OSContext; -#define OSError(...) OSPanic(__FILE__, __LINE__, __VA_ARGS__) +#define OS_ERROR(...) OSPanic(__FILE__, __LINE__, __VA_ARGS__) #define OS_ASSERT(exp, ...) \ if (!(exp)) \ diff --git a/include/revolution/OS/OSFastCast.h b/include/revolution/OS/OSFastCast.h index 643d71b..0201c9e 100644 --- a/include/revolution/OS/OSFastCast.h +++ b/include/revolution/OS/OSFastCast.h @@ -10,6 +10,10 @@ extern "C" { #define OS_GQR_TYPE_S8 6 #define OS_GQR_TYPE_S16 7 +#if defined(LIBKIWI_PRECOMPILE) +#define static inline +#endif + static void OSInitFastCast(void) { // clang-format off asm { @@ -177,6 +181,10 @@ static void OSf32tos16(f32* in, volatile s16* out) { *out = __OSf32tos16(*in); } +#if defined(LIBKIWI_PRECOMPILE) +#undef static +#endif + #ifdef __cplusplus } #endif diff --git a/include/revolution/OS/OSFatal.h b/include/revolution/OS/OSFatal.h index 6ffb7cb..e1c6a6f 100644 --- a/include/revolution/OS/OSFatal.h +++ b/include/revolution/OS/OSFatal.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_OS_FATAL_H #define RVL_SDK_OS_FATAL_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/OS/OSHardware.h b/include/revolution/OS/OSHardware.h index 58d1b77..986c720 100644 --- a/include/revolution/OS/OSHardware.h +++ b/include/revolution/OS/OSHardware.h @@ -153,6 +153,7 @@ OS_DEF_GLOBAL_VAR(u32, NAND_TITLE_LAUNCH_CODE, 0x8000318C); OS_DEF_GLOBAL_VAR(u32, NAND_TITLE_RETURN_CODE, 0x80003190); OS_DEF_GLOBAL_VAR(u32, BOOT_PARTITION_TYPE, 0x80003194); OS_DEF_GLOBAL_VAR(u32, BOOT_PARTITION_OFFSET, 0x80003198); +OS_DEF_GLOBAL_VAR(s8, WIFI_AFH_CHANNEL, 0x800031A2); OS_DEF_GLOBAL_ARR(u8, NWC24_USER_ID_BUFFER, [32], 0x800031C0); OS_DEF_GLOBAL_VAR(u64, NWC24_USER_ID, 0x800031C0); OS_DEF_GLOBAL_ARR(u8, SC_PRDINFO, [0x100], 0x80003800); @@ -255,22 +256,13 @@ typedef enum { #define MI_INTSR_ADDR (1 << 4) /** - * DI hardware globals + * DI hardware registers */ -// clang-format off -OS_DEF_HW_REG(volatile u32, DI_DMA_ADDR, 0xCD006014); -OS_DEF_HW_REG(volatile u32, DI_CONFIG, 0xCD006024); -// clang-format on - -/** - * Misc/unknown globals - */ -// clang-format off -OS_DEF_HW_REG(volatile u32, UNK_CD000034, 0xCD000034); -OS_DEF_HW_REG(volatile u32, UNK_CD800180, 0xCD800180); -OS_DEF_HW_REG(volatile u32, UNK_CD8001CC, 0xCD8001CC); -OS_DEF_HW_REG(volatile u32, UNK_CD8001D0, 0xCD8001D0); -// clang-format on +volatile u32 DI_HW_REGS[] : 0xCD006000; +typedef enum { + DI_DMA_ADDR = 5, // !< 0xCD006014 + DI_CONFIG = 9, // !< 0xCD006024 +} DIHwReg; #ifdef __cplusplus } diff --git a/include/revolution/OS/OSMemory.h b/include/revolution/OS/OSMemory.h index 9663985..4252bbe 100644 --- a/include/revolution/OS/OSMemory.h +++ b/include/revolution/OS/OSMemory.h @@ -5,6 +5,7 @@ extern "C" { #endif +#define OS_MEM_KB_TO_B(mb) ((mb) * 1024) #define OS_MEM_B_TO_KB(mb) ((mb) / 1024) #define OS_MEM_B_TO_MB(mb) ((mb) / 1024 / 1024) @@ -15,6 +16,9 @@ extern "C" { #define OSIsMEM1Region(addr) (((u32)(addr) & 0x30000000) == 0) #define OSIsMEM2Region(addr) (((u32)(addr) & 0x30000000) == 0x10000000) +#define OS_IS_MEM1_REGION(addr) OSIsMEM1Region(addr) +#define OS_IS_MEM2_REGION(addr) OSIsMEM2Region(addr) + u32 OSGetPhysicalMem1Size(void); u32 OSGetPhysicalMem2Size(void); u32 OSGetConsoleSimulatedMem1Size(void); diff --git a/include/revolution/OS/OSMessage.h b/include/revolution/OS/OSMessage.h index c39bc20..b4318fa 100644 --- a/include/revolution/OS/OSMessage.h +++ b/include/revolution/OS/OSMessage.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_OS_MESSAGE_H #define RVL_SDK_OS_MESSAGE_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/OS/OSMutex.h b/include/revolution/OS/OSMutex.h index 28d13b6..2651adb 100644 --- a/include/revolution/OS/OSMutex.h +++ b/include/revolution/OS/OSMutex.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_OS_MUTEX_H #define RVL_SDK_OS_MUTEX_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/OS/OSReset.h b/include/revolution/OS/OSReset.h index 6186dbc..1ae25dd 100644 --- a/include/revolution/OS/OSReset.h +++ b/include/revolution/OS/OSReset.h @@ -8,10 +8,13 @@ extern "C" { typedef BOOL (*OSShutdownFunction)(BOOL final, u32 event); typedef enum { - OS_SD_EVENT_SHUTDOWN = 2, - OS_SD_EVENT_RESTART = 4, - OS_SD_EVENT_RETURN_TO_MENU = 5, - OS_SD_EVENT_LAUNCH_APP = 6, + OS_SD_EVENT_FATAL, + OS_SD_EVENT_1, + OS_SD_EVENT_SHUTDOWN, + OS_SD_EVENT_3, + OS_SD_EVENT_RESTART, + OS_SD_EVENT_RETURN_TO_MENU, + OS_SD_EVENT_LAUNCH_APP, } OSShutdownEvent; typedef struct OSShutdownFunctionInfo { diff --git a/include/revolution/OS/OSThread.h b/include/revolution/OS/OSThread.h index 3a51f68..413fad0 100644 --- a/include/revolution/OS/OSThread.h +++ b/include/revolution/OS/OSThread.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_OS_THREAD_H #define RVL_SDK_OS_THREAD_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/OS/OSTime.h b/include/revolution/OS/OSTime.h index 2ae0923..e91ab02 100644 --- a/include/revolution/OS/OSTime.h +++ b/include/revolution/OS/OSTime.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_OS_TIME_H #define RVL_SDK_OS_TIME_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/SC/scapi.h b/include/revolution/SC/scapi.h index 9d41f8f..c648ef1 100644 --- a/include/revolution/SC/scapi.h +++ b/include/revolution/SC/scapi.h @@ -3,11 +3,14 @@ #include #include -#include #ifdef __cplusplus extern "C" { #endif +#define SC_MAX_DEV_ENTRY_FOR_STD 10 +#define SC_MAX_DEV_ENTRY_FOR_SMP 6 +#define SC_MAX_DEV_ENTRY (SC_MAX_DEV_ENTRY_FOR_STD + SC_MAX_DEV_ENTRY_FOR_SMP) + typedef enum { SC_ASPECT_STD, SC_ASPECT_WIDE } SCAspectRatio; typedef enum { SC_EURGB_50_HZ, SC_EURGB_60_HZ } SCEuRgb60Mode; @@ -25,6 +28,10 @@ typedef enum { SC_LANG_KR, } SCLanguage; +typedef enum { SC_INTERLACED, SC_PROGRESSIVE } SCProgressiveMode; + +typedef enum { SC_MOTOR_OFF, SC_MOTOR_ON } SCMotorMode; + typedef enum { SC_SND_MONO, SC_SND_STEREO, SC_SND_SURROUND } SCSoundMode; typedef enum { SC_SENSOR_BAR_BOTTOM, SC_SENSOR_BAR_TOP } SCSensorBarPos; @@ -34,21 +41,28 @@ typedef struct SCIdleModeInfo { u8 slotLight; // at 0x1 } SCIdleModeInfo; +typedef struct SCDevInfo { + char devName[20]; // at 0x0 + char at_0x14[1]; + char UNK_0x15[0xB]; + LINK_KEY linkKey; // at 0x20 + char UNK_0x30[0x10]; +} SCDevInfo; + typedef struct SCBtDeviceInfo { - BD_ADDR addr; // at 0x0 - WUDSmallDevInfo info; // at 0x6 + BD_ADDR addr; // at 0x0 + SCDevInfo info; // at 0x6 } SCBtDeviceInfo; typedef struct SCBtDeviceInfoArray { u8 numRegist; // at 0x0 union { struct { - SCBtDeviceInfo regist[WUD_MAX_DEV_ENTRY_FOR_STD]; // at 0x1 - SCBtDeviceInfo active[WUD_MAX_DEV_ENTRY_FOR_SMP]; // at 0x2BD + SCBtDeviceInfo regist[SC_MAX_DEV_ENTRY_FOR_STD]; // at 0x1 + SCBtDeviceInfo active[SC_MAX_DEV_ENTRY_FOR_SMP]; // at 0x2BD }; - SCBtDeviceInfo - devices[WUD_MAX_DEV_ENTRY_FOR_STD + WUD_MAX_DEV_ENTRY_FOR_SMP]; + SCBtDeviceInfo devices[SC_MAX_DEV_ENTRY]; }; } SCBtDeviceInfoArray; @@ -65,10 +79,10 @@ void SCGetBtDeviceInfoArray(SCBtDeviceInfoArray* info); BOOL SCSetBtDeviceInfoArray(const SCBtDeviceInfoArray* info); u32 SCGetBtDpdSensibility(void); u8 SCGetWpadMotorMode(void); -void SCSetWpadMotorMode(u8 mode); +BOOL SCSetWpadMotorMode(u8 mode); u8 SCGetWpadSensorBarPosition(void); u8 SCGetWpadSpeakerVolume(void); -void SCSetWpadSpeakerVolume(u8 vol); +BOOL SCSetWpadSpeakerVolume(u8 vol); #ifdef __cplusplus } diff --git a/include/revolution/USB/usb.h b/include/revolution/USB/usb.h index fed82f6..e502eaa 100644 --- a/include/revolution/USB/usb.h +++ b/include/revolution/USB/usb.h @@ -1,8 +1,7 @@ #ifndef RVL_SDK_USB_H #define RVL_SDK_USB_H -#include - #include +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/revolution/VI/vi.h b/include/revolution/VI/vi.h index fc17fd1..9569678 100644 --- a/include/revolution/VI/vi.h +++ b/include/revolution/VI/vi.h @@ -7,35 +7,55 @@ extern "C" { #endif -// Merge format/mode to one value for TV info (see GXRenderModeObj) -#define VI_TV_INFO(format, mode) (((format) << 2) + (mode)) -// Get TV format from TV info -#define VI_TV_INFO_FMT(info) ((info) >> 2) -// Get TV scan mode from TV info -#define VI_TV_INFO_MODE(info) ((info) & 0b00000011) +// Merge format/scanmode to one value for TV mode (see GXRenderModeObj) +#define VI_TVMODE(format, scanMode) (((format) << 2) + (scanMode)) + +// Get TV format from TV mode +#define VI_TVMODE_FORMAT(mode) ((mode) >> 2) +// Get TV scan mode from TV mode +#define VI_TVMODE_SCANMODE(mode) ((mode) & 0b00000011) typedef enum { - VI_TV_FMT_NTSC, - VI_TV_FMT_PAL, - VI_TV_FMT_MPAL, - VI_TV_FMT_DEBUG, - VI_TV_FMT_DEBUG_PAL, - VI_TV_FMT_EURGB60, - VI_TV_FMT_6, - VI_TV_FMT_7, - VI_TV_FMT_8, -} VITvFormat; + VI_TVFORMAT_NTSC, + VI_TVFORMAT_PAL, + VI_TVFORMAT_MPAL, + VI_TVFORMAT_DEBUG, + VI_TVFORMAT_DEBUG_PAL, + VI_TVFORMAT_EURGB60 +} VITVFormat; typedef enum VIScanMode { - VI_SCAN_MODE_INT, - VI_SCAN_MODE_DS, - VI_SCAN_MODE_PROG + VI_SCANMODE_INT, + VI_SCANMODE_DS, + VI_SCANMODE_PROG } VIScanMode; -typedef enum VIXfbMode { - VI_XFB_MODE_SF, - VI_XFB_MODE_DF, -} VIXfbMode; +typedef enum VIXFBMode { + VI_XFBMODE_SF, + VI_XFBMODE_DF, +} VIXFBMode; + +typedef enum VITVMode { + VI_TVMODE_NTSC_INT = VI_TVMODE(VI_TVFORMAT_NTSC, VI_SCANMODE_INT), + VI_TVMODE_NTSC_DS = VI_TVMODE(VI_TVFORMAT_NTSC, VI_SCANMODE_DS), + VI_TVMODE_NTSC_PROG = VI_TVMODE(VI_TVFORMAT_NTSC, VI_SCANMODE_PROG), + + VI_TVMODE_PAL_INT = VI_TVMODE(VI_TVFORMAT_PAL, VI_SCANMODE_INT), + VI_TVMODE_PAL_DS = VI_TVMODE(VI_TVFORMAT_PAL, VI_SCANMODE_DS), + + VI_TVMODE_EURGB60_INT = VI_TVMODE(VI_TVFORMAT_EURGB60, VI_SCANMODE_INT), + VI_TVMODE_EURGB60_DS = VI_TVMODE(VI_TVFORMAT_EURGB60, VI_SCANMODE_DS), + VI_TVMODE_EURGB60_PROG = VI_TVMODE(VI_TVFORMAT_EURGB60, VI_SCANMODE_PROG), + + VI_TVMODE_MPAL_INT = VI_TVMODE(VI_TVFORMAT_MPAL, VI_SCANMODE_INT), + VI_TVMODE_MPAL_DS = VI_TVMODE(VI_TVFORMAT_MPAL, VI_SCANMODE_DS), + VI_TVMODE_MPAL_PROG = VI_TVMODE(VI_TVFORMAT_MPAL, VI_SCANMODE_PROG), + + VI_TVMODE_DEBUG_INT = VI_TVMODE(VI_TVFORMAT_DEBUG, VI_SCANMODE_INT), + + VI_TVMODE_DEBUG_PAL_INT = VI_TVMODE(VI_TVFORMAT_DEBUG_PAL, VI_SCANMODE_INT), + VI_TVMODE_DEBUG_PAL_DS = VI_TVMODE(VI_TVFORMAT_DEBUG_PAL, VI_SCANMODE_DS), +} VITVMode; typedef void (*VIRetraceCallback)(u32 retraceCount); typedef void (*VIPositionCallback)(s16 displayX, s16 displayY); @@ -56,8 +76,9 @@ void* VIGetCurrentFrameBuffer(void); void VISetBlack(BOOL black); s32 VIGetRetraceCount(void); -VITvFormat VIGetTvFormat(void); +VITVFormat VIGetTvFormat(void); VIScanMode VIGetScanMode(void); +u32 VIGetDTVStatus(void); #ifdef __cplusplus } diff --git a/include/revolution/VI/vihardware.h b/include/revolution/VI/vihardware.h index 5886281..0c8ef01 100644 --- a/include/revolution/VI/vihardware.h +++ b/include/revolution/VI/vihardware.h @@ -93,6 +93,9 @@ typedef enum { #define VI_VICLK_SPEED (1 << 0) typedef enum { VI_VICLK_27MHZ, VI_VICLK_54MHZ } VIClkSpeed; +// VISEL - VI DTV Status Register +#define VI_VISEL_COMPONENT (1 << 0) + // HBE - Border HBE #define VI_HBE_BRDR_EN (1 << 15) diff --git a/include/revolution/WPAD.h b/include/revolution/WPAD.h index 408e4a9..d472737 100644 --- a/include/revolution/WPAD.h +++ b/include/revolution/WPAD.h @@ -1,3 +1,7 @@ +/** + * References: WiiBrew + */ + #ifndef RVL_SDK_PUBLIC_WPAD_H #define RVL_SDK_PUBLIC_WPAD_H #ifdef __cplusplus @@ -5,6 +9,8 @@ extern "C" { #endif #include +#include +#include #ifdef __cplusplus } diff --git a/include/revolution/WPAD/WPAD.h b/include/revolution/WPAD/WPAD.h index 51848a9..a22298a 100644 --- a/include/revolution/WPAD/WPAD.h +++ b/include/revolution/WPAD/WPAD.h @@ -1,48 +1,339 @@ #ifndef RVL_SDK_WPAD_H #define RVL_SDK_WPAD_H #include + +#include +#include #ifdef __cplusplus extern "C" { #endif #define WPAD_ADDR_LEN 6 +#define WPAD_MAX_DPD_OBJECTS 4 + +#define WPAD_MIN_DPD_SENS 1 +#define WPAD_MAX_DPD_SENS 5 + +#define WPAD_MAX_DPD_X 1023 +#define WPAD_MAX_DPD_Y 767 + +#define WPAD_MAX_SPEAKER_VOLUME 127 + +extern u8 _scFlush; + +typedef WUDAllocFunc WPADAllocFunc; +typedef WUDFreeFunc WPADFreeFunc; typedef void (*WPADCallback)(s32 chan, s32 result); +typedef void (*WPADSamplingCallback)(s32 chan); +typedef void (*WPADConnectCallback)(s32 chan, s32 result); +typedef void (*WPADExtensionCallback)(s32 chan, s32 dev); + +typedef WUDSyncDeviceCallback WPADSyncDeviceCallback; +typedef WUDClearDeviceCallback WPADClearDeviceCallback; +typedef SCFlushCallback WPADSaveCallback; typedef enum { - WPAD_CHAN_0, - WPAD_CHAN_1, - WPAD_CHAN_2, - WPAD_CHAN_3, - WPAD_MAX_CONTROLLERS -} WPADChan; + WPAD_LIB_STATUS_0 = WUD_LIB_STATUS_0, + WPAD_LIB_STATUS_1 = WUD_LIB_STATUS_1, + WPAD_LIB_STATUS_2 = WUD_LIB_STATUS_2, + WPAD_LIB_STATUS_3 = WUD_LIB_STATUS_3, + WPAD_LIB_STATUS_4 = WUD_LIB_STATUS_4, +} WPADLibStatus; typedef enum { + WPAD_ERR_OK = 0, + WPAD_ERR_NO_CONTROLLER = -1, + WPAD_ERR_COMMUNICATION_ERROR = -2, + WPAD_ERR_TRANSFER = -3, + WPAD_ERR_INVALID = -4, WPAD_ERR_CORRUPTED = -7, - WPAD_ERR_6, - WPAD_ERR_5, - WPAD_ERR_INVALID, - WPAD_ERR_TRANSFER, - WPAD_ERR_BUSY, - WPAD_ERR_NO_CONTROLLER, - WPAD_ERR_OK = 0, + WPAD_ERR_BUSY = WPAD_ERR_COMMUNICATION_ERROR, } WPADResult; +typedef enum { + WPAD_CHAN0, + WPAD_CHAN1, + WPAD_CHAN2, + WPAD_CHAN3, + + WPAD_MAX_CONTROLLERS, + WPAD_CHAN_INVALID = -1 +} WPADChannel; + +typedef enum { + // Wii Remote (Core) + WPAD_BUTTON_LEFT = (1 << 0), + WPAD_BUTTON_RIGHT = (1 << 1), + WPAD_BUTTON_DOWN = (1 << 2), + WPAD_BUTTON_UP = (1 << 3), + + WPAD_BUTTON_A = (1 << 11), + WPAD_BUTTON_B = (1 << 10), + WPAD_BUTTON_1 = (1 << 9), + WPAD_BUTTON_2 = (1 << 8), + + WPAD_BUTTON_PLUS = (1 << 4), + WPAD_BUTTON_MINUS = (1 << 12), + WPAD_BUTTON_HOME = (1 << 15), + + // Nunchuk (Free Style) + WPAD_BUTTON_FS_Z = (1 << 13), + WPAD_BUTTON_FS_C = (1 << 14), + + // Classic Controller + WPAD_BUTTON_CL_LEFT = (1 << 1), + WPAD_BUTTON_CL_RIGHT = (1 << 15), + WPAD_BUTTON_CL_DOWN = (1 << 14), + WPAD_BUTTON_CL_UP = (1 << 0), + + WPAD_BUTTON_CL_A = (1 << 4), + WPAD_BUTTON_CL_B = (1 << 6), + WPAD_BUTTON_CL_X = (1 << 3), + WPAD_BUTTON_CL_Y = (1 << 5), + WPAD_BUTTON_CL_ZL = (1 << 7), + WPAD_BUTTON_CL_ZR = (1 << 2), + + WPAD_BUTTON_CL_L = (1 << 13), + WPAD_BUTTON_CL_R = (1 << 9), + + WPAD_BUTTON_CL_PLUS = (1 << 10), + WPAD_BUTTON_CL_MINUS = (1 << 12), + WPAD_BUTTON_CL_HOME = (1 << 11), +} WPADButton; + +typedef enum { + WPAD_DEV_CORE, + WPAD_DEV_FREESTYLE, + WPAD_DEV_CLASSIC, + + WPAD_DEV_FUTURE = 251, + WPAD_DEV_NOT_SUPPORTED = 252, + WPAD_DEV_NOT_FOUND = 253, + WPAD_DEV_NULL = 254, + WPAD_DEV_UNKNOWN = 255, +} WPADDeviceType; + +typedef enum { + WPAD_FMT_CORE_BTN, + WPAD_FMT_CORE_BTN_ACC, + WPAD_FMT_CORE_BTN_ACC_DPD, + + WPAD_FMT_FS_BTN, + WPAD_FMT_FS_BTN_ACC, + WPAD_FMT_FS_BTN_ACC_DPD, + + WPAD_FMT_CLASSIC_BTN, + WPAD_FMT_CLASSIC_BTN_ACC, + WPAD_FMT_CLASSIC_BTN_ACC_DPD, + + WPAD_FMT_BTN_ACC_DPD_EXTENDED, +} WPADDataFormat; + +typedef enum { + WPAD_DEV_MODE_NORMAL, + WPAD_DEV_MODE_CLASSIC_REDUCED, + WPAD_DEV_MODE_CLASSIC_EXTENDED, + WPAD_DEV_MODE_CLASSIC_STANDARD, +} WPADDeviceMode; + +typedef enum { + WPAD_MOTOR_STOP, + WPAD_MOTOR_RUMBLE, +} WPADMotorCommand; + typedef enum { WPAD_SPEAKER_OFF, WPAD_SPEAKER_ON, - - WPAD_SPEAKER_PLAY = 4, + WPAD_SPEAKER_MUTE, + WPAD_SPEAKER_UNMUTE, + WPAD_SPEAKER_PLAY, + WPAD_SPEAKER_5 } WPADSpeakerCommand; -s32 WPADControlSpeaker(s32, UNKWORD, WPADCallback); -BOOL WPADCanSendStreamData(s32); -s32 WPADSendStreamData(s32, UNKTYPE*, UNKWORD); +typedef enum { + WPAD_DPD_DISABLE = 0x00, + WPAD_DPD_BASIC = 0x01, + WPAD_DPD_STANDARD = 0x03, + WPAD_DPD_EXTENDED = 0x05, +} WPADDpdCommand; + +typedef enum { + WPAD_SENSOR_BAR_BOTTOM = SC_SENSOR_BAR_BOTTOM, + WPAD_SENSOR_BAR_TOP = SC_SENSOR_BAR_TOP +} WPADSensorBarPos; + +typedef enum { + WPAD_MOTOR_OFF = SC_MOTOR_OFF, + WPAD_MOTOR_ON = SC_MOTOR_ON +} WPADMotorMode; + +typedef enum { + WPAD_ACC_GRAVITY_UNIT_CORE, + WPAD_ACC_GRAVITY_UNIT_FS, +} WPADAccGravityUnitType; + +typedef struct DPDObject { + s16 x; // at 0x0 + s16 y; // at 0x2 + u16 size; // at 0x4 + u8 traceId; // at 0x6 +} DPDObject; + +typedef struct DPDObjEx { + s16 range_x1; // at 0x0 + s16 range_y1; // at 0x2 + s16 range_x2; // at 0x4 + s16 range_y2; // at 0x6 + u16 pixel; // at 0x8 + s8 radius; // at 0xA +} DPDObjEx; + +typedef struct WPADInfo { + BOOL dpd; // at 0x0 + BOOL speaker; // at 0x4 + BOOL attach; // at 0x8 + BOOL lowBat; // at 0xC + BOOL nearempty; // at 0x10 + u8 battery; // at 0x14 + u8 led; // at 0x15 + u8 protocol; // at 0x16 + u8 firmware; // at 0x17 +} WPADInfo; + +typedef struct WPADStatus { + u16 button; // at 0x0 + s16 accX; // at 0x2 + s16 accY; // at 0x4 + s16 accZ; // at 0x6 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // at 0x8 + u8 dev; // at 0x28 + s8 err; // at 0x29 +} WPADStatus; + +typedef struct WPADStatusEx { + u16 button; // at 0x0 + s16 accX; // at 0x2 + s16 accY; // at 0x4 + s16 accZ; // at 0x6 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // at 0x8 + u8 dev; // at 0x28 + s8 err; // at 0x29 + + DPDObjEx exp[WPAD_MAX_DPD_OBJECTS]; // at 0x2A +} WPADStatusEx; + +typedef struct WPADFSStatus { + u16 button; // at 0x0 + s16 accX; // at 0x2 + s16 accY; // at 0x4 + s16 accZ; // at 0x6 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // at 0x8 + u8 dev; // at 0x28 + s8 err; // at 0x29 + + s16 fsAccX; // at 0x2A + s16 fsAccY; // at 0x2C + s16 fsAccZ; // at 0x2E + s8 fsStickX; // at 0x30 + s8 fsStickY; // at 0x31 +} WPADFSStatus; + +typedef struct WPADCLStatus { + u16 button; // at 0x0 + s16 accX; // at 0x2 + s16 accY; // at 0x4 + s16 accZ; // at 0x6 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // at 0x8 + u8 dev; // at 0x28 + s8 err; // at 0x29 + + u16 clButton; // at 0x2A + s16 clLStickX; // at 0x2C + s16 clLStickY; // at 0x2E + s16 clRStickX; // at 0x30 + s16 clRStickY; // at 0x32 + u8 clTriggerL; // at 0x34 + u8 clTriggerR; // at 0x35 +} WPADCLStatus; + +typedef struct WPADAccGravityUnit { + s16 x; // at 0x0 + s16 y; // at 0x2 + s16 z; // at 0x4 +} WPADAccGravityUnit; + +void WPADInit(void); +void WPADShutdown(void); + +BOOL WPADStartSimpleSync(void); +BOOL WPADStartFastSimpleSync(void); +BOOL WPADStopSimpleSync(void); +BOOL WPADStartClearDevice(void); + +WPADSyncDeviceCallback +WPADSetSimpleSyncCallback(WPADSyncDeviceCallback pCallback); + +WPADClearDeviceCallback +WPADSetClearDeviceCallback(WPADClearDeviceCallback pCallback); + +void WPADRegisterAllocator(WPADAllocFunc pAllocFunc, WPADFreeFunc pFreeFunc); +u32 WPADGetWorkMemorySize(void); + +WPADLibStatus WPADGetStatus(void); +void WPADGetAddress(s32 chan, BD_ADDR_PTR pAddr); +u8 WPADGetSensorBarPosition(void); + +void WPADGetAccGravityUnit(s32 chan, u32 type, WPADAccGravityUnit* pAcc); + +void WPADDisconnect(s32 chan); +s32 WPADProbe(s32 chan, s32* pDevType); + +WPADSamplingCallback WPADSetSamplingCallback(s32 chan, + WPADSamplingCallback pCallback); +WPADConnectCallback WPADSetConnectCallback(s32 chan, + WPADConnectCallback pCallback); +WPADExtensionCallback WPADSetExtensionCallback(s32 chan, + WPADExtensionCallback pCallback); + +u32 WPADGetDataFormat(s32 chan); +s32 WPADSetDataFormat(s32 chan, u32 format); + +s32 WPADGetInfoAsync(s32 chan, WPADInfo* pInfo, WPADCallback pCallback); + +void WPADControlMotor(s32 chan, u32 command); +void WPADEnableMotor(BOOL enable); +BOOL WPADIsMotorEnabled(void); + +s32 WPADControlLed(s32 chan, u8 flags, WPADCallback pCallback); + +BOOL WPADSaveConfig(WPADSaveCallback pCallback); + +void WPADRead(s32 chan, WPADStatus* pStatus); +void WPADSetAutoSamplingBuf(s32 chan, void* pBuffer, u32 len); + +BOOL WPADIsSpeakerEnabled(s32 chan); +s32 WPADControlSpeaker(s32 chan, u32 command, WPADCallback pCallback); +u8 WPADGetSpeakerVolume(void); +void WPADSetSpeakerVolume(u8 volume); + +BOOL WPADCanSendStreamData(s32 chan); +s32 WPADSendStreamData(s32 chan, void* pData, u16 len); + +u8 WPADGetDpdSensitivity(void); +BOOL WPADSetSensorBarPower(BOOL enable); +BOOL WPADIsDpdEnabled(s32 chan); +s32 WPADControlDpd(s32 chan, u32 command, WPADCallback pCallback); + +void WPADRecalibrate(s32 chan); + +//! ///////////////////////////////// -s32 WPADProbe(s32 chan, u32* type); s32 WPADReadFaceData(s32 chan, void* dst, u32 size, u32 src, WPADCallback cb); +//! ///////////////////////////////// + #ifdef __cplusplus } #endif diff --git a/include/revolution/WPAD/WPADHIDParser.h b/include/revolution/WPAD/WPADHIDParser.h new file mode 100644 index 0000000..2106331 --- /dev/null +++ b/include/revolution/WPAD/WPADHIDParser.h @@ -0,0 +1,211 @@ +#ifndef RVL_SDK_WPAD_HID_PARSER_H +#define RVL_SDK_WPAD_HID_PARSER_H +#include +#ifdef __cplusplus +extern "C" { +#endif + +#define RPT_REPORT_ID 0 +#define RPT_MAX_SIZE 21 + +// Limits +#define RPTID_OUT_LO RPTID_SET_RUMBLE +#define RPTID_OUT_HI RPTID_SET_DPD_CSB + +#define RPTID_IN_LO RPTID_STATUS +#define RPTID_IN_HI RPTID_DATA_BTN_ACC_DPD18_2 + +// All outgoing reports +#define RPT_OUT_FLAGS 1 + +#define RPT_OUT_FLAG_ENABLE_FEATURE 2 +#define RPT_OUT_FLAG_REQUEST_ACK_RPT 1 +#define RPT_OUT_FLAG_RUMBLE 0 + +// All incoming reports with Button data (all except 0x3d) +#define RPT_BTN0 1 +#define RPT_BTN1 2 + +// All incoming reports with Accelerometer (Standard) data (0x31, 0x33, 0x35, +// 0x37) +#define RPT_ACC_OFFSET 1 +#define RPT_ACC_SIZE 3 + +/** + * + * Outgoing reports (from POV of the host) + * + */ +// Report 0x10: Set rumble status +#define RPTID_SET_RUMBLE 0x10 +#define RPT10_SIZE 1 + +#define RPT10_RUMBLE 0 + +// Report 0x11: Set LED lights +#define RPTID_SET_PORT 0x11 // internally called SetPort +#define RPT11_SIZE 1 + +#define RPT11_LED 0 + +// Report 0x12: Set data reporting mode +#define RPTID_SET_DATA_REPORT_MODE 0x12 +#define RPT12_SIZE 2 + +#define RPT12_CONT_REPORT 0 +#define RPT12_DATA_REPORT_MODE 1 + +// Report 0x13: Enable IR camera +#define RPTID_ENABLE_DPD 0x13 // internally called the DPD +#define RPT13_SIZE 1 + +#define RPT13_DPD_ENABLE 0 + +// Report 0x14: Enable IR camera +#define RPTID_ENABLE_SPEAKER 0x14 +#define RPT14_SIZE 1 + +#define RPT14_SPEAKER_ENABLE 0 + +// Report 0x15: Request status report +#define RPTID_REQUEST_STATUS 0x15 +#define RPT15_SIZE 1 + +// Report 0x16: Write data +#define RPTID_WRITE_DATA 0x16 +#define RPT16_SIZE RPT_MAX_SIZE + +#define RPT16_DATA_DST_ADDRESS 0 +#define RPT16_DATA_LENGTH 4 +#define RPT16_DATA 5 + +// Report 0x17: Read data +#define RPTID_READ_DATA 0x17 +#define RPT17_SIZE 6 + +#define RPT17_DATA_SRC_ADDRESS 0 +#define RPT17_DATA_LENGTH 4 + +// Report 0x18: Send speaker data +#define RPTID_SEND_SPEAKER_DATA 0x18 +#define RPT18_SIZE RPT_MAX_SIZE + +#define RPT18_DATA_LENGTH 0 +#define RPT18_DATA 1 + +// Report 0x19: Mute speaker +#define RPTID_MUTE_SPEAKER 0x19 +#define RPT19_SIZE 1 + +#define RPT19_SPEAKER_MUTE 0 + +// Report 0x1A: WPADiSendDPDCSB (?) +#define RPTID_SEND_DPD_CSB 0x1A +#define RPT1A_SIZE 1 + +#define RPT1A_DPD_CSB 0 + +/** + * + * Incoming reports (from POV of the host) + * + */ +// Report 0x20: Status report +#define RPTID_STATUS 0x20 +#define RPT20_FLAGS 3 +#define RPT20_PROTO_FW 5 +#define RPT20_BATTERY 6 + +// Report 0x21: Read Wiimote data +#define RPTID_DATA_READ 0x21 +#define RPT21_SIZE_ERR 3 +#define RPT21_ADDR0 4 +#define RPT21_ADDR1 5 +#define RPT21_DATA 6 + +// Report 0x22: Acknowledgement and request result +#define RPTID_ACK 0x22 +#define RPT22_ACKED_RPT_ID 3 +#define RPT22_ERR_CODE 4 + +// Reports 0x23-0x2F: Unused + +// Report 0x30: Buttons +#define RPTID_DATA_BTN 0x30 + +// Report 0x31: Buttons, Accelerometer (Standard) +#define RPTID_DATA_BTN_ACC 0x31 + +// Report 0x32: Buttons, Extension (8 bytes) +#define RPTID_DATA_BTN_EXT8 0x32 +#define RPT32_EXT_OFFSET 3 +#define RPT32_EXT_LENGTH 8 + +/** + * Report 0x33: Buttons, Accelerometer (Standard), IR Camera (Standard, 12 + * bytes) + */ +#define RPTID_DATA_BTN_ACC_DPD12 0x33 +#define RPT33_DPD_OFFSET 6 +#define RPT33_DPD_LENGTH 12 + +// Report 0x34: Buttons, Extension (19 bytes) +#define RPTID_DATA_BTN_EXT19 0x34 +#define RPT34_EXT_OFFSET 3 +#define RPT34_EXT_LENGTH 19 + +// Report 0x35: Buttons, Accelerometer (Standard), Extension (16 bytes) +#define RPTID_DATA_BTN_ACC_EXT16 0x35 +#define RPT35_EXT_OFFSET 6 +#define RPT35_EXT_LENGTH 16 + +// Report 0x36: Buttons, IR Camera (Basic, 10 bytes), Extension (9 bytes) +#define RPTID_DATA_BTN_DPD10_EXT9 0x36 +#define RPT36_DPD_OFFSET 3 +#define RPT36_DPD_LENGTH 10 +#define RPT36_EXT_OFFSET 13 +#define RPT36_EXT_LENGTH 9 + +/** + * Report 0x37: Buttons, Accelerometer (Standard), IR Camera (Basic, 10 bytes), + * Extension (6 bytes) + */ +#define RPTID_DATA_BTN_ACC_DPD10_EXT9 0x37 +#define RPT37_DPD_OFFSET 6 +#define RPT37_DPD_LENGTH 10 +#define RPT37_EXT_OFFSET 16 +#define RPT37_EXT_LENGTH 6 + +// Report 0x38-0x3C: Unused + +// Report 0x3D: Extension (21 bytes) +#define RPTID_DATA_EXT21 0x3D +#define RPT3D_EXT_OFFSET 1 +#define RPT3D_EXT_LENGTH 21 + +/** + * Report 0x3E: Buttons, Accelerometer (Interleaved 1), IR Camera (Full 1, 18 + * bytes) + */ +#define RPTID_DATA_BTN_ACC_DPD18_1 0x3E +#define RPT3E_DPD0 0 +#define RPT3E_DPD0_OFFSET 4 +#define RPT3E_DPD1 1 +#define RPT3E_DPD1_OFFSET 13 + +/** + * Report 0x3F: Buttons, Accelerometer (Interleaved 2), IR Camera (Full 2, 18 + * bytes) + */ +#define RPTID_DATA_BTN_ACC_DPD18_2 0x3F +#define RPT3F_DPD2 2 +#define RPT3F_DPD2_OFFSET 4 +#define RPT3F_DPD3 3 +#define RPT3F_DPD3_OFFSET 13 + +s32 WPADiHIDParser(u8 port, u8* p_rpt); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/revolution/WPAD/WPADInternal.h b/include/revolution/WPAD/WPADInternal.h new file mode 100644 index 0000000..8813940 --- /dev/null +++ b/include/revolution/WPAD/WPADInternal.h @@ -0,0 +1,290 @@ +#ifndef RVL_SDK_WPAD_INTERNAL_H +#define RVL_SDK_WPAD_INTERNAL_H +#include + +// Public API +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +#define RX_BUFFER_SIZE ROUND_UP(sizeof(WPADStatusEx), 32) + +#define WPAD_CONFIG_BLOCK_CHECKSUM_BIAS 0x55 +#define WPAD_MAX_CONFIG_BLOCKS 2 + +#define WPAD_DPD_CONFIG_BLOCK_CHECKSUM 10 +#define WPAD_DPD_CONFIG_BLOCK_SIZE 11 + +#define WPAD_DEV_CONFIG_BLOCK_CHECKSUM 9 +#define WPAD_DEV_CONFIG_BLOCK_SIZE 10 + +#define DPD_CFG_OBJ_BL 0 +#define DPD_CFG_OBJ_BR 1 +#define DPD_CFG_OBJ_TR 2 +#define DPD_CFG_OBJ_TL 3 + +/* + * Wiimote memory addresses + */ +// clang-format off +#define WM_ADDR_MEM_DEV_CONFIG_0 WM_MEM_ADDR(0x0000) +#define WM_ADDR_MEM_GAME_INFO_0 WM_MEM_ADDR(0x002A) +#define WM_ADDR_MEM_GAME_INFO_1 WM_MEM_ADDR(0x0062) +#define WM_ADDR_MEM_176C WM_MEM_ADDR(0x176C) +#define WM_ADDR_MEM_1770 WM_MEM_ADDR(0x1770) +// clang-format on + +/* + * Wiimote extension register addresses + */ +// clang-format off +// Speaker register addresses +#define WM_REG_SPEAKER_01 WM_EXT_REG_ADDR(SPEAKER, 0x01) +#define WM_REG_SPEAKER_08 WM_EXT_REG_ADDR(SPEAKER, 0x08) +#define WM_REG_SPEAKER_09 WM_EXT_REG_ADDR(SPEAKER, 0x09) + +// Extension register addresses +#define WM_REG_EXTENSION_CONFIG WM_EXT_REG_ADDR(EXTENSION, 0x20) +#define WM_REG_EXTENSION_40 WM_EXT_REG_ADDR(EXTENSION, 0x40) +#define WM_REG_EXTENSION_CERT_PARAM WM_EXT_REG_ADDR(EXTENSION, 0x50) +#define WM_REG_EXTENSION_F0 WM_EXT_REG_ADDR(EXTENSION, 0xF0) +#define WM_REG_EXTENSION_CERT_CHALLENGE WM_EXT_REG_ADDR(EXTENSION, 0xF1) +#define WM_REG_EXTENSION_F2 WM_EXT_REG_ADDR(EXTENSION, 0xF2) +#define WM_REG_EXTENSION_F3 WM_EXT_REG_ADDR(EXTENSION, 0xF3) +#define WM_REG_EXTENSION_EXT_TYPE_2 WM_EXT_REG_ADDR(EXTENSION, 0xF6) +#define WM_REG_EXTENSION_CERT_PROBE WM_EXT_REG_ADDR(EXTENSION, 0xF7) +#define WM_REG_EXTENSION_FA WM_EXT_REG_ADDR(EXTENSION, 0xFA) +#define WM_REG_EXTENSION_FB WM_EXT_REG_ADDR(EXTENSION, 0xFB) +#define WM_REG_EXTENSION_DEV_MODE WM_EXT_REG_ADDR(EXTENSION, 0xFE) +#define WM_REG_EXTENSION_ID_BYTE WM_EXT_REG_ADDR(EXTENSION, 0xFF) + +// IR camera register addresses +#define WM_REG_DPD_CONFIG_BLOCK_1 WM_EXT_REG_ADDR(DPD, 0x00) +#define WM_REG_DPD_CONFIG_BLOCK_2 WM_EXT_REG_ADDR(DPD, 0x1A) +#define WM_REG_DPD_30 WM_EXT_REG_ADDR(DPD, 0x30) +#define WM_REG_DPD_DATA_FORMAT WM_EXT_REG_ADDR(DPD, 0x33) +// clang-format on + +#define WM_EXTENSION_CONFIG_SIZE 0x20 // 0xA40020 - 0xA4003F + +typedef enum { + WPAD_STATE_EXT_UNINITIALIZED, + WPAD_STATE_EXT_INITIALIZED, + WPAD_STATE_EXT_ENCRYPTED, + WPAD_STATE_EXT_ENCRYPTED_3RD, +} WPADExtensionState; + +typedef enum { + WPAD_RADIO_QUALITY_GOOD, // 80+ + WPAD_RADIO_QUALITY_BAD // 80- + // if radioQuality calculation == 80, state stays the same +} WPADRadioQuality; + +typedef enum { + WPAD_ILBUF_NONE = 0, + + WPAD_ILBUF_BUF3E = (1 << 0), + WPAD_ILBUF_BUF3F = (1 << 1), + + WPAD_ILBUF_ALL = WPAD_ILBUF_BUF3E | WPAD_ILBUF_BUF3F, +} WPADInterleaveBufferFlags; + +typedef struct WPADCommand { + u32 reportID; // at 0x0 + u8 dataBuf[RPT_MAX_SIZE]; // at 0x4 + u16 dataLength; // at 0x1A + void* dstBuf; // at 0x1C + u16 readLength; // at 0x20 + u32 readAddress; // at 0x24 + WPADInfo* statusReportOut; // at 0x28 + WPADCallback cmdCB; // at 0x2C +} WPADCommand; + +typedef struct WPADCommandQueue { + s8 front; // at 0x1 + s8 back; // at 0x0 + WPADCommand* buffer; // at 0x4 + u32 capacity; // at 0x8 +} WPADCommandQueue; + +typedef struct WPADDevConfig { + DPDObject dpd[WPAD_MAX_DPD_OBJECTS]; // at 0x0 + + s16 accX0g; // at 0x20 + s16 accY0g; // at 0x22 + s16 accZ0g; // at 0x24 + + s16 accX1g; // at 0x26 + s16 accY1g; // at 0x28 + s16 accZ1g; // at 0x2A + + u8 motor; // at 0x2C + u8 volume; // at 0x2D +} WPADDevConfig; + +typedef struct WPADFSConfig { + s16 stickXCenter; // at 0x0 + s16 at_0x02; // at 0x2 + s16 at_0x04; // at 0x4 + s16 stickYCenter; // at 0x6 + s16 at_0x08; // at 0x8 + s16 at_0x0a; // at 0xA + + s16 accX0g; // at 0xC + s16 accY0g; // at 0xE + s16 accZ0g; // at 0x10 + + s16 accX1g; // at 0x12 + s16 accY1g; // at 0x14 + s16 accZ1g; // at 0x16 +} WPADFSConfig; + +typedef struct WPADCLConfig { + s16 lStickXCenter; // at 0x0 + s16 at_0x02; // at 0x2 + s16 at_0x04; // at 0x4 + s16 lStickYCenter; // at 0x6 + s16 at_0x08; // at 0x8 + s16 at_0x0a; // at 0xA + + s16 rStickXCenter; // at 0xC + s16 at_0x0e; // at 0xE + s16 at_0x10; // at 0x10 + s16 rStickYCenter; // at 0x12 + s16 at_0x14; // at 0x14 + s16 at_0x16; // at 0x16 + + u8 triggerLZero; // at 0x18 + u8 triggerRZero; // at 0x19 +} WPADCLConfig; + +typedef struct WPADExtConfig { + union { + WPADFSConfig fs; + WPADCLConfig cl; + }; +} WPADExtConfig; + +typedef struct WPADCB { + WPADGameInfo gameInfo; // at 0x0 + s32 UNK_0x38[2]; + u8 rxBufMain[RX_BUFFER_SIZE]; // at 0x40 + u8 rxBufs[2][RX_BUFFER_SIZE]; // at 0xA0 + WPADCommandQueue stdCmdQueue; // at 0x160 + WPADCommand stdCmdQueueList[24]; // at 0x16C + WPADCommandQueue extCmdQueue; // at 0x5EC + WPADCommand extCmdQueueList[12]; // at 0x5F8 + WPADInfo wpInfo; // at 0x838 + WPADInfo* wpInfoOut; // at 0x850 + WPADDevConfig devConfig; // at 0x854 + WPADExtConfig extConfig; // at 0x882 + WPADCallback cmdBlkCB; // at 0x89C + WPADExtensionCallback extensionCB; // at 0x8A0 + WPADConnectCallback connectCB; // at 0x8A4 + WPADSamplingCallback samplingCB; // at 0x8A8 + union { + WPADStatus* samplingBuf; + WPADStatusEx* samplingBufEx; + WPADFSStatus* samplingBufFS; + WPADCLStatus* samplingBufCL; + }; // at 0x8AC + u32 samplingBufIndex; // at 0x8B0 + u32 samplingBufSize; // at 0x8B4 + u32 dataFormat; // at 0x8B8 + s32 status; // at 0x8BC + u8 statusReqBusy; // at 0x8C0 + u8 devType; // at 0x8C1 + u8 devMode; // at 0x8C2 + s8 devHandle; // at 0x8C3 + s32 UNK_0x8C4; + u8 rxBufIndex; // at 0x8C8 + s8 UNK_0x8C9; + u8 defaultDpdSize; // at 0x8CA + u8 currentDpdCommand; // at 0x8CB + u8 pendingDpdCommand; // at 0x8CC + u8 radioQuality; // at 0x8CD + u8 radioQualityOkMs; // at 0x8CE + u8 audioFrames; // at 0x8CF + u32 motorBusy; // at 0x8D0 + BOOL motorRunning; // at 0x8D4 + BOOL used; // at 0x8D8 + BOOL handshakeFinished; // at 0x8DC + s32 configIndex; // at 0x8E0 + OSThreadQueue threadQueue; // at 0x8E4 + s64 lastControllerDataUpdate; // at 0x8F0 + u16 filterDiffDpd; // at 0x8F8 + u16 filterSameDpd; // at 0x8FA + u16 filterDiffAcc; // at 0x8FC + u16 filterSameAcc; // at 0x8FE + u16 filterDiffExt; // at 0x900 + u16 filterSameExt; // at 0x902 + s64 lastReportSendTime; // at 0x908 + u8 UNK_0x910; + u8 calibrated; // at 0x911 + u16 comboHeld; // at 0x912 + u8 encryptionKey[16]; // at 0x914 + u8 decryptAddTable[8]; // at 0x924 + u8 decryptXorTable[8]; // at 0x92C + u8 wmReadDataBuf[64]; // at 0x934 + u8* wmReadDataPtr; // at 0x974 + u32 wmReadAddress; // at 0x978 + int wmReadHadError; // at 0x97C + u16 wmReadLength; // at 0x980 + s8 UNK_0x982; + u8 radioSensitivity; // at 0x983 + u16 copyOutCount; // at 0x984 + u8 sleeping; // at 0x986 + u8 lastReportID; // at 0x987 + WPADCallback getInfoCB; // at 0x988 + u8 getInfoBusy; // at 0x98C + u8 UNK_0x98F[0x9A0 - 0x990]; +} WPADCB; + +extern WPADCB _wpd[WPAD_MAX_CONTROLLERS]; +extern WPADCB* _wpdcb[WPAD_MAX_CONTROLLERS]; + +void WPADiInitSub(void); + +void WPADiExcludeButton(s32 chan); +void WPADiCopyOut(s32 chan); + +BOOL WPADiSendSetPort(WPADCommandQueue* pQueue, u8 port, + WPADCallback pCallback); +BOOL WPADiSendSetReportType(WPADCommandQueue* pQueue, s32 format, + WPADCallback pCallback); +BOOL WPADiSendEnableDPD(WPADCommandQueue* pQueue, BOOL enable, + WPADCallback pCallback); +BOOL WPADiSendEnableSpeaker(WPADCommandQueue* pQueue, BOOL enable, + WPADCallback pCallback); +BOOL WPADiSendGetContStat(WPADCommandQueue* pQueue, WPADInfo* pInfo, + WPADCallback pCallback); +BOOL WPADiSendWriteDataCmd(WPADCommandQueue* pQueue, u8 cmd, u32 addr, + WPADCallback pCallback); +BOOL WPADiSendWriteData(WPADCommandQueue* pQueue, const void* pSrc, u16 len, + u32 addr, WPADCallback pCallback); +BOOL WPADiSendReadData(WPADCommandQueue* pQueue, void* pDst, u16 len, u32 addr, + WPADCallback pCallback); +BOOL WPADiSendStreamData(WPADCommandQueue* pQueue, const void* pData, u16 len); +BOOL WPADiSendMuteSpeaker(WPADCommandQueue* pQueue, BOOL mute, + WPADCallback pCallback); +BOOL WPADiSendDPDCSB(WPADCommandQueue* pQueue, BOOL enable, + WPADCallback pCallback); + +void WPADiClearQueue(WPADCommandQueue* pQueue); +BOOL WPADiPushCommand(WPADCommandQueue* pQueue, WPADCommand command); +BOOL WPADiGetCommand(const WPADCommandQueue* pQueue, WPADCommand* pCommand); +BOOL WPADiPopCommand(WPADCommandQueue* pQueue); + +u16 _WPADGetStackBufferStatus(s32 chan); +u16 _WPADGetModuleBufferStatus(s32 chan); + +void __WPADShutdown(void); +void __WPADReconnect(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/revolution/WPAD/WPADMem.h b/include/revolution/WPAD/WPADMem.h new file mode 100644 index 0000000..e212268 --- /dev/null +++ b/include/revolution/WPAD/WPADMem.h @@ -0,0 +1,44 @@ +#ifndef RVL_SDK_WPAD_MEM_H +#define RVL_SDK_WPAD_MEM_H +#include + +#include +#ifdef __cplusplus +extern "C" { +#endif + +#define WM_MEM_ADDR(ADDR) ((ADDR) & 0xFFFF) + +#define WM_EXT_REG_ADDR(TYPE, ADDR) \ + (((ADDR) & 0xFFFF) | ((WPAD_EXT_REG_##TYPE) << 16) | (1 << 26)) + +typedef enum { + WPAD_EXT_REG_SPEAKER = 0xA2, + WPAD_EXT_REG_EXTENSION = 0xA4, + WPAD_EXT_REG_MOTION_PLUS = 0xA6, + WPAD_EXT_REG_DPD = 0xB0 +} WPADExtRegType; + +typedef struct WPADMemBlock { + int at_0x00; // at 0x00 + int at_0x04; // at 0x04 + s16 at_0x08; // at 0x08 + int at_0x0c; // at 0x0C + WPADCallback at_0x10; // at 0x10 +} WPADMemBlock; + +typedef struct WPADGameInfo { + s64 timestamp; // at 0x0 + u16 gameName[16 + 1]; // at 0x8 + char gameID[4]; // at 0x2A + u8 gameType; // at 0x2E + u8 checksum; // at 0x2F + u8 UNK_0x30[8]; +} WPADGameInfo; + +extern WPADMemBlock _wmb[WPAD_MAX_CONTROLLERS]; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/revolution/WPAD/debug_msg.h b/include/revolution/WPAD/debug_msg.h new file mode 100644 index 0000000..f12de06 --- /dev/null +++ b/include/revolution/WPAD/debug_msg.h @@ -0,0 +1,13 @@ +#ifndef RVL_SDK_WPAD_DEBUG_MSG_H +#define RVL_SDK_WPAD_DEBUG_MSG_H +#include +#ifdef __cplusplus +extern "C" { +#endif + +void DEBUGPrint(const char* pFmt, ...); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/revolution/WUD/WUD.h b/include/revolution/WUD/WUD.h index 695ee76..1e754bb 100644 --- a/include/revolution/WUD/WUD.h +++ b/include/revolution/WUD/WUD.h @@ -1,19 +1,30 @@ #ifndef RVL_SDK_WUD_H #define RVL_SDK_WUD_H #include + +#include +#include #ifdef __cplusplus extern "C" { #endif -#define WUD_MAX_DEV_ENTRY_FOR_STD 10 -#define WUD_MAX_DEV_ENTRY_FOR_SMP 6 - -#define WUD_MAX_DEV_ENTRY 16 +#define WUD_MAX_DEV_ENTRY_FOR_STD SC_MAX_DEV_ENTRY_FOR_STD +#define WUD_MAX_DEV_ENTRY_FOR_SMP SC_MAX_DEV_ENTRY_FOR_SMP +#define WUD_MAX_DEV_ENTRY SC_MAX_DEV_ENTRY #define WUD_DEV_HANDLE_INVALID (-1) // Forward declarations typedef struct WUDDevInfo WUDDevInfo; +typedef enum { + WUD_LIB_STATUS_0, + WUD_LIB_STATUS_1, + WUD_LIB_STATUS_2, + WUD_LIB_STATUS_3, + WUD_LIB_STATUS_4, + WUD_LIB_STATUS_5, +} WUDLibStatus; + typedef enum { WUD_CHAN0, WUD_CHAN1, @@ -24,14 +35,6 @@ typedef enum { WUD_CHAN_INVALID = -1 } WUDChannel; -typedef enum { - WUD_LIB_STATUS_0, - WUD_LIB_STATUS_1, - WUD_LIB_STATUS_2, - WUD_LIB_STATUS_3, - WUD_LIB_STATUS_4, -} WUDLibStatus; - typedef enum { WUD_SYNC_TYPE_STANDARD, WUD_SYNC_TYPE_SIMPLE, @@ -41,39 +44,94 @@ typedef void* (*WUDAllocFunc)(u32 size); typedef BOOL (*WUDFreeFunc)(void* pBlock); typedef void (*WUDSyncDeviceCallback)(s32 result, s32 num); -typedef void (*WUDClearDeviceCallback)(s8 result); - -typedef void (*WUDHidConnectCallback)(WUDDevInfo* pInfo, u8 isOpenEvent); -typedef void (*WUDHidReceiveCallback)(UINT8 devHandle, UINT8* pReport, - UINT16 len); +typedef void (*WUDClearDeviceCallback)(s32 result); -typedef struct WUDSmallDevInfo { - char devName[20]; // at 0x0 - char at_0x14[1]; - char UNK_0x15[0xB]; - LINK_KEY linkKey; // at 0x20 - char UNK_0x30[0x10]; -} WUDSmallDevInfo; +typedef void (*WUDHidConnCallback)(UINT8 devHandle, u8 open); +typedef void (*WUDHidRecvCallback)(UINT8 devHandle, UINT8* pReport, UINT16 len); typedef struct WUDDevInfo { - WUDSmallDevInfo small; // at 0x0 - BD_ADDR devAddr; // at 0x40 - LINK_KEY linkKey; // at 0x46 - UINT8 devHandle; // at 0x56 - UINT8 subclass; // at 0x57 - UINT8 appID; // at 0x58 - u8 status; // at 0x59 - s8 UNK_0x5A; // at 0x5A - u8 UNK_0x5B; // at 0x5B - u8 UNK_0x5C; // at 0x5C - u8 unk_0x5d[1]; + SCDevInfo conf; // at 0x0 + BD_ADDR devAddr; // at 0x40 + LINK_KEY linkKey; // at 0x46 + UINT8 devHandle; // at 0x56 + UINT8 subclass; // at 0x57 + UINT8 appID; // at 0x58 + u8 status; // at 0x59 + s8 UNK_0x5A; // at 0x5A + u8 UNK_0x5B; // at 0x5B + u8 UNK_0x5C; // at 0x5C + u8 UNK_0x5D[1]; tBTA_HH_ATTR_MASK hhAttrMask; // at 0x5E } WUDDevInfo; +BOOL WUDInit(void); +BOOL WUDIsBusy(void); +void WUDRegisterAllocator(WUDAllocFunc pAllocFunc, WUDFreeFunc pFreeFunc); +u32 WUDGetAllocatedMemSize(void); +void WUDShutdown(void); + +WUDLibStatus WUDGetStatus(void); +u8 WUDGetBufferStatus(void); + +void WUDSetSniffMode(BD_ADDR addr, s32 interval); + +// clang-format off +WUDSyncDeviceCallback +WUDSetSyncSimpleCallback(WUDSyncDeviceCallback pCallback); + +WUDClearDeviceCallback +WUDSetClearDeviceCallback(WUDClearDeviceCallback pCallback); +// clang-format on + +BOOL WUDStartSyncDevice(void); +BOOL WUDStartFastSyncSimple(void); +BOOL WUDStartSyncSimple(void); +BOOL WUDStopSyncSimple(void); + +BOOL WUDStartClearDevice(void); +BOOL WUDSetDisableChannel(s8 afhChannel); + +WUDHidRecvCallback WUDSetHidRecvCallback(WUDHidRecvCallback pCallback); +WUDHidConnCallback WUDSetHidConnCallback(WUDHidConnCallback pCallback); + +void WUDSetVisibility(u8 disc, u8 conn); +u8 WUDGetConnectable(void); + +void WUDiGetFirmwareVersion(void); +void WUDiInitSub(void); + +void WUDiEnableStack(void); +void WUDiAutoSync(void); +void WUDiDeleteAllLinkKeys(void); + +void WUDiRegisterDevice(BD_ADDR addr); +void WUDiRemoveDevice(BD_ADDR addr); + +WUDDevInfo* WUDiGetDevInfo(BD_ADDR addr); +WUDDevInfo* WUDiGetDevInfoIndex(int idx); +WUDDevInfo* WUDiGetNewDevInfo(void); +void WUDiRemoveDevInfo(BD_ADDR addr); +void WUDiClearDevice(void); + +u8 WUDiGetDevNumber(void); +u8 WUDiGetDevSmpNumber(void); +u8 WUDiGetConnNumber(void); +u8 WUDiGetLinkNum(void); + +void WUDiMoveTopSmpDevInfoPtr(WUDDevInfo* pInfo); void WUDiMoveBottomSmpDevInfoPtr(WUDDevInfo* pInfo); +WUDDevInfo* WUDiGetRemoveSmpDevice(void); +void WUDiMoveTopOfDisconnectedSmpDevice(WUDDevInfo* pInfo); + void WUDiMoveTopStdDevInfoPtr(WUDDevInfo* pInfo); void WUDiMoveBottomStdDevInfoPtr(WUDDevInfo* pInfo); -BOOL WUDIsBusy(void); +WUDDevInfo* WUDiGetRemoveStdDevice(void); +void WUDiMoveTopOfDisconnectedStdDevice(WUDDevInfo* pInfo); + +BD_ADDR_PTR _WUDGetDevAddr(UINT8 handle); +u16 _WUDGetQueuedSize(s8 handle); +u16 _WUDGetNotAckedSize(s8 handle); +u8 _WUDGetLinkNumber(void); #ifdef __cplusplus } diff --git a/include/revolution/WUD/WUDHidHost.h b/include/revolution/WUD/WUDHidHost.h index 5341c28..50613b0 100644 --- a/include/revolution/WUD/WUDHidHost.h +++ b/include/revolution/WUD/WUDHidHost.h @@ -7,7 +7,7 @@ extern "C" { #endif -void WUDiHidHostEventCallback(tBTA_HH_EVT event, tBTA_HH* p_data); +void WUDHidHostCallback(tBTA_HH_EVT event, tBTA_HH* pData); #ifdef __cplusplus } diff --git a/include/revolution/WUD/WUDInternal.h b/include/revolution/WUD/WUDInternal.h index fda4f75..36e6225 100644 --- a/include/revolution/WUD/WUDInternal.h +++ b/include/revolution/WUD/WUDInternal.h @@ -7,20 +7,26 @@ #include #include +#include #ifdef __cplusplus extern "C" { #endif -typedef enum { - WUD_STATE_START = 0, +#define WUD_BDCMP(LHS, RHS) memcmp(LHS, RHS, BD_ADDR_LEN) +#define WUD_BDCPY(DST, SRC) memcpy(DST, SRC, BD_ADDR_LEN) + +// clang-format off +#define WUD_DEV_NAME_IS(NAME, VALUE) \ + (memcmp(NAME, VALUE, sizeof(VALUE) - 1) == 0) - WUD_STATE_WII_FIT_OPEN = 100, - WUD_STATE_WII_FIT_SEEK = 101, - WUD_STATE_WII_FIT_UPDATE = 102, - WUD_STATE_WII_FIT_CLOSE = 103, +#define WUD_DEV_NAME_IS_CNT(NAME) \ + WUD_DEV_NAME_IS(NAME, "Nintendo RVL-CNT") - WUD_STATE_ERROR = 255 -} WUDState; +#define WUD_DEV_NAME_IS_CNT_01(NAME) \ + WUD_DEV_NAME_IS(NAME, "Nintendo RVL-CNT-01") +// clang-format on + +typedef enum { WUD_STATE_START = 0, WUD_STATE_ERROR = 255 } WUDState; typedef enum { WUD_STATE_SYNC_PREPARE_SEARCH = 1, @@ -47,7 +53,7 @@ typedef enum { WUD_STATE_SYNC_COMPLETE = 23, WUD_STATE_SYNC_WAIT_FOR_INCOMING = 24, WUD_STATE_SYNC_SC_FLUSH = 25, - WUD_STATE_SYNC_26 = 26, + WUD_STATE_SYNC_CANCEL_SEARCH = 26, WUD_STATE_SYNC_WAIT_FOR_START_SEARCH = 29, } WUDSyncState; @@ -120,6 +126,16 @@ typedef struct WUDDiscResp { u8 UNK_0x104[0x4]; } WUDDiscResp; +typedef struct WUDPatchCmd { + u8 data[13]; // at 0x0 +} WUDPatchCmd; +typedef struct WUDPatchList { + u8 num; // at 0x0 + WUDPatchCmd cmds[]; // at 0x1 +} WUDPatchList; +#define WUD_PATCH_BUFFER_SIZE 0xFF +#define WUD_MAX_PATCHES (WUD_PATCH_BUFFER_SIZE / (s32)sizeof(WUDPatchCmd)) + typedef struct WUDCB { WUDSyncDeviceCallback syncStdCB; // at 0x0 WUDSyncDeviceCallback syncSmpCB; // at 0x4 @@ -157,8 +173,8 @@ typedef struct WUDCB { u8 connectable; // at 0x6EA u8 discoverable; // at 0x6EB - WUDHidReceiveCallback hidRecvCB; // at 0x6EC - WUDHidConnectCallback hidConnCB; // at 0x6F0 + WUDHidRecvCallback hidRecvCB; // at 0x6EC + WUDHidConnCallback hidConnCB; // at 0x6F0 WUDAllocFunc allocFunc; // at 0x6F4 WUDFreeFunc freeFunc; // at 0x6F8 @@ -176,13 +192,16 @@ typedef struct WUDCB { u16 bufferStatus0; // at 0x744 u16 bufferStatus1; // at 0x746 - - s8 initWaitDeviceUpFrames; // at 0x748 - s8 waitStartSearchFrames; // at 0x749 - s16 waitIncomingFrames; // at 0x74A } WUDCB; extern WUDCB _wcb; +extern WUDDevInfo _work; + +extern SCBtDeviceInfoArray _scArray; + +extern BD_ADDR_PTR _dev_handle_to_bda[WUD_MAX_DEV_ENTRY]; +extern u16 _dev_handle_queue_size[WUD_MAX_DEV_ENTRY]; +extern u16 _dev_handle_notack_num[WUD_MAX_DEV_ENTRY]; #ifdef __cplusplus } diff --git a/include/revolution/WUD/debug_msg.h b/include/revolution/WUD/debug_msg.h index 4927e76..3790d7b 100644 --- a/include/revolution/WUD/debug_msg.h +++ b/include/revolution/WUD/debug_msg.h @@ -5,7 +5,7 @@ extern "C" { #endif -void WUD_DEBUGPrint(const char* pMsg, ...); +void WUD_DEBUGPrint(const char* pFmt, ...); #ifdef __cplusplus } diff --git a/include/revolution/version.h b/include/revolution/version.h new file mode 100644 index 0000000..6b1b414 --- /dev/null +++ b/include/revolution/version.h @@ -0,0 +1,10 @@ +#ifndef RVL_SDK_VERSION_H +#define RVL_SDK_VERSION_H +#include + +#define RVL_LIB_VERSION(NAME, ORIGINAL_DATE, ORIGINAL_TIME, ORIGINAL_CWCC) \ + const char* __##NAME##Version = \ + "<< RVL_SDK - " #NAME " \trelease build: " ORIGINAL_DATE \ + " " ORIGINAL_TIME " (" ORIGINAL_CWCC ") >>" + +#endif diff --git a/include/types.h b/include/types.h index c47be0d..93d92b8 100644 --- a/include/types.h +++ b/include/types.h @@ -14,6 +14,7 @@ #include #include +#include #include typedef unsigned long long u64; diff --git a/lib/libkiwi/core/kiwiController.h b/lib/libkiwi/core/kiwiController.h index 92cb54c..fd36687 100644 --- a/lib/libkiwi/core/kiwiController.h +++ b/lib/libkiwi/core/kiwiController.h @@ -80,10 +80,10 @@ class WiiCtrl : public Extension { static u32 ConvertMask(u32 mask); /** - * @brief Gets KPAD data (read-only) + * @brief Gets controller status data (read-only) */ - const KPADStatus& GetStatus() const { - return *reinterpret_cast(getCoreStatus()); + const EGG::CoreStatus& GetStatus() const { + return *const_cast(this)->getCoreStatus(); } }; diff --git a/lib/libkiwi/core/kiwiDvdStream.cpp b/lib/libkiwi/core/kiwiDvdStream.cpp index a2014fe..f003f16 100644 --- a/lib/libkiwi/core/kiwiDvdStream.cpp +++ b/lib/libkiwi/core/kiwiDvdStream.cpp @@ -16,12 +16,13 @@ bool DvdStream::Open(const String& rPath) { // Need to get the file entry number from the FST s32 entryNum = DVDConvertPathToEntrynum(rPath); if (entryNum < 0) { - K_LOG_EX("Can't find DVD file: %s\n", rPath.CStr()); return false; } - if (!DVDFastOpen(entryNum, &mFileInfo)) { - K_LOG_EX("Can't open DVD file: %s\n", rPath.CStr()); + bool success = DVDFastOpen(entryNum, &mFileInfo); + K_ASSERT(success); + + if (!success) { return false; } @@ -105,7 +106,7 @@ s32 DvdStream::ReadImpl(void* pDst, u32 size) { s32 DvdStream::WriteImpl(const void* pSrc, u32 size) { K_ASSERT_PTR(pSrc); K_ASSERT_EX(false, "DVD is immutable"); - return DVD_RESULT_FATAL; + return DVD_RESULT_FATAL_ERROR; } /** diff --git a/lib/libkiwi/core/kiwiFileRipper.cpp b/lib/libkiwi/core/kiwiFileRipper.cpp index 0e356a4..815795e 100644 --- a/lib/libkiwi/core/kiwiFileRipper.cpp +++ b/lib/libkiwi/core/kiwiFileRipper.cpp @@ -51,7 +51,13 @@ void* FileRipper::Rip(FileStream& rStrm, const FileRipperArg& rArg) { // ...or ripper may be responsible for allocating one if (pBuffer == nullptr) { - pBuffer = new (rStrm.GetBufferAlign(), rArg.region) u8[bufferSize]; + s32 align = Max(rStrm.GetBufferAlign(), rArg.align); + + if (rArg.pHeap != nullptr) { + pBuffer = new (align, rArg.pHeap) u8[bufferSize]; + } else { + pBuffer = new (align, rArg.region) u8[bufferSize]; + } } K_ASSERT_PTR(pBuffer); diff --git a/lib/libkiwi/core/kiwiFileRipper.h b/lib/libkiwi/core/kiwiFileRipper.h index e143c52..6931eb8 100644 --- a/lib/libkiwi/core/kiwiFileRipper.h +++ b/lib/libkiwi/core/kiwiFileRipper.h @@ -3,6 +3,8 @@ #include #include +#include + namespace kiwi { //! @addtogroup libkiwi_core //! @{ @@ -35,16 +37,34 @@ struct FileRipperArg { */ u32* pSize; + /** + * @brief Heap to use for ripper memory allocation + * @note Overrides `region` setting. + */ + EGG::Heap* pHeap; + /** * @brief Memory region to use for ripper memory allocation * @details Defaults to MEM2. + * @note Ignored when heap is specified with `pHeap`. */ EMemory region; + /** + * @brief Byte alignment to use for ripper memory allocation + * @details Defaults to 4. + */ + s32 align; + /** * @brief Constructor */ - FileRipperArg() : pDst(nullptr), pSize(nullptr), region(EMemory_MEM2) {} + FileRipperArg() + : pDst(nullptr), + pSize(nullptr), + pHeap(nullptr), + region(EMemory_MEM2), + align(4) {} }; /** diff --git a/lib/libkiwi/core/kiwiIScene.cpp b/lib/libkiwi/core/kiwiIScene.cpp index 2664774..94e4e05 100644 --- a/lib/libkiwi/core/kiwiIScene.cpp +++ b/lib/libkiwi/core/kiwiIScene.cpp @@ -12,6 +12,8 @@ void IScene::Configure() { // Setup renderer view RPGrpScreen* pScreen = new RPGrpScreen(); K_ASSERT_PTR(pScreen); + + pScreen->SetFarZ(10000.0f); pScreen->SetCanvasMode(RPGrpScreen::CANVASMODE_CC); // Create 2D view for layout draw diff --git a/lib/libkiwi/core/kiwiIScene.h b/lib/libkiwi/core/kiwiIScene.h index 9f60342..1a3b028 100644 --- a/lib/libkiwi/core/kiwiIScene.h +++ b/lib/libkiwi/core/kiwiIScene.h @@ -19,7 +19,7 @@ namespace kiwi { // Forward declarations namespace detail { template class SceneDecl; -} +} // namespace detail /** * @brief User scene interface diff --git a/lib/libkiwi/core/kiwiIStream.h b/lib/libkiwi/core/kiwiIStream.h index 8070903..b0d9c1e 100644 --- a/lib/libkiwi/core/kiwiIStream.h +++ b/lib/libkiwi/core/kiwiIStream.h @@ -51,6 +51,13 @@ class IStream { return mIsOpen; } + /** + * @brief Gets the current stream position + */ + virtual u32 GetPosition() const { + return mPosition; + } + /** * @brief Tests whether this stream type supports seeking */ diff --git a/lib/libkiwi/core/kiwiJSON.cpp b/lib/libkiwi/core/kiwiJSON.cpp index f07d38d..2e1e7cd 100644 --- a/lib/libkiwi/core/kiwiJSON.cpp +++ b/lib/libkiwi/core/kiwiJSON.cpp @@ -1229,10 +1229,10 @@ void PrintVisitor::Visit(const Element& rElement) { for (Object::ConstIterator it = rElement.Get().Begin(); it != rElement.Get().End(); ++it, i++) { - Print('\"' + (it.Key() + "\": ")); + Print('\"' + (it->key + "\": ")); // TODO: Fix this somehow? - Visit(it.Value()); + Visit(it->value); // Values are comma separated if (i != size - 1) { diff --git a/lib/libkiwi/core/kiwiJSON.h b/lib/libkiwi/core/kiwiJSON.h index 486c661..b3e7792 100644 --- a/lib/libkiwi/core/kiwiJSON.h +++ b/lib/libkiwi/core/kiwiJSON.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -21,7 +20,7 @@ class Element; //! JSON 'array' contains zero or more elements typedef TVector Array; //! JSON 'object' contains zero or more key/value pairs -typedef TMap Object; +typedef THashMap Object; struct Null_t {}; //! JavaScript 'null' keyword diff --git a/lib/libkiwi/core/kiwiMemStream.h b/lib/libkiwi/core/kiwiMemStream.h index 167bae7..e11ce87 100644 --- a/lib/libkiwi/core/kiwiMemStream.h +++ b/lib/libkiwi/core/kiwiMemStream.h @@ -78,6 +78,13 @@ class MemStream : public FileStream { */ virtual void Close(); + /** + * @brief Gets the currently open buffer + */ + const u8* GetBuffer() const { + return mpBuffer; + } + /** * @brief Gets the size of the currently open buffer */ diff --git a/lib/libkiwi/core/kiwiMemoryMgr.cpp b/lib/libkiwi/core/kiwiMemoryMgr.cpp index 9c4a38d..ac1e1d9 100644 --- a/lib/libkiwi/core/kiwiMemoryMgr.cpp +++ b/lib/libkiwi/core/kiwiMemoryMgr.cpp @@ -2,6 +2,8 @@ #include +#include + namespace kiwi { namespace { @@ -35,14 +37,21 @@ void CheckDoubleFree(const void* pBlock) { K_ASSERT_PTR(pBlock); - // Sanity check, should always be ExpHeap MEMiHeapHead* pHandle = MEMFindContainHeap(pBlock); K_ASSERT_PTR(pHandle); - K_ASSERT(pHandle->magic == 'EXPH'); + K_ASSERT(pHandle->magic == 'EXPH' || pHandle->magic == 'FRMH'); + + // Only expanded heaps have memory blocks we can check + if (pHandle->magic != 'EXPH') { + return; + } // Heap block lives before the allocated memory - const MEMiExpHeapMBlock* pMBlock = static_cast( - AddToPtr(pBlock, -sizeof(MEMiExpHeapMBlock))); + const MEMiExpHeapMBlock* pMBlock = + AddToPtr(pBlock, -sizeof(MEMiExpHeapMBlock)); + + K_ASSERT_EX(pMBlock->state == 'UD' || pMBlock->state == 'FR', + "Heap block is corrupted"); K_ASSERT_EX(pMBlock->state == 'UD', "Double free!"); #endif @@ -121,7 +130,7 @@ EGG::Heap* MemoryMgr::GetHeap(EMemory memory) const { */ void* MemoryMgr::Alloc(u32 size, s32 align, EMemory memory) const { void* pBlock = GetHeap(memory)->alloc(size, align); - K_ASSERT_EX(pBlock != nullptr, "Out of memory (alloc %d)", size); + K_ASSERT_PTR_EX(pBlock, "Out of memory (alloc %d)", size); K_ASSERT(memory == EMemory_MEM1 ? OSIsMEM1Region(pBlock) : OSIsMEM2Region(pBlock)); @@ -140,7 +149,7 @@ void MemoryMgr::Free(void* pBlock) const { } /** - * @brief Gets total size of available heap memory + * @brief Gets size of available heap memory * * @param memory Target memory region */ @@ -148,6 +157,15 @@ u32 MemoryMgr::GetFreeSize(EMemory memory) const { return GetHeap(memory)->getAllocatableSize(); } +/** + * @brief Gets size of total heap memory + * + * @param memory Target memory region + */ +u32 MemoryMgr::GetTotalSize(EMemory memory) const { + return static_cast(GetHeap(memory)->getTotalSize()); +} + /** * @brief Tests whether an address points to an allocation from this manager * @@ -237,6 +255,37 @@ void* operator new[](size_t size, kiwi::EMemory memory) { return kiwi::MemoryMgr::GetInstance().Alloc(size, 4, memory); } +/** + * @brief Allocates a block of memory + * + * @param size Block size + * @param pHeap Target heap + * @return Pointer to allocated block + */ +void* operator new(size_t size, EGG::Heap* pHeap) { + K_ASSERT_PTR(pHeap); + + void* pBlock = pHeap->alloc(size); + K_ASSERT_PTR_EX(pBlock, "Out of memory (alloc %d)", size); + + return pBlock; +} +/** + * @brief Allocates a block of memory for an array + * + * @param size Block size + * @param pHeap Target heap + * @return Pointer to allocated block + */ +void* operator new[](size_t size, EGG::Heap* pHeap) { + K_ASSERT_PTR(pHeap); + + void* pBlock = pHeap->alloc(size); + K_ASSERT_PTR_EX(pBlock, "Out of memory (alloc %d)", size); + + return pBlock; +} + /** * @brief Allocates a block of memory * @@ -260,6 +309,39 @@ void* operator new[](size_t size, s32 align, kiwi::EMemory memory) { return kiwi::MemoryMgr::GetInstance().Alloc(size, align, memory); } +/** + * @brief Allocates a block of memory + * + * @param size Block size + * @param align Block address alignment + * @param pHeap Target heap + * @return Pointer to allocated block + */ +void* operator new(size_t size, s32 align, EGG::Heap* pHeap) { + K_ASSERT_PTR(pHeap); + + void* pBlock = pHeap->alloc(size, align); + K_ASSERT_PTR_EX(pBlock, "Out of memory (alloc %d)", size); + + return pBlock; +} +/** + * @brief Allocates a block of memory for an array + * + * @param size Block size + * @param align Block address alignment + * @param pHeap Target heap + * @return Pointer to allocated block + */ +void* operator new[](size_t size, s32 align, EGG::Heap* pHeap) { + K_ASSERT_PTR(pHeap); + + void* pBlock = pHeap->alloc(size, align); + K_ASSERT_PTR_EX(pBlock, "Out of memory (alloc %d)", size); + + return pBlock; +} + /** * @brief Frees a block of memory * diff --git a/lib/libkiwi/core/kiwiMemoryMgr.h b/lib/libkiwi/core/kiwiMemoryMgr.h index 03d015a..0a69ae4 100644 --- a/lib/libkiwi/core/kiwiMemoryMgr.h +++ b/lib/libkiwi/core/kiwiMemoryMgr.h @@ -34,7 +34,7 @@ class MemoryMgr : public StaticSingleton { * @param memory Target memory region * @return Pointer to allocated block */ - void* Alloc(u32 size, s32 align, EMemory region) const; + void* Alloc(u32 size, s32 align, EMemory memory) const; /** * @brief Frees a block of memory @@ -44,11 +44,18 @@ class MemoryMgr : public StaticSingleton { void Free(void* pBlock) const; /** - * @brief Gets total size of available heap memory + * @brief Gets size of available heap memory * * @param memory Target memory region */ - u32 GetFreeSize(EMemory region) const; + u32 GetFreeSize(EMemory memory) const; + + /** + * @brief Gets size of total heap memory + * + * @param memory Target memory region + */ + u32 GetTotalSize(EMemory memory) const; /** * @brief Tests whether an address points to an allocation from this manager @@ -143,6 +150,23 @@ void* operator new(size_t size, kiwi::EMemory memory); */ void* operator new[](size_t size, kiwi::EMemory memory); +/** + * @brief Allocates a block of memory + * + * @param size Block size + * @param pHeap Target heap + * @return Pointer to allocated block + */ +void* operator new(size_t size, EGG::Heap* pHeap); +/** + * @brief Allocates a block of memory for an array + * + * @param size Block size + * @param pHeap Target heap + * @return Pointer to allocated block + */ +void* operator new[](size_t size, EGG::Heap* pHeap); + /** * @brief Allocates a block of memory * @@ -162,6 +186,25 @@ void* operator new(size_t size, s32 align, kiwi::EMemory memory); */ void* operator new[](size_t size, s32 align, kiwi::EMemory memory); +/** + * @brief Allocates a block of memory + * + * @param size Block size + * @param align Block address alignment + * @param pHeap Target heap + * @return Pointer to allocated block + */ +void* operator new(size_t size, s32 align, EGG::Heap* pHeap); +/** + * @brief Allocates a block of memory for an array + * + * @param size Block size + * @param align Block address alignment + * @param pHeap Target heap + * @return Pointer to allocated block + */ +void* operator new[](size_t size, s32 align, EGG::Heap* pHeap); + /** * @brief Frees a block of memory * diff --git a/lib/libkiwi/core/kiwiNandStream.h b/lib/libkiwi/core/kiwiNandStream.h index bbfcb72..4fa0957 100644 --- a/lib/libkiwi/core/kiwiNandStream.h +++ b/lib/libkiwi/core/kiwiNandStream.h @@ -39,6 +39,14 @@ class NandStream : public FileStream { Close(); } + /** + * @brief Gets the current stream position + */ + virtual u32 GetPosition() const { + K_NOT_IMPLEMENTED(); + return 0; + } + /** * @brief Opens stream to NAND file * diff --git a/lib/libkiwi/core/kiwiSceneCreator.cpp b/lib/libkiwi/core/kiwiSceneCreator.cpp index 1fa5a1f..4f485ea 100644 --- a/lib/libkiwi/core/kiwiSceneCreator.cpp +++ b/lib/libkiwi/core/kiwiSceneCreator.cpp @@ -15,6 +15,13 @@ const SceneCreator::Info SceneCreator::scPackScenes[] = { {nullptr, "Logo", "RPCommon/", kiwi::ESceneID_RPSysBootScene, kiwi::EPackID_AllPack, kiwi::ECreateType_Standard, kiwi::EExitType_Sibling, true}, {nullptr, "Player Select", "RPCommon/", kiwi::ESceneID_RPSysPlayerSelectScene, kiwi::EPackID_AllPack, kiwi::ECreateType_Standard, kiwi::EExitType_2, true}, {nullptr, "Nunchuk Check", "RPCommon/", kiwi::ESceneID_RPSysNunchukScene, kiwi::EPackID_AllPack, kiwi::ECreateType_Sibling, kiwi::EExitType_3, false}, +#elif defined(PACK_PLAY) + {nullptr, "Logo", "RPCommonParty/", kiwi::ESceneID_RPSysBootScene, kiwi::EPackID_AllPack, kiwi::ECreateType_Standard, kiwi::EExitType_Sibling, true}, + {nullptr, "Player Select", "RPCommonParty/", kiwi::ESceneID_RPSysPlayerSelectScene, kiwi::EPackID_AllPack, kiwi::ECreateType_Standard, kiwi::EExitType_2, true}, + {nullptr, "Nunchuk Check", "RPCommonParty/", kiwi::ESceneID_RPSysNunchukScene, kiwi::EPackID_AllPack, kiwi::ECreateType_Sibling, kiwi::EExitType_3, false}, +#endif + +#if defined(PACK_SPORTS) || defined(PACK_PLAY) {nullptr, "Baseball", "RPBsbScene/", kiwi::ESceneID_RPBsbScene, kiwi::EPackID_SportsPack, kiwi::ECreateType_Sibling, kiwi::EExitType_Standard, false}, {nullptr, "Bowling", "RPBowScene/", kiwi::ESceneID_RPBowScene, kiwi::EPackID_SportsPack, kiwi::ECreateType_Sibling, kiwi::EExitType_Standard, false}, {nullptr, "Golf", "RPGolScene/", kiwi::ESceneID_RPGolScene, kiwi::EPackID_SportsPack, kiwi::ECreateType_Sibling, kiwi::EExitType_Standard, false}, @@ -27,10 +34,8 @@ const SceneCreator::Info SceneCreator::scPackScenes[] = { {nullptr, "Physical Measure Explanation", "RPSportsPhysical/", kiwi::ESceneID_RPSportsPhysicalPreviewScene, kiwi::EPackID_SportsPack, kiwi::ECreateType_Sibling, kiwi::EExitType_3, true}, {nullptr, "Physical Measure Results", "RPSportsPhysical/", kiwi::ESceneID_RPSportsPhysicalResultScene, kiwi::EPackID_SportsPack, kiwi::ECreateType_Sibling, kiwi::EExitType_3, true}, {nullptr, "Golf Course Select", "RPGolScene/", kiwi::ESceneID_RPGolSelectScene, kiwi::EPackID_SportsPack, kiwi::ECreateType_Sibling, kiwi::EExitType_Standard, false}, -#elif defined(PACK_PLAY) - {nullptr, "Logo", "RPCommonParty/", kiwi::ESceneID_RPSysBootScene, kiwi::EPackID_AllPack, kiwi::ECreateType_Standard, kiwi::EExitType_Sibling, true}, - {nullptr, "Player Select", "RPCommonParty/", kiwi::ESceneID_RPSysPlayerSelectScene, kiwi::EPackID_AllPack, kiwi::ECreateType_Standard, kiwi::EExitType_2, true}, - {nullptr, "Nunchuk Check", "RPCommonParty/", kiwi::ESceneID_RPSysNunchukScene, kiwi::EPackID_AllPack, kiwi::ECreateType_Sibling, kiwi::EExitType_3, false}, + + {nullptr, "Orchestra", "RPOchScene/", kiwi::ESceneID_RPOchScene, kiwi::EPackID_PartyPack, kiwi::ECreateType_Sibling, kiwi::EExitType_Standard, false}, {nullptr, "Fishing", "RPFshScene/", kiwi::ESceneID_RPFshScene, kiwi::EPackID_PartyPack, kiwi::ECreateType_Sibling, kiwi::EExitType_Standard, false}, {nullptr, "Hockey", "RPHkyScene/", kiwi::ESceneID_RPHkyScene, kiwi::EPackID_PartyPack, kiwi::ECreateType_Sibling, kiwi::EExitType_Standard, false}, {nullptr, "Shooting", "RPDucScene/", kiwi::ESceneID_RPDucScene, kiwi::EPackID_PartyPack, kiwi::ECreateType_Sibling, kiwi::EExitType_Standard, false}, @@ -43,7 +48,9 @@ const SceneCreator::Info SceneCreator::scPackScenes[] = { {nullptr, "Party Pack", "RPPartyTitle/", kiwi::ESceneID_RPPartyTitleScene, kiwi::EPackID_PartyPack, kiwi::ECreateType_Standard, kiwi::EExitType_Sibling, true}, {nullptr, "Tour Menu", "RPPartyCommon/", kiwi::ESceneID_RPPartyMiiLoadScene, kiwi::EPackID_PartyPack, kiwi::ECreateType_Standard, kiwi::EExitType_Child, true}, {nullptr, "Tour Menu", "RPPartyCommon/", kiwi::ESceneID_RPPartyMenuScene, kiwi::EPackID_PartyPack, kiwi::ECreateType_Sibling, kiwi::EExitType_3, true}, -#elif defined(PACK_RESORT) +#endif + +#if defined(PACK_RESORT) {nullptr, "Strap", "StrapScene/", kiwi::ESceneID_Sp2StrapScene, false, kiwi::EGroupID_Cmn, kiwi::EPackID_SportsPack, kiwi::ECreateType_Standard, kiwi::EExitType_Standard, true}, {nullptr, "SaveDataLoad", "SeqScene1/", kiwi::ESceneID_Sp2SaveDataLoadScene, false, kiwi::EGroupID_Cmn, kiwi::EPackID_SportsPack, kiwi::ECreateType_Standard, kiwi::EExitType_Standard, true}, {nullptr, "Title", "SeqScene1/", kiwi::ESceneID_Sp2TitleScene, false, kiwi::EGroupID_Cmn, kiwi::EPackID_SportsPack, kiwi::ECreateType_Standard, kiwi::EExitType_Standard, true}, @@ -79,7 +86,12 @@ const SceneCreator::Info SceneCreator::scPackScenes[] = { /** * @brief User-registered scenes */ -TMap SceneCreator::sUserScenes; +THashMap SceneCreator::sUserScenes; + +/** + * @brief Previous scene ID + */ +s32 SceneCreator::sPrevSceneID = -1; /** * @brief Root debug menu scene ID @@ -162,13 +174,26 @@ void SceneCreator::RegistDebugRoot(s32 id, bool bootUp, u16 buttons) { } /** - * @brief Gets the scene ID of the main menu scene + * @brief Gets the scene ID of the bootup scene */ -s32 SceneCreator::GetMenuScene() { +s32 SceneCreator::GetBootScene() { +#if defined(PACK_SPORTS) || defined(PACK_PLAY) + return kiwi::ESceneID_RPSysBootScene; +#elif defined(PACK_RESORT) + return kiwi::ESceneID_Sp2StrapScene; +#else + return -1; +#endif +} + +/** + * @brief Gets the scene ID of the bootup scene + */ +s32 SceneCreator::GetTitleScene() { #if defined(PACK_SPORTS) - return kiwi::ESceneID_RPSportsMenuScene; + return kiwi::ESceneID_RPSportsTitleScene; #elif defined(PACK_PLAY) - return kiwi::ESceneID_RPPartyMenuScene; + return kiwi::ESceneID_RPPartyTitleScene; #elif defined(PACK_RESORT) return kiwi::ESceneID_Sp2TitleScene; #else @@ -177,18 +202,27 @@ s32 SceneCreator::GetMenuScene() { } /** - * @brief Gets the scene ID of the bootup scene + * @brief Gets the scene ID of the main menu scene */ -s32 SceneCreator::GetBootScene() { -#if defined(PACK_SPORTS) || defined(PACK_PLAY) - return kiwi::ESceneID_RPSysBootScene; +s32 SceneCreator::GetMenuScene() { +#if defined(PACK_SPORTS) + return kiwi::ESceneID_RPSportsMenuScene; +#elif defined(PACK_PLAY) + return kiwi::ESceneID_RPPartyMenuScene; #elif defined(PACK_RESORT) - return kiwi::ESceneID_Sp2StrapScene; + return kiwi::ESceneID_Sp2TitleScene; #else return -1; #endif } +/** + * @brief Gets the scene ID of the previous scene + */ +s32 SceneCreator::GetPrevSceneID() { + return sPrevSceneID; +} + #if defined(PACK_SPORTS) || defined(PACK_PLAY) /** * @brief Fades out into a new scene @@ -246,6 +280,7 @@ bool SceneCreator::ChangeSceneAfterFade(s32 id, bool reload) { mLastSceneID = current; } + sPrevSceneID = current; return success; } #elif defined(PACK_RESORT) @@ -312,13 +347,17 @@ bool SceneCreator::ChangeSceneAfterFade(s32 id, const nw4r::ut::Color* pColor) { } } + sPrevSceneID = current; return success; } #endif -KOKESHI_BY_PACK(KM_BRANCH_MF(0x80184ba4, SceneCreator, ChangeSceneAfterFade), // Wii Sports - KM_BRANCH_MF(0x8018459c, SceneCreator, ChangeSceneAfterFade), // Wii Play - KM_BRANCH_MF(0x8022edfc, SceneCreator, ChangeSceneAfterFade)); // Wii Sports Resort +KOKESHI_BY_PACK(KM_BRANCH_MF(0x80184ba4, SceneCreator, + ChangeSceneAfterFade), // Wii Sports + KM_BRANCH_MF(0x8018459c, SceneCreator, + ChangeSceneAfterFade), // Wii Play + KM_BRANCH_MF(0x8022edfc, SceneCreator, + ChangeSceneAfterFade)); // Wii Sports Resort /** * @brief Gets the specified scene's name @@ -341,9 +380,12 @@ const char* SceneCreator::GetSceneDirectory(s32 id) const { const Info* pInfo = GetSceneInfo(id); return pInfo->dir; } -KOKESHI_BY_PACK(KM_BRANCH_MF(0x80184758, SceneCreator, GetSceneDirectory), // Wii Sports - KM_BRANCH_MF(0x80184124, SceneCreator, GetSceneDirectory), // Wii Play - KM_BRANCH_MF(0x8022ebe8, SceneCreator, GetSceneDirectory)); // Wii Sports Resort +KOKESHI_BY_PACK(KM_BRANCH_MF(0x80184758, SceneCreator, + GetSceneDirectory), // Wii Sports + KM_BRANCH_MF(0x80184124, SceneCreator, + GetSceneDirectory), // Wii Play + KM_BRANCH_MF(0x8022ebe8, SceneCreator, + GetSceneDirectory)); // Wii Sports Resort #if defined(PACK_RESORT) /** @@ -358,7 +400,8 @@ bool SceneCreator::IsSceneWarnAsLoading(s32 id) const { K_ASSERT_PTR(pInfo); return pInfo->warnAsSceneLoading; } -KM_BRANCH_MF(0x8022eaf8, SceneCreator, IsSceneWarnAsLoading); // Wii Sports Resort +KM_BRANCH_MF(0x8022eaf8, SceneCreator, + IsSceneWarnAsLoading); // Wii Sports Resort /** * @brief Gets the specified scene's group @@ -397,9 +440,10 @@ ECreateType SceneCreator::GetSceneCreateType(s32 id) const { K_ASSERT_PTR(pInfo); return pInfo->create; } -KOKESHI_BY_PACK(KM_BRANCH_MF(0x801845f4, SceneCreator, GetSceneCreateType), // Wii Sports - KM_BRANCH_MF(0x8018402c, SceneCreator, GetSceneCreateType), // Wii Play - /* not applicable */); // Wii Sports Resort +KOKESHI_BY_PACK( + KM_BRANCH_MF(0x801845f4, SceneCreator, GetSceneCreateType), // Wii Sports + KM_BRANCH_MF(0x8018402c, SceneCreator, GetSceneCreateType), // Wii Play + /* not applicable */); // Wii Sports Resort /** * @brief Gets the specified scene's exit type @@ -412,9 +456,12 @@ EExitType SceneCreator::GetSceneExitType(s32 id) const { K_ASSERT_PTR(pInfo); return pInfo->exit; } -KOKESHI_BY_PACK(KM_BRANCH_MF(0x80184558, SceneCreator, GetSceneExitType), // Wii Sports - KM_BRANCH_MF(0x80183f90, SceneCreator, GetSceneExitType), // Wii Play - KM_BRANCH_MF(0x8022eac4, SceneCreator, GetSceneExitType)); // Wii Sports Resort +KOKESHI_BY_PACK(KM_BRANCH_MF(0x80184558, SceneCreator, + GetSceneExitType), // Wii Sports + KM_BRANCH_MF(0x80183f90, SceneCreator, + GetSceneExitType), // Wii Play + KM_BRANCH_MF(0x8022eac4, SceneCreator, + GetSceneExitType)); // Wii Sports Resort /** * @brief Tests whether the specified scene requires the RP common sound @@ -428,9 +475,10 @@ bool SceneCreator::IsSceneCommonSound(s32 id) const { K_ASSERT_PTR(pInfo); return pInfo->common; } -KOKESHI_BY_PACK(KM_BRANCH_MF(0x801844bc, SceneCreator, IsSceneCommonSound), // Wii Sports - KM_BRANCH_MF(0x80183ef4, SceneCreator, IsSceneCommonSound), // Wii Play - /* not applicable */); // Wii Sports Resort +KOKESHI_BY_PACK( + KM_BRANCH_MF(0x801844bc, SceneCreator, IsSceneCommonSound), // Wii Sports + KM_BRANCH_MF(0x80183ef4, SceneCreator, IsSceneCommonSound), // Wii Play + /* not applicable */); // Wii Sports Resort /** * @brief Creates a new scene by ID @@ -490,9 +538,10 @@ RPSysScene* SceneCreator::Create(s32 id) { pScene->setCreatorSceneID(mLastSceneID); return pScene; } -KOKESHI_BY_PACK(KM_BRANCH_MF(0x80184838, SceneCreator, Create), // Wii Sports - KM_BRANCH_MF(0x80184230, SceneCreator, Create), // Wii Play - KM_BRANCH_MF(0x8022ec90, SceneCreator, Create)); // Wii Sports Resort +KOKESHI_BY_PACK(KM_BRANCH_MF(0x80184838, SceneCreator, Create), // Wii Sports + KM_BRANCH_MF(0x80184230, SceneCreator, Create), // Wii Play + KM_BRANCH_MF(0x8022ec90, SceneCreator, + Create)); // Wii Sports Resort /** * @brief Creates a new system scene by ID diff --git a/lib/libkiwi/core/kiwiSceneCreator.h b/lib/libkiwi/core/kiwiSceneCreator.h index bf90973..775d629 100644 --- a/lib/libkiwi/core/kiwiSceneCreator.h +++ b/lib/libkiwi/core/kiwiSceneCreator.h @@ -1,7 +1,7 @@ #ifndef LIBKIWI_CORE_SCENE_CREATOR_H #define LIBKIWI_CORE_SCENE_CREATOR_H -#include +#include #include #include #include @@ -46,7 +46,7 @@ enum ESceneID { #endif // RPParty - ESceneID_Unknown09, + ESceneID_RPOchScene, //!< THEORY ONLY ESceneID_RPFshScene, ESceneID_RPHkyScene, ESceneID_RPDucScene, @@ -185,14 +185,23 @@ class SceneCreator : public ExtSingletonPtr { static void RegistDebugRoot(s32 id, bool bootUp = true, u16 buttons = EButton_B | EButton_Minus); + /** + * @brief Gets the scene ID of the bootup scene + */ + static s32 GetBootScene(); + /** + * @brief Gets the scene ID of the title scene + */ + static s32 GetTitleScene(); /** * @brief Gets the scene ID of the main menu scene */ static s32 GetMenuScene(); + /** - * @brief Gets the scene ID of the bootup scene + * @brief Gets the scene ID of the previous scene */ - static s32 GetBootScene(); + static s32 GetPrevSceneID(); #if defined(PACK_SPORTS) || defined(PACK_PLAY) /** @@ -215,20 +224,28 @@ class SceneCreator : public ExtSingletonPtr { #endif /** - * @brief Changes to the menu scene + * @brief Changes to the bootup scene * * @return Success */ - bool ChangeMenuScene() { - return ChangeSceneAfterFade(GetMenuScene()); + bool ChangeBootScene() { + return ChangeSceneAfterFade(GetBootScene()); } /** - * @brief Changes to the bootup scene + * @brief Changes to the title scene * * @return Success */ - bool ChangeBootScene() { - return ChangeSceneAfterFade(GetBootScene()); + bool ChangeTitleScene() { + return ChangeSceneAfterFade(GetTitleScene()); + } + /** + * @brief Changes to the menu scene + * + * @return Success + */ + bool ChangeMenuScene() { + return ChangeSceneAfterFade(GetMenuScene()); } /** @@ -367,7 +384,10 @@ class SceneCreator : public ExtSingletonPtr { //! Pack Project scenes static const Info scPackScenes[]; //! User-registered scenes - static TMap sUserScenes; + static THashMap sUserScenes; + + //! Previous scene ID + static s32 sPrevSceneID; //! Root debug menu scene ID static s32 sDebugRootID; diff --git a/lib/libkiwi/core/kiwiSceneHookMgr.cpp b/lib/libkiwi/core/kiwiSceneHookMgr.cpp index 80dc731..8149000 100644 --- a/lib/libkiwi/core/kiwiSceneHookMgr.cpp +++ b/lib/libkiwi/core/kiwiSceneHookMgr.cpp @@ -36,7 +36,7 @@ bool IsCurrentPackScene() { /** * @brief Gets the list of active hooks for the current scene */ -TList& SceneHookMgr::GetSceneHooks() { +TList& SceneHookMgr::GetSceneHooks() { K_ASSERT_EX(IsCurrentPackScene(), "Only game scenes have hooks"); s32 id = RP_GET_INSTANCE(RPSysSceneMgr)->getCurrentSceneID(); return mSceneHookLists[id]; @@ -60,7 +60,7 @@ void SceneHookMgr::AddHook(ISceneHook& rHook) { * * @param rHook Scene hook */ -void SceneHookMgr::RemoveHook(const ISceneHook& rHook) { +void SceneHookMgr::RemoveHook(ISceneHook& rHook) { if (rHook.mSceneID == -1) { mGlobalHooks.Remove(&rHook); } else { @@ -78,13 +78,13 @@ void SceneHookMgr::DoConfigure() { // Global hooks K_FOREACH (it, r.mGlobalHooks) { - it->Configure(GetCurrentScene()); + (*it)->Configure(GetCurrentScene()); } // Hooks for game scene if (IsCurrentPackScene()) { K_FOREACH (it, r.GetSceneHooks()) { - it->Configure(GetCurrentScene()); + (*it)->Configure(GetCurrentScene()); } } } @@ -100,13 +100,13 @@ void SceneHookMgr::DoReset() { // Global hooks K_FOREACH (it, r.mGlobalHooks) { - it->BeforeReset(GetCurrentScene()); + (*it)->BeforeReset(GetCurrentScene()); } // Hooks for game scene if (IsCurrentPackScene()) { K_FOREACH (it, r.GetSceneHooks()) { - it->BeforeReset(GetCurrentScene()); + (*it)->BeforeReset(GetCurrentScene()); } } @@ -114,13 +114,13 @@ void SceneHookMgr::DoReset() { // Global hooks K_FOREACH (it, r.mGlobalHooks) { - it->AfterReset(GetCurrentScene()); + (*it)->AfterReset(GetCurrentScene()); } // Hooks for game scene if (IsCurrentPackScene()) { K_FOREACH (it, r.GetSceneHooks()) { - it->AfterReset(GetCurrentScene()); + (*it)->AfterReset(GetCurrentScene()); } } } @@ -143,13 +143,13 @@ void SceneHookMgr::DoLoadResource() { // Global hooks K_FOREACH (it, r.mGlobalHooks) { - it->LoadResource(GetCurrentScene()); + (*it)->LoadResource(GetCurrentScene()); } // Hooks for game scene if (IsCurrentPackScene()) { K_FOREACH (it, r.GetSceneHooks()) { - it->LoadResource(GetCurrentScene()); + (*it)->LoadResource(GetCurrentScene()); } } } @@ -165,35 +165,33 @@ void SceneHookMgr::DoCalculate() { // Global hooks K_FOREACH (it, r.mGlobalHooks) { - it->BeforeCalculate(GetCurrentScene()); + (*it)->BeforeCalculate(GetCurrentScene()); } // Hooks for game scene if (IsCurrentPackScene()) { K_FOREACH (it, r.GetSceneHooks()) { - it->BeforeCalculate(GetCurrentScene()); + (*it)->BeforeCalculate(GetCurrentScene()); } } - // Run scene logic - RP_GET_INSTANCE(RPSysSceneMgr)->updateState(); - RP_GET_INSTANCE(RPSysSceneMgr)->SceneManager::calcCurrentScene(); + GetCurrentScene()->Calculate(); // Global hooks K_FOREACH (it, r.mGlobalHooks) { - it->AfterCalculate(GetCurrentScene()); + (*it)->AfterCalculate(GetCurrentScene()); } // Hooks for game scene if (IsCurrentPackScene()) { K_FOREACH (it, r.GetSceneHooks()) { - it->AfterCalculate(GetCurrentScene()); + (*it)->AfterCalculate(GetCurrentScene()); } } } -KOKESHI_BY_PACK(KM_BRANCH(0x80185868, SceneHookMgr::DoCalculate), // Wii Sports - KM_BRANCH(0x801851f0, SceneHookMgr::DoCalculate), // Wii Play - KM_BRANCH(0x8023016c, SceneHookMgr::DoCalculate)); // Wii Sports Resort +KOKESHI_BY_PACK(KM_CALL(0x80185110, SceneHookMgr::DoCalculate), // Wii Sports + KM_CALL(0x80184b08, SceneHookMgr::DoCalculate), // Wii Play + KM_CALL(0x8022f870, SceneHookMgr::DoCalculate)); // Wii Sports Resort /** * @brief Runs active hooks and scene function(s) for the Exit state @@ -205,13 +203,13 @@ void SceneHookMgr::DoExit() { // Global hooks K_FOREACH (it, r.mGlobalHooks) { - it->Exit(GetCurrentScene()); + (*it)->Exit(GetCurrentScene()); } // Hooks for game scene if (IsCurrentPackScene()) { K_FOREACH (it, r.GetSceneHooks()) { - it->Exit(GetCurrentScene()); + (*it)->Exit(GetCurrentScene()); } } } @@ -230,19 +228,20 @@ void SceneHookMgr::DoPause() { // Global hooks K_FOREACH (it, r.mGlobalHooks) { - it->Pause(GetCurrentScene(), true); + (*it)->Pause(GetCurrentScene(), true); } // Hooks for game scene if (IsCurrentPackScene()) { K_FOREACH (it, r.GetSceneHooks()) { - it->Pause(GetCurrentScene(), true); + (*it)->Pause(GetCurrentScene(), true); } } } -KOKESHI_BY_PACK(KM_CALL(0x8018cec8, SceneHookMgr::DoPause), // Wii Sports - KM_CALL(0x8018b084, SceneHookMgr::DoPause), // Wii Play - KM_CALL(0x8022fc94, SceneHookMgr::DoPause)); // Wii Sports Resort +KOKESHI_BY_PACK(KM_CALL(0x8018cec8, SceneHookMgr::DoPause), // Wii Sports + KM_CALL(0x8018b084, SceneHookMgr::DoPause), // Wii Play + KM_CALL(0x8022fc94, + SceneHookMgr::DoPause)); // Wii Sports Resort /** * @brief Runs active hooks and scene function(s) for exiting the pause menu @@ -254,27 +253,28 @@ void SceneHookMgr::DoUnPause() { // Global hooks K_FOREACH (it, r.mGlobalHooks) { - it->Pause(GetCurrentScene(), false); + (*it)->Pause(GetCurrentScene(), false); } // Hooks for game scene if (IsCurrentPackScene()) { K_FOREACH (it, r.GetSceneHooks()) { - it->Pause(GetCurrentScene(), false); + (*it)->Pause(GetCurrentScene(), false); } } } // 'Continue' -KOKESHI_BY_PACK(KM_CALL(0x8018d118, SceneHookMgr::DoUnPause), // Wii Sports - KM_CALL(0x8018b174, SceneHookMgr::DoUnPause), // Wii Play - KM_CALL(0x8022fc38, SceneHookMgr::DoUnPause)); // Wii Sports Resort +KOKESHI_BY_PACK(KM_CALL(0x8018d118, SceneHookMgr::DoUnPause), // Wii Sports + KM_CALL(0x8018b174, SceneHookMgr::DoUnPause), // Wii Play + KM_CALL(0x8022fc38, + SceneHookMgr::DoUnPause)); // Wii Sports Resort // 'Start over' -KOKESHI_BY_PACK(KM_CALL(0x8018d14c, SceneHookMgr::DoUnPause), // Wii Sports - KM_CALL(0x8018b1a8, SceneHookMgr::DoUnPause), // Wii Play +KOKESHI_BY_PACK(KM_CALL(0x8018d14c, SceneHookMgr::DoUnPause), // Wii Sports + KM_CALL(0x8018b1a8, SceneHookMgr::DoUnPause), // Wii Play /* WS2 only needs one patch */); // Wii Sports Resort // 'Quit' -KOKESHI_BY_PACK(KM_CALL(0x8018d1b8, SceneHookMgr::DoUnPause), // Wii Sports - KM_CALL(0x8018b20c, SceneHookMgr::DoUnPause), // Wii Play +KOKESHI_BY_PACK(KM_CALL(0x8018d1b8, SceneHookMgr::DoUnPause), // Wii Sports + KM_CALL(0x8018b20c, SceneHookMgr::DoUnPause), // Wii Play /* WS2 only needs one patch */); // Wii Sports Resort } // namespace kiwi diff --git a/lib/libkiwi/core/kiwiSceneHookMgr.h b/lib/libkiwi/core/kiwiSceneHookMgr.h index 3478370..2d8211d 100644 --- a/lib/libkiwi/core/kiwiSceneHookMgr.h +++ b/lib/libkiwi/core/kiwiSceneHookMgr.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include namespace kiwi { @@ -32,7 +32,7 @@ class SceneHookMgr : public StaticSingleton { * * @param rHook Scene hook */ - void RemoveHook(const ISceneHook& rHook); + void RemoveHook(ISceneHook& rHook); private: LIBKIWI_KAMEK_PUBLIC @@ -71,13 +71,13 @@ class SceneHookMgr : public StaticSingleton { /** * @brief Gets the list of active hooks for the current scene */ - TList& GetSceneHooks(); + TList& GetSceneHooks(); private: //! Lists of scene hooks - TArray, ESceneID_Max> mSceneHookLists; + TArray, ESceneID_Max> mSceneHookLists; //! Global hooks (always active) - TList mGlobalHooks; + TList mGlobalHooks; }; /** diff --git a/lib/libkiwi/core/kiwiStaticMem.cpp b/lib/libkiwi/core/kiwiStaticMem.cpp new file mode 100644 index 0000000..fba60d8 --- /dev/null +++ b/lib/libkiwi/core/kiwiStaticMem.cpp @@ -0,0 +1,47 @@ +#include + +namespace kiwi { + +/** + * @brief Sets the value of a static variable + * + * @param index Variable index + * @param value Variable value + */ +void StaticMem::SetVariable(u32 index, u32 value) { + K_ASSERT(index < NUM_VARIABLE); + mVariables[index] = value; +} + +/** + * @brief Clears the value of a static variable + * + * @param index Variable index + */ +void StaticMem::ClearVariable(u32 index) { + K_ASSERT(index < NUM_VARIABLE); + mVariables[index].Reset(); +} + +/** + * @brief Gets the value of a static variable + * + * @param index Variable index + */ +Optional StaticMem::GetVariable(u32 index) const { + K_ASSERT(index < NUM_VARIABLE); + return mVariables[index]; +} + +/** + * @brief Tests whether a static variable has been set + * + * @param index Variable index + * @return Whether it has been given a value + */ +bool StaticMem::IsVariableSet(u32 index) const { + K_ASSERT(index < NUM_VARIABLE); + return mVariables[index].HasValue(); +} + +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/core/kiwiStaticMem.h b/lib/libkiwi/core/kiwiStaticMem.h new file mode 100644 index 0000000..5feeb67 --- /dev/null +++ b/lib/libkiwi/core/kiwiStaticMem.h @@ -0,0 +1,61 @@ +#ifndef LIBKIWI_CORE_STATIC_MEM_H +#define LIBKIWI_CORE_STATIC_MEM_H +#include +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_core +//! @{ + +/** + * @brief Static-lifetime variable storage + */ +class StaticMem : public StaticSingleton { + friend class StaticSingleton; + +public: + //! Number of static variables + static const u32 NUM_VARIABLE = 256; + +public: + /** + * @brief Sets the value of a static variable + * + * @param index Variable index + * @param value Variable value + */ + void SetVariable(u32 index, u32 value); + + /** + * @brief Clears the value of a static variable + * + * @param index Variable index + */ + void ClearVariable(u32 index); + + /** + * @brief Gets the value of a static variable + * + * @param index Variable index + */ + Optional GetVariable(u32 index) const; + + /** + * @brief Tests whether a static variable has been set + * + * @param index Variable index + * @return Whether it has been given a value + */ + bool IsVariableSet(u32 index) const; + +private: + //! Static variables + Optional mVariables[NUM_VARIABLE]; +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/core/kiwiThreadImpl.hpp b/lib/libkiwi/core/kiwiThreadImpl.hpp index f16a4c1..2403b59 100644 --- a/lib/libkiwi/core/kiwiThreadImpl.hpp +++ b/lib/libkiwi/core/kiwiThreadImpl.hpp @@ -57,7 +57,7 @@ Thread::Thread(TRet (*pFunc)(Thread::Param), Thread::Param pArg) { */ template Thread::Thread(TRet (TClass::*pFunc)(), TClass& rObj) { - K_ASSERT_PTR(pFunc); + K_ASSERT(pFunc); SetMemberFunction(pFunc, rObj); Start(); @@ -73,7 +73,7 @@ Thread::Thread(TRet (TClass::*pFunc)(), TClass& rObj) { template Thread::Thread(TRet (TClass::*pFunc)(Thread::Param), TClass& rObj, Thread::Param pArg) { - K_ASSERT_PTR(pFunc); + K_ASSERT(pFunc); SetMemberFunction(pFunc, rObj); SetGPR(4, BitCast(pArg)); @@ -93,7 +93,7 @@ Thread::Thread(TRet (TClass::*pFunc)(Thread::Param), TClass& rObj, */ template Thread::Thread(TRet (TClass::*pFunc)() const, const TClass& rObj) { - K_ASSERT_PTR(pFunc); + K_ASSERT(pFunc); SetMemberFunction(pFunc, rObj); Start(); @@ -109,7 +109,7 @@ Thread::Thread(TRet (TClass::*pFunc)() const, const TClass& rObj) { template Thread::Thread(TRet (TClass::*pFunc)(Thread::Param) const, const TClass& rObj, Thread::Param pArg) { - K_ASSERT_PTR(pFunc); + K_ASSERT(pFunc); SetMemberFunction(pFunc, rObj); SetGPR(4, BitCast(pArg)); diff --git a/lib/libkiwi/crypt/kiwiSHA1.cpp b/lib/libkiwi/crypt/kiwiSHA1.cpp index 2b2d322..7883ef5 100644 --- a/lib/libkiwi/crypt/kiwiSHA1.cpp +++ b/lib/libkiwi/crypt/kiwiSHA1.cpp @@ -27,6 +27,8 @@ String SHA1::Finalize() { digest[i * 2 + 0] = sHexDigits[(buffer[i] & 0xF0) >> 8]; digest[i * 2 + 1] = sHexDigits[(buffer[i] & 0x0F) >> 0]; } + + return digest; } namespace detail { diff --git a/lib/libkiwi/debug/kiwiAssert.cpp b/lib/libkiwi/debug/kiwiAssert.cpp index f36fc76..d0708c8 100644 --- a/lib/libkiwi/debug/kiwiAssert.cpp +++ b/lib/libkiwi/debug/kiwiAssert.cpp @@ -12,14 +12,14 @@ * @param ... Format string arguments */ void kiwi_log(const char* pMsg, ...) { - char msgbuf[1024]; + char msgBuf[1024]; std::va_list list; va_start(list, pMsg); - std::vsnprintf(msgbuf, sizeof(msgbuf), pMsg, list); + std::vsnprintf(msgBuf, sizeof(msgBuf), pMsg, list); va_end(list); - OSReport(msgbuf); + OSReport(msgBuf); } /** @@ -31,14 +31,43 @@ void kiwi_log(const char* pMsg, ...) { * @param ... Format string arguments */ void kiwi_fail_assert(const char* pFile, int line, const char* pMsg, ...) { - char msgbuf[1024]; + static bool firstTime = true; + + char msgBuf[1024]; std::va_list list; va_start(list, pMsg); - std::vsnprintf(msgbuf, sizeof(msgbuf), pMsg, list); + std::vsnprintf(msgBuf, sizeof(msgBuf), pMsg, list); va_end(list); - kiwi::Nw4rException::GetInstance().FailAssert(pFile, line, msgbuf); + // Stuck in an assertion loop if this is not our first time + bool recursive = !firstTime; + // Early enough assertion can happen before the handler is created + bool noHandler = !kiwi::Nw4rException::IsCreateInstance(); + + // Need to avoid using Nw4rException when it could recurse/OOM + if (recursive || noHandler) { + char fatalBuf[2048]; + + std::snprintf(fatalBuf, sizeof(fatalBuf), // + "******** ASSERTION FAILED! ********\n" // + "%s\n" // + "Source: %s(%d)\n", // + msgBuf, pFile, line); + + if (recursive) { + std::strncat(fatalBuf, "(Recursive assertion)\n", sizeof(fatalBuf)); + } else { + std::strncat(fatalBuf, "(Before exception handler created)\n", + sizeof(fatalBuf)); + } + + OSFatal(kiwi::Color(kiwi::Color::WHITE), kiwi::Color(kiwi::Color::BLUE), + fatalBuf); + } + + firstTime = false; + kiwi::Nw4rException::GetInstance().FailAssert(pFile, line, msgBuf); } // Catch EGG_ASSERT KOKESHI_BY_PACK(KM_BRANCH(0x800a1f08, kiwi_fail_assert), // Wii Sports diff --git a/lib/libkiwi/debug/kiwiAssert.h b/lib/libkiwi/debug/kiwiAssert.h index fffdeb8..6559266 100644 --- a/lib/libkiwi/debug/kiwiAssert.h +++ b/lib/libkiwi/debug/kiwiAssert.h @@ -30,11 +30,16 @@ //! Assert that the pointer falls into a valid memory region #define ASSERT_PTR(exp) K_ASSERT_PTR(exp) +//! Assert that the pointer falls into a valid memory region +#define ASSERT_PTR_EX(exp, ...) K_ASSERT_PTR_EX(exp, __VA_ARGS__) + //! Assert that the floating-point value is a finite, non-NaN value #define ASSERT_FP(exp) K_ASSERT_FP(exp) //! Assert that a code path is unreachable #define UNREACHABLE() K_UNREACHABLE() +//! Denote a function as not implemented +#define NOT_IMPLEMENTED() K_NOT_IMPLEMENTED() //! Compile-time assertion #define STATIC_ASSERT(exp) K_STATIC_ASSERT(exp) @@ -70,11 +75,14 @@ //! Assert that the pointer falls into a valid memory region #define K_ASSERT_PTR(exp) \ K_ASSERT_EX(kiwi::PtrUtil::IsPointer(exp), \ - "%s is not a valid pointer (=0x%08X)", #exp, exp) + #exp " is not a valid pointer (=0x%08X)", exp) +//! Assert that the pointer falls into a valid memory region +#define K_ASSERT_PTR_EX(exp, ...) \ + K_ASSERT_EX(kiwi::PtrUtil::IsPointer(exp), __VA_ARGS__) //! Assert that the floating-point value is a finite, non-NaN value #define K_ASSERT_FP(exp) \ - K_ASSERT_EX(isfinite(exp) && !isnan(exp), "%s is infinite or nan", #exp) + K_ASSERT_EX(isfinite(exp) && !isnan(exp), #exp " is infinite or nan") //! Assert that a code path is unreachable #define K_UNREACHABLE() K_ASSERT_EX(false, "Unreachable code") diff --git a/lib/libkiwi/debug/kiwiDebugMenu.cpp b/lib/libkiwi/debug/kiwiDebugMenu.cpp index 34448d6..6eaf30e 100644 --- a/lib/libkiwi/debug/kiwiDebugMenu.cpp +++ b/lib/libkiwi/debug/kiwiDebugMenu.cpp @@ -17,7 +17,7 @@ EDebugMenuResult DebugMenu::Calculate() { return EDebugMenuResult_None; } - EDebugMenuResult result = mPageStack.Top().Calculate(); + EDebugMenuResult result = mPageStack.Top()->Calculate(); if (result == EDebugMenuResult_Back) { if (mPageStack.Size() > 1) { @@ -39,7 +39,7 @@ void DebugMenu::UserDraw() { return; } - mPageStack.Top().UserDraw(); + mPageStack.Top()->UserDraw(); } /****************************************************************************** @@ -76,7 +76,7 @@ EDebugMenuResult DebugPage::Calculate() { K_ASSERT(0 <= mCursor && mCursor < mOptions.Size()); DebugOptionBase* pOption = mOptions[mCursor]; - K_ASSERT(pOption != nullptr); + K_ASSERT_PTR(pOption); // Change option with Left/Right if (rCtrl.IsTrig(EButton_Right)) { @@ -96,6 +96,8 @@ EDebugMenuResult DebugPage::Calculate() { return EDebugMenuResult_Back; } } + + return EDebugMenuResult_None; } /** diff --git a/lib/libkiwi/debug/kiwiDebugMenu.h b/lib/libkiwi/debug/kiwiDebugMenu.h index 9e8d1ef..051991c 100644 --- a/lib/libkiwi/debug/kiwiDebugMenu.h +++ b/lib/libkiwi/debug/kiwiDebugMenu.h @@ -58,7 +58,7 @@ class DebugMenu : public IRPGrpDrawObject { protected: //! Menu page hierarchy - TStack mPageStack; + TStack mPageStack; }; /** diff --git a/lib/libkiwi/debug/kiwiDebugOption.cpp b/lib/libkiwi/debug/kiwiDebugOption.cpp index 12138f1..395f39b 100644 --- a/lib/libkiwi/debug/kiwiDebugOption.cpp +++ b/lib/libkiwi/debug/kiwiDebugOption.cpp @@ -216,7 +216,7 @@ EDebugMenuResult DebugProcOption::Select() { } if (mpCallback != nullptr) { - return mpCallback(mpCallbackArg); + return mpCallback(this, mpCallbackArg); } return EDebugMenuResult_None; @@ -231,9 +231,11 @@ EDebugMenuResult DebugProcOption::Select() { /** * @brief Opens the specified sub-page * + * @param pInvoker Callback invoker * @param pArg Callback user argument */ -EDebugMenuResult DebugOpenPageOption::OpenPageProc(void* pArg) { +EDebugMenuResult DebugOpenPageOption::OpenPageProc(DebugOptionBase* pInvoker, + void* pArg) { K_ASSERT_PTR(pArg); DebugOpenPageOption* p = static_cast(pArg); diff --git a/lib/libkiwi/debug/kiwiDebugOption.h b/lib/libkiwi/debug/kiwiDebugOption.h index 1457fdf..f381592 100644 --- a/lib/libkiwi/debug/kiwiDebugOption.h +++ b/lib/libkiwi/debug/kiwiDebugOption.h @@ -7,6 +7,17 @@ namespace kiwi { //! @addtogroup libkiwi_debug //! @{ +/** + * @brief Debug menu user data storage type + */ +typedef void* DebugUserData; + +/****************************************************************************** + * + * DebugOptionBase + * + ******************************************************************************/ + /** * @brief Basic debug menu option */ @@ -15,10 +26,12 @@ class DebugOptionBase { /** * @brief Callback function for option selection * + * @param pInvoker Callback invoker * @param pArg Callback user argument * @return Action result */ - typedef EDebugMenuResult (*SelectCallback)(void* pArg); + typedef EDebugMenuResult (*SelectCallback)(DebugOptionBase* pInvoker, + void* pArg); /** * @brief Option type @@ -118,6 +131,21 @@ class DebugOptionBase { */ void SetEnabled(bool enable); + /** + * @brief Gets the user's stored data + */ + DebugUserData GetUserData() const { + return mUserData; + } + /** + * @brief Sets the user's stored data + * + * @param userData User data + */ + void SetUserData(DebugUserData userData) { + mUserData = userData; + } + protected: /** * @brief Validates the option value @@ -140,8 +168,17 @@ class DebugOptionBase { String mName; //! Option value String mValueText; + + //! User data storage + DebugUserData mUserData; }; +/****************************************************************************** + * + * DebugIntOption + * + ******************************************************************************/ + /** * @brief Debug menu option with an integer value */ @@ -257,6 +294,12 @@ class DebugIntOption : public DebugOptionBase { int mValue; }; +/****************************************************************************** + * + * DebugBoolOption + * + ******************************************************************************/ + /** * @brief Debug option with a boolean value */ @@ -297,6 +340,12 @@ class DebugBoolOption : public DebugIntOption { virtual void UpdateString(); }; +/****************************************************************************** + * + * DebugEnumOption + * + ******************************************************************************/ + /** * @brief Debug option with an enum value */ @@ -360,6 +409,12 @@ class DebugEnumOption : public DebugIntOption { const char** mppValues; }; +/****************************************************************************** + * + * DebugProcOption + * + ******************************************************************************/ + /** * @brief Debug option with procedure */ @@ -406,6 +461,12 @@ class DebugProcOption : public DebugOptionBase { void* mpCallbackArg; }; +/****************************************************************************** + * + * DebugOpenPageOption + * + ******************************************************************************/ + /** * @brief Debug option which opens a new page */ @@ -443,9 +504,10 @@ class DebugOpenPageOption : public DebugProcOption { /** * @brief Opens the specified sub-page * + * @param pInvoker Callback invoker * @param pArg Callback user argument */ - static EDebugMenuResult OpenPageProc(void* pArg); + static EDebugMenuResult OpenPageProc(DebugOptionBase* pInvoker, void* pArg); private: //! Sub-page to open diff --git a/lib/libkiwi/debug/kiwiMapFile.cpp b/lib/libkiwi/debug/kiwiMapFile.cpp index 0091686..22c19bd 100644 --- a/lib/libkiwi/debug/kiwiMapFile.cpp +++ b/lib/libkiwi/debug/kiwiMapFile.cpp @@ -49,11 +49,11 @@ void MapFile::Open(const String& rPath, ELinkType type) { * @brief Closes map file */ void MapFile::Close() { - TList::Iterator it = mSymbols.Begin(); - for (; it != mSymbols.End(); it++) { - TList::Iterator next = it++; + TList::Iterator it = mSymbols.Begin(); + while (it != mSymbols.End()) { + TList::Iterator next = it++; mSymbols.Erase(next); - delete &*next; + delete *next; } delete mpMapBuffer; @@ -72,17 +72,17 @@ const MapFile::Symbol* MapFile::QueryTextSymbol(const void* pAddr) const { return nullptr; } - TList::ConstIterator it = mSymbols.Begin(); + TList::ConstIterator it = mSymbols.Begin(); for (; it != mSymbols.End(); it++) { // Resolve the symbol's address const void* pResolved = - it->type == ELinkType_Static - ? it->pAddr - : AddToPtr(GetModuleTextStart(), it->offset); + (*it)->type == ELinkType_Static + ? (*it)->pAddr + : AddToPtr(GetModuleTextStart(), (*it)->offset); // Determine if the specified address falls within the symbol - if (PtrDistance(pResolved, pAddr) < it->size) { - return &*it; + if (PtrDistance(pResolved, pAddr) < (*it)->size) { + return *it; } } diff --git a/lib/libkiwi/debug/kiwiMapFile.h b/lib/libkiwi/debug/kiwiMapFile.h index 3d8e2f5..ce854f7 100644 --- a/lib/libkiwi/debug/kiwiMapFile.h +++ b/lib/libkiwi/debug/kiwiMapFile.h @@ -1,7 +1,7 @@ #ifndef LIBKIWI_DEBUG_MAP_FILE_H #define LIBKIWI_DEBUG_MAP_FILE_H #include -#include +#include #include namespace kiwi { @@ -80,10 +80,10 @@ class MapFile : public DynamicSingleton { void Unpack(); private: - ELinkType mLinkType; //!< Linkage type - char* mpMapBuffer; //!< Text buffer - bool mIsUnpacked; //!< Whether the map has been unpacked - TList mSymbols; //!< Map symbols + ELinkType mLinkType; //!< Linkage type + char* mpMapBuffer; //!< Text buffer + bool mIsUnpacked; //!< Whether the map has been unpacked + TList mSymbols; //!< Map symbols }; //! @} diff --git a/lib/libkiwi/debug/kiwiNw4rDirectPrint.cpp b/lib/libkiwi/debug/kiwiNw4rDirectPrint.cpp index f460200..46e828c 100644 --- a/lib/libkiwi/debug/kiwiNw4rDirectPrint.cpp +++ b/lib/libkiwi/debug/kiwiNw4rDirectPrint.cpp @@ -36,7 +36,7 @@ void* CreateFB(const GXRenderModeObj* pRmo) { // Try using heap, but be careful to not throw a nested exception void* pXfb = nullptr; if (MemoryMgr::GetInstance().GetFreeSize(EMemory_MEM1) > size) { - pXfb = new (32) u8[size]; + pXfb = new (32, EMemory_MEM1) u8[size]; } // Force allocation from OS arena diff --git a/lib/libkiwi/debug/kiwiNw4rException.cpp b/lib/libkiwi/debug/kiwiNw4rException.cpp index de84175..49a163c 100644 --- a/lib/libkiwi/debug/kiwiNw4rException.cpp +++ b/lib/libkiwi/debug/kiwiNw4rException.cpp @@ -313,10 +313,15 @@ void Nw4rException::PrintHeapInfo() { OS_MEM_B_TO_KB(static_cast( MemoryMgr::GetInstance().GetFreeSize(EMemory_MEM2)))); - Printf("RPSysSystem: %.2f KB free\n", + Printf("RPSysSystem (System): %.2f KB free\n", OS_MEM_B_TO_KB(static_cast( RPSysSystem::getSystemHeap()->getAllocatableSize()))); + Printf("RPSysSystem (Resource): %.2f KB free\n", + OS_MEM_B_TO_KB(static_cast(RP_GET_INSTANCE(RPSysSystem) + ->getResourceHeap() + ->getAllocatableSize()))); + Printf("\n"); } @@ -328,6 +333,7 @@ void Nw4rException::PrintBuildInfo() { Printf("%s\n", GetBuildDate()); Printf("%s (%s)\n", GetBuildPack(), GetBuildTarget()); + Printf("Commit %s\n", GetGitCommitHash()); Printf("\n"); } diff --git a/lib/libkiwi/debug/kiwiTextBuilder.cpp b/lib/libkiwi/debug/kiwiTextBuilder.cpp index d7da8e4..f550fab 100644 --- a/lib/libkiwi/debug/kiwiTextBuilder.cpp +++ b/lib/libkiwi/debug/kiwiTextBuilder.cpp @@ -118,7 +118,7 @@ template void TextImpl::Print() { } default: { - K_ASSERT(false); + K_UNREACHABLE(); break; } } diff --git a/lib/libkiwi/debug/kiwiTextWriter.cpp b/lib/libkiwi/debug/kiwiTextWriter.cpp index 78e56a2..a167473 100644 --- a/lib/libkiwi/debug/kiwiTextWriter.cpp +++ b/lib/libkiwi/debug/kiwiTextWriter.cpp @@ -14,7 +14,7 @@ namespace kiwi { TextWriter::TextWriter() : mIsRendering(false), mOldDrawFlags(0) { #if defined(PACK_SPORTS) || defined(PACK_PLAY) - bool success = SetResFont(EResFont_nRodDb_32_IA4); + bool success = SetResFont(EResFont_nRodEb_32_I4); #elif defined(PACK_RESORT) bool success = SetResFont(EResFont_nRodB_32_IA4); #endif @@ -33,7 +33,7 @@ bool TextWriter::SetResFont(EResFont font) { K_ASSERT(font < EResFont_Max); const nw4r::ut::Font* pFont = FontMgr::GetInstance().GetResFont(font); - K_ASSERT(pFont != nullptr); + K_ASSERT_PTR(pFont); return SetFont(*pFont); } @@ -47,7 +47,7 @@ bool TextWriter::SetResFont(EResFont font) { */ bool TextWriter::SetResFont(const String& rName) { const nw4r::ut::Font* pFont = FontMgr::GetInstance().GetResFont(rName); - K_ASSERT(pFont != nullptr); + K_ASSERT_PTR(pFont); return SetFont(*pFont); } diff --git a/lib/libkiwi/fun/kiwiChip8.cpp b/lib/libkiwi/fun/kiwiChip8.cpp new file mode 100644 index 0000000..93b4869 --- /dev/null +++ b/lib/libkiwi/fun/kiwiChip8.cpp @@ -0,0 +1,1092 @@ +#include + +#include + +#include + +#include + +namespace kiwi { +namespace chip8 { +namespace { + +/** + * @brief Converts a color to the packed RGBA565 format + * + * @param c RGBA color + * @return RGBA565 encoded color + */ +u16 ColorToRgba565(Color c) { + u8 r = c.r >> 3; + u8 g = c.g >> 2; + u8 b = c.b >> 3; + return r << 11 | g << 5 | b; +} + +} // namespace + +/****************************************************************************** + * + * IFont + * + ******************************************************************************/ + +/** + * @brief Gets the size of the font sprite data + */ +const u32 IFont::GetSpriteDataSize() { + K_ASSERT(GetMaxChar() >= GetMinChar()); + + u32 range = GetMaxChar() - GetMinChar() + 1; + u32 oneSize = GetCharWidth() * GetCharHeight() * GetBitDepth(); + + return range * oneSize; +} + +/****************************************************************************** + * + * DefaultFont + * + ******************************************************************************/ + +/** + * @brief Font sprite data + */ +const u8 DefaultFont::scSpriteData[] = { + 0b11110000, // **** + 0b10010000, // * * + 0b10010000, // * * + 0b10010000, // * * + 0b11110000, // **** + + 0b00100000, // * + 0b01100000, // ** + 0b00100000, // * + 0b00100000, // * + 0b01110000, // *** + + 0b11110000, // **** + 0b00010000, // * + 0b11110000, // **** + 0b10000000, // * + 0b11110000, // **** + + 0b11110000, // **** + 0b00010000, // * + 0b11110000, // **** + 0b00010000, // * + 0b11110000, // **** + + 0b10010000, // * * + 0b10010000, // * * + 0b11110000, // **** + 0b00010000, // * + 0b00010000, // * + + 0b11110000, // **** + 0b10000000, // * + 0b11110000, // **** + 0b00010000, // * + 0b11110000, // **** + + 0b11110000, // **** + 0b10000000, // * + 0b11110000, // **** + 0b10010000, // * * + 0b11110000, // **** + + 0b11110000, // **** + 0b00010000, // * + 0b00100000, // * + 0b01000000, // * + 0b01000000, // * + + 0b11110000, // **** + 0b10010000, // * * + 0b11110000, // **** + 0b10010000, // * * + 0b11110000, // **** + + 0b11110000, // **** + 0b10010000, // * * + 0b11110000, // **** + 0b00010000, // * + 0b11110000, // **** + + 0b11110000, // **** + 0b10010000, // * * + 0b11110000, // **** + 0b10010000, // * * + 0b10010000, // * * + + 0b11100000, // *** + 0b10010000, // * * + 0b11100000, // *** + 0b10010000, // * * + 0b11100000, // *** + + 0b11110000, // **** + 0b10000000, // * + 0b10000000, // * + 0b10000000, // * + 0b11110000, // **** + + 0b11100000, // *** + 0b10010000, // * * + 0b10010000, // * * + 0b10010000, // * * + 0b11100000, // *** + + 0b11110000, // **** + 0b10000000, // * + 0b11110000, // **** + 0b10000000, // * + 0b11110000, // **** + + 0b11110000, // **** + 0b10000000, // * + 0b11110000, // **** + 0b10000000, // * + 0b10000000, // * +}; + +/****************************************************************************** + * + * GXRenderer + * + ******************************************************************************/ + +/** + * @brief Constructor + */ +GXRenderer::GXRenderer() + : mpTexture(nullptr), mpPalette(nullptr), mTextureSize(0) { + + // 16-bit color + mpPalette = new (32) u8[sizeof(u16) * 2]; + K_ASSERT_PTR(mpPalette); +} + +/** + * @brief Destructor + */ +GXRenderer::~GXRenderer() { + delete[] mpTexture; + mpTexture = nullptr; + + delete[] mpPalette; + mpPalette = nullptr; +} + +/** + * @brief Draws the emulator framebuffer + * + * @param rArg Rendering context + */ +void GXRenderer::Draw(const IRenderer::Arg& rArg) { + K_ASSERT_PTR(rArg.pBuffer); + + CreateTexture(rArg); + CreatePalette(rArg); + + // Screen texture uses palette/color index due to simplicity + GXInitTexObjCI(&mTexObj, mpTexture, rArg.width, rArg.height, + static_cast(GX_TF_C8), GX_CLAMP, GX_CLAMP, + GX_FALSE, GX_TLUT0); + GXLoadTexObj(&mTexObj, GX_TEXMAP0); + + // Palette is RGB565 because we don't need alpha + GXInitTlutObj(&mTlutObj, mpPalette, GX_TL_RGB565, PALETTE_ENTRY_NUM); + GXLoadTlut(&mTlutObj, GX_TLUT0); + + EGG::DrawGX::BeginDrawQuad(EGG::DrawGX::COLORCHAN_COLOR, + EGG::DrawGX::ZMODE_ALWAYS, + EGG::DrawGX::BLEND_NORMAL, true, false); + + EGG::Matrix34f ident; + ident.makeIdentity(); + EGG::DrawGX::DrawDLWorld(EGG::DrawGX::DL_QUAD_TEXTURE, ident); +} + +/** + * @brief Creates CI8 texture data from the Chip-8 framebuffer + * + * @param rArg Rendering context + */ +void GXRenderer::CreateTexture(const Arg& rArg) { + K_ASSERT_PTR(rArg.pBuffer); + K_ASSERT(rArg.width % CI8_BLOCK_WIDTH == 0); + K_ASSERT(rArg.height % CI8_BLOCK_HEIGHT == 0); + + // Textures are stored in blocks so we must round up to the nearest + u32 textureWidth = RoundUp(rArg.width, CI8_BLOCK_WIDTH); + u32 textureHeight = RoundUp(rArg.width, CI8_BLOCK_HEIGHT); + u32 textureSize = textureWidth * textureHeight; + + // Number of 8x8 blocks required to encode the texture + u32 blocksPerRow = textureWidth / CI8_BLOCK_WIDTH; + u32 blocksPerCol = textureHeight / CI8_BLOCK_HEIGHT; + + // Need to realloc to fit the screen texture + if (mpTexture == nullptr || textureSize > mTextureSize) { + delete[] mpTexture; + mpTexture = new (32) u8[textureSize]; + mTextureSize = textureSize; + } + + K_ASSERT_PTR(mpTexture); + K_ASSERT(textureSize <= mTextureSize); + + // Clear with the OFF color + std::memset(mpTexture, 0, mTextureSize); + + for (u32 y = 0; y < rArg.height; y++) { + for (u32 x = 0; x < rArg.width; x++) { + + // "Source" position inside framebuffer + u32 src = // + y * rArg.width + // + x; + + // "Desintation" position inside texture + u32 dst = // + (y + y % CI8_BLOCK_HEIGHT) * rArg.width + // + (x + x % CI8_BLOCK_WIDTH); + + // On/off pixels use the 1/0 palette entries, respectively + mpTexture[dst] = rArg.pBuffer[src] ? 1 : 0; + } + } + + K_LOG_EX("bufferData: %p, bufferSize: %08X\n", rArg.pBuffer, + rArg.width * rArg.height); + K_LOG_EX("texData: %p, texSize: %08X\n", mpTexture, mTextureSize); + K_LOG_EX("plttData: %p, plttSize: %08X\n", mpPalette, sizeof(u16) * 2); +} + +/** + * @brief Creates RGB565 palette data from the Chip-8 framebuffer + * + * @param rArg Rendering context + */ +void GXRenderer::CreatePalette(const Arg& rArg) { + reinterpret_cast(mpPalette)[0] = ColorToRgba565(rArg.off); + reinterpret_cast(mpPalette)[1] = ColorToRgba565(rArg.on); +} + +/****************************************************************************** + * + * System + * + ******************************************************************************/ + +/** + * @brief Opcode group handler functions + */ +const System::OpcodeFunc System::scOpcodeGroupFuncs[] = { + /* 0x0XXX */ &System::Opcode_0XXX, + /* 0x1XXX */ &System::Opcode_JP_NNN, + /* 0x2XXX */ &System::Opcode_CALL_NNN, + /* 0x3XXX */ &System::Opcode_SE_VX_KK, + /* 0x4XXX */ &System::Opcode_SNE_VX_KK, + /* 0x5XXX */ &System::Opcode_SE_VX_VY, + /* 0x6XXX */ &System::Opcode_LD_VX_KK, + /* 0x7XXX */ &System::Opcode_ADD_VX_KK, + /* 0x8XXX */ &System::Opcode_8XXX, + /* 0x9XXX */ &System::Opcode_SNE_VX_VY, + /* 0xAXXX */ &System::Opcode_LD_I_NNN, + /* 0xBXXX */ &System::Opcode_JP_V0_NNN, + /* 0xCXXX */ &System::Opcode_RND, + /* 0xDXXX */ &System::Opcode_DRW, + /* 0xEXXX */ &System::Opcode_EXXX, + /* 0xFXXX */ &System::Opcode_FXXX, +}; + +/** + * @brief Keyboard button map + */ +const u32 System::scButtonMap[] = { + EButton_Left, // 0x00 + EButton_Right, // 0x01 + EButton_Down, // 0x02 + EButton_Up, // 0x03 + EButton_A, // 0x04 + EButton_B, // 0x05 + EButton_1, // 0x06 + EButton_2, // 0x07 + EButton_Plus, // 0x08 + EButton_Minus, // 0x09 +}; + +/** + * @brief Corax+ test ROM + */ +const u8 System::scTestRom[] = { + 0x12, 0x0A, 0x60, 0x01, 0x00, 0xEE, 0x60, 0x02, 0x12, 0xA6, 0x00, 0xE0, + 0x68, 0x32, 0x6B, 0x1A, 0xA4, 0xF1, 0xD8, 0xB4, 0x68, 0x3A, 0xA4, 0xF5, + 0xD8, 0xB4, 0x68, 0x02, 0x69, 0x06, 0x6A, 0x0B, 0x6B, 0x01, 0x65, 0x2A, + 0x66, 0x2B, 0xA4, 0xB5, 0xD8, 0xB4, 0xA4, 0xED, 0xD9, 0xB4, 0xA4, 0xA5, + 0x36, 0x2B, 0xA4, 0xA1, 0xDA, 0xB4, 0x6B, 0x06, 0xA4, 0xB9, 0xD8, 0xB4, + 0xA4, 0xED, 0xD9, 0xB4, 0xA4, 0xA1, 0x45, 0x2A, 0xA4, 0xA5, 0xDA, 0xB4, + 0x6B, 0x0B, 0xA4, 0xBD, 0xD8, 0xB4, 0xA4, 0xED, 0xD9, 0xB4, 0xA4, 0xA1, + 0x55, 0x60, 0xA4, 0xA5, 0xDA, 0xB4, 0x6B, 0x10, 0xA4, 0xC5, 0xD8, 0xB4, + 0xA4, 0xED, 0xD9, 0xB4, 0xA4, 0xA1, 0x76, 0xFF, 0x46, 0x2A, 0xA4, 0xA5, + 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xCD, 0xD8, 0xB4, 0xA4, 0xED, 0xD9, 0xB4, + 0xA4, 0xA1, 0x95, 0x60, 0xA4, 0xA5, 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xAD, + 0xD8, 0xB4, 0xA4, 0xED, 0xD9, 0xB4, 0xA4, 0xA5, 0x12, 0x90, 0xA4, 0xA1, + 0xDA, 0xB4, 0x68, 0x12, 0x69, 0x16, 0x6A, 0x1B, 0x6B, 0x01, 0xA4, 0xB1, + 0xD8, 0xB4, 0xA4, 0xED, 0xD9, 0xB4, 0x60, 0x00, 0x22, 0x02, 0xA4, 0xA5, + 0x40, 0x00, 0xA4, 0xA1, 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xA9, 0xD8, 0xB4, + 0xA4, 0xE1, 0xD9, 0xB4, 0xA4, 0xA5, 0x40, 0x02, 0xA4, 0xA1, 0x30, 0x00, + 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xC9, 0xD8, 0xB4, 0xA4, 0xA9, 0xD9, 0xB4, + 0xA4, 0xA1, 0x65, 0x2A, 0x67, 0x00, 0x87, 0x50, 0x47, 0x2A, 0xA4, 0xA5, + 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xC9, 0xD8, 0xB4, 0xA4, 0xAD, 0xD9, 0xB4, + 0xA4, 0xA1, 0x66, 0x0B, 0x67, 0x2A, 0x87, 0x61, 0x47, 0x2B, 0xA4, 0xA5, + 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xC9, 0xD8, 0xB4, 0xA4, 0xB1, 0xD9, 0xB4, + 0xA4, 0xA1, 0x66, 0x78, 0x67, 0x1F, 0x87, 0x62, 0x47, 0x18, 0xA4, 0xA5, + 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xC9, 0xD8, 0xB4, 0xA4, 0xB5, 0xD9, 0xB4, + 0xA4, 0xA1, 0x66, 0x78, 0x67, 0x1F, 0x87, 0x63, 0x47, 0x67, 0xA4, 0xA5, + 0xDA, 0xB4, 0x68, 0x22, 0x69, 0x26, 0x6A, 0x2B, 0x6B, 0x01, 0xA4, 0xC9, + 0xD8, 0xB4, 0xA4, 0xB9, 0xD9, 0xB4, 0xA4, 0xA1, 0x66, 0x8C, 0x67, 0x8C, + 0x87, 0x64, 0x47, 0x18, 0xA4, 0xA5, 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xC9, + 0xD8, 0xB4, 0xA4, 0xBD, 0xD9, 0xB4, 0xA4, 0xA1, 0x66, 0x8C, 0x67, 0x78, + 0x87, 0x65, 0x47, 0xEC, 0xA4, 0xA5, 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xC9, + 0xD8, 0xB4, 0xA4, 0xC5, 0xD9, 0xB4, 0xA4, 0xA1, 0x66, 0x78, 0x67, 0x8C, + 0x87, 0x67, 0x47, 0xEC, 0xA4, 0xA5, 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xC9, + 0xD8, 0xB4, 0xA4, 0xC1, 0xD9, 0xB4, 0xA4, 0xA1, 0x66, 0x0F, 0x86, 0x66, + 0x46, 0x07, 0xA4, 0xA5, 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xC9, 0xD8, 0xB4, + 0xA4, 0xE1, 0xD9, 0xB4, 0xA4, 0xA1, 0x66, 0xE0, 0x86, 0x6E, 0x46, 0xC0, + 0xA4, 0xA5, 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xE5, 0xD8, 0xB4, 0xA4, 0xC1, + 0xD9, 0xB4, 0xA4, 0x9E, 0xF1, 0x65, 0xA4, 0xA5, 0x30, 0xAA, 0xA4, 0xA1, + 0x31, 0x55, 0xA4, 0xA1, 0xDA, 0xB4, 0x68, 0x32, 0x69, 0x36, 0x6A, 0x3B, + 0x6B, 0x01, 0xA4, 0xE5, 0xD8, 0xB4, 0xA4, 0xBD, 0xD9, 0xB4, 0xA4, 0x9E, + 0x60, 0x00, 0x61, 0x30, 0xF1, 0x55, 0xA4, 0x9E, 0xF0, 0x65, 0x81, 0x00, + 0xA4, 0x9F, 0xF0, 0x65, 0xA4, 0xA5, 0x30, 0x30, 0xA4, 0xA1, 0x31, 0x00, + 0xA4, 0xA1, 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xE5, 0xD8, 0xB4, 0xA4, 0xB5, + 0xD9, 0xB4, 0xA4, 0x9E, 0x66, 0x89, 0xF6, 0x33, 0xF2, 0x65, 0xA4, 0xA1, + 0x30, 0x01, 0x14, 0x32, 0x31, 0x03, 0x14, 0x32, 0x32, 0x07, 0x14, 0x32, + 0xA4, 0x9E, 0x66, 0x41, 0xF6, 0x33, 0xF2, 0x65, 0xA4, 0xA1, 0x30, 0x00, + 0x14, 0x32, 0x31, 0x06, 0x14, 0x32, 0x32, 0x05, 0x14, 0x32, 0xA4, 0x9E, + 0x66, 0x04, 0xF6, 0x33, 0xF2, 0x65, 0xA4, 0xA1, 0x30, 0x00, 0x14, 0x32, + 0x31, 0x00, 0x14, 0x32, 0x32, 0x04, 0x14, 0x32, 0xA4, 0xA5, 0xDA, 0xB4, + 0x7B, 0x05, 0xA4, 0xE5, 0xD8, 0xB4, 0xA4, 0xE1, 0xD9, 0xB4, 0xA4, 0xA1, + 0x66, 0x04, 0xF6, 0x1E, 0xDA, 0xB4, 0x7B, 0x05, 0xA4, 0xE9, 0xD8, 0xB4, + 0xA4, 0xED, 0xD9, 0xB4, 0xA4, 0xA5, 0x66, 0xFF, 0x76, 0x0A, 0x36, 0x09, + 0xA4, 0xA1, 0x86, 0x66, 0x36, 0x04, 0xA4, 0xA1, 0x66, 0xFF, 0x60, 0x0A, + 0x86, 0x04, 0x36, 0x09, 0xA4, 0xA1, 0x86, 0x66, 0x36, 0x04, 0xA4, 0xA1, + 0x66, 0xFF, 0x86, 0x6E, 0x86, 0x66, 0x36, 0x7F, 0xA4, 0xA1, 0x86, 0x66, + 0x86, 0x6E, 0x36, 0x7E, 0xA4, 0xA1, 0x66, 0x05, 0x76, 0xF6, 0x36, 0xFB, + 0xA4, 0xA1, 0x66, 0x05, 0x86, 0x05, 0x36, 0xFB, 0xA4, 0xA1, 0x66, 0x05, + 0x80, 0x67, 0x30, 0xFB, 0xA4, 0xA1, 0xDA, 0xB4, 0x14, 0x9C, 0xAA, 0x55, + 0x00, 0x00, 0xA0, 0x40, 0xA0, 0x00, 0xA0, 0xC0, 0x80, 0xE0, 0xA0, 0xA0, + 0xE0, 0xC0, 0x40, 0x40, 0xE0, 0xE0, 0x20, 0xC0, 0xE0, 0xE0, 0x60, 0x20, + 0xE0, 0xA0, 0xE0, 0x20, 0x20, 0xE0, 0xC0, 0x20, 0xC0, 0x60, 0x80, 0xE0, + 0xE0, 0xE0, 0x20, 0x40, 0x40, 0xE0, 0xE0, 0xA0, 0xE0, 0xE0, 0xE0, 0x20, + 0xC0, 0x40, 0xA0, 0xE0, 0xA0, 0xC0, 0xE0, 0xA0, 0xE0, 0xE0, 0x80, 0x80, + 0xE0, 0xC0, 0xA0, 0xA0, 0xC0, 0xE0, 0xC0, 0x80, 0xE0, 0xE0, 0x80, 0xC0, + 0x80, 0x00, 0xA0, 0xA0, 0x40, 0xA0, 0x40, 0xA0, 0xA0, 0x0A, 0xAE, 0xA2, + 0x42, 0x38, 0x08, 0x30, 0xB8, +}; + +/** + * @brief Constructor + * + * @param pRenderer Renderer + */ +System::System(IRenderer* pRenderer) + : mpRenderer(pRenderer), + mpFont(new DefaultFont()), + mpIllegalInstCallback(DefaultIllegalInstCallback), + mClockSpeed(DEFAULT_CLOCK_SPEED), + mOffColor(Color::BLACK), + mOnColor(Color::WHITE) { + + K_ASSERT_PTR(mpRenderer); + K_ASSERT_PTR(mpFont); + + Reset(); +} + +/** + * @brief Destructor + */ +System::~System() { + delete mpRenderer; + mpRenderer = nullptr; + + delete mpFont; + mpFont = nullptr; +} + +/** + * @brief Resets the emulator state + * @note This does not re-load the ROM. + */ +void System::Reset() { + K_ASSERT_PTR(mpFont); + K_ASSERT_EX(mpFont->GetLoadAddr() + mpFont->GetSpriteDataSize() < + MEMORY_SIZE, + "Font sprite data is too big"); + + std::memcpy(mMemory + mpFont->GetLoadAddr(), mpFont->GetSpriteData(), + mpFont->GetSpriteDataSize()); + + std::memset(mMemory, 0, sizeof(mMemory)); + std::memset(mFrameBuffer, 0, sizeof(mFrameBuffer)); + + std::memset(V, 0, sizeof(V)); + I = 0; + PC = 0; + + std::memset(mStack, 0, sizeof(mStack)); + SP = 0; + + mDelayTimer = 0; + mSoundTimer = 0; +} + +/** + * @brief Performs one frame of execution + */ +void System::Calculate() { + // Program stalling for keypress + if (mWaitKeyPressReg) { + CalculateWaitKey(); + return; + } + + // Perform one initial cycle + if (!mPrevOSTick) { + mPrevOSTick = OSGetTick(); + Update(static_cast(1)); + return; + } + + s64 deltaTick = OS_TICKS_DELTA(OSGetTick(), *mPrevOSTick); + f32 deltaTime = OS_TICKS_TO_USEC(deltaTick) / 1000000.0f; + Update(deltaTime); +} + +/** + * @brief Draws the latest frame + */ +void System::Draw() { + K_ASSERT_PTR(mpRenderer); + + IRenderer::Arg arg; + arg.pBuffer = mFrameBuffer; + arg.width = FRAMEBUFFER_WIDTH; + arg.height = FRAMEBUFFER_HEIGHT; + arg.off = mOffColor; + arg.on = mOnColor; + + mpRenderer->Draw(arg); +} + +/** + * @brief Loads a ROM binary + * + * @param pBinary Binary data + * @param binarySize Binary data size + */ +void System::LoadROM(const void* pBinary, u32 binarySize) { + K_ASSERT_PTR(pBinary); + K_ASSERT(PROG_ADDR + binarySize < MEMORY_SIZE); + + Reset(); + std::memcpy(mMemory + PROG_ADDR, pBinary, binarySize); + + PC = PROG_ADDR; +} + +/** + * @brief Loads the test ROM binary + */ +void System::LoadTestROM() { + LoadROM(scTestRom, sizeof(scTestRom)); +} + +/** + * @brief Performs the specified amount of CPU cycles + * + * @param cycles Cycle count + */ +void System::Update(u32 cycles) { + for (u32 i = 0; i < cycles; i++) { + K_ASSERT_EX(PC <= MEMORY_SIZE - 2, "Program counter overflow!"); + + mOpcode.raw = mMemory[PC++] << 8 | mMemory[PC++]; + (this->*scOpcodeGroupFuncs[mOpcode.type])(); + } +} + +/** + * @brief Updates waiting for keypress state + */ +void System::CalculateWaitKey() { + K_ASSERT(mWaitKeyPressReg.HasValue()); + + const kiwi::WiiCtrl& rCtrl = + kiwi::CtrlMgr::GetInstance().GetWiiCtrl(kiwi::EPlayer_1); + + for (u32 i = 0; i < K_LENGTHOF(scButtonMap); i++) { + if (!rCtrl.IsHold(scButtonMap[i])) { + continue; + } + + V[*mWaitKeyPressReg] = static_cast(i); + mWaitKeyPressReg.Reset(); + break; + } +} + +/** + * @brief Default illegal instruction callback + * + * @param opcode Illegal instruction opcode + * @param V Register state (mutable) + */ +void System::DefaultIllegalInstCallback(u16 opcode, u8 V[VREG_NUM]) { + K_ASSERT_PTR(V); + + K_ASSERT_EX(false, "Unhandled illegal instruction (%04X)", opcode); +} + +/** + * @brief Executes an opcode in the 0XXX group + */ +void System::Opcode_0XXX() { + switch (mOpcode.kk) { + case 0xE0: { + Opcode_CLS(); + break; + } + + case 0xEE: { + Opcode_RET(); + break; + } + + default: { + Opcode_Illegal(); + break; + } + } +} + +/** + * @brief Executes an opcode in the 8XXX group + */ +void System::Opcode_8XXX() { + static const OpcodeFunc table[] = { + &System::Opcode_LD_VX_VY, &System::Opcode_OR, + &System::Opcode_AND, &System::Opcode_XOR, + &System::Opcode_ADD_VX_VY, &System::Opcode_SUB, + &System::Opcode_SHR, &System::Opcode_SUBN, + &System::Opcode_Illegal, &System::Opcode_Illegal, + &System::Opcode_Illegal, &System::Opcode_Illegal, + &System::Opcode_Illegal, &System::Opcode_Illegal, + &System::Opcode_SHL, &System::Opcode_Illegal}; + + (this->*table[mOpcode.n])(); +} + +/** + * @brief Executes an opcode in the EXXX group + */ +void System::Opcode_EXXX() { + switch (mOpcode.kk) { + case 0x9E: { + Opcode_SKP(); + break; + } + + case 0xA1: { + Opcode_SKNP(); + break; + } + + default: { + Opcode_Illegal(); + break; + } + } +} + +/** + * @brief Executes an opcode in the FXXX group + */ +void System::Opcode_FXXX() { + switch (mOpcode.kk) { + case 0x07: { + Opcode_LD_VX_DT(); + break; + } + + case 0x0A: { + Opcode_LD_VX_K(); + break; + } + + case 0x15: { + Opcode_LD_DT_VX(); + break; + } + + case 0x18: { + Opcode_LD_ST_VX(); + break; + } + + case 0x1E: { + Opcode_ADD_I_VX(); + break; + } + + case 0x29: { + Opcode_LD_F_VX(); + break; + } + + case 0x33: { + Opcode_LD_B_VX(); + break; + } + + case 0x55: { + Opcode_LD_I_VX(); + break; + } + + case 0x65: { + Opcode_LD_VX_I(); + break; + } + + default: { + Opcode_Illegal(); + break; + } + } +} + +/** + * @brief Handler for illegal opcodes + */ +void System::Opcode_Illegal() { + if (mpIllegalInstCallback != nullptr) { + mpIllegalInstCallback(mOpcode.raw, V); + } else { + // Catch unhandled exceptions in debug + K_UNREACHABLE(); + } +} + +/** + * @brief 00E0 - CLS + * @details Clear the display. + */ +void System::Opcode_CLS() { + std::memset(mFrameBuffer, 0, sizeof(mFrameBuffer)); +} + +/** + * @brief 00EE - RET + * @details Return from a subroutine. + */ +void System::Opcode_RET() { + K_ASSERT_EX(SP > 0, "Stack underflow!"); + K_ASSERT(SP < STACK_LENGTH); + PC = mStack[SP--]; +} + +/** + * @brief 1nnn - JP addr + * @details Jump to location nnn. + */ +void System::Opcode_JP_NNN() { + PC = mOpcode.nnn; +} + +/** + * @brief 2nnn - CALL addr + * @details Call subroutine at nnn. + */ +void System::Opcode_CALL_NNN() { + K_ASSERT_EX(SP < STACK_LENGTH - 1, "Stack overflow!"); + mStack[++SP] = PC; + PC = mOpcode.nnn; +} + +/** + * @brief 3xkk - SE Vx, byte + * @details Skip next instruction if Vx = kk. + */ +void System::Opcode_SE_VX_KK() { + if (V[mOpcode.x] == mOpcode.kk) { + PC += sizeof(u16); + } +} + +/** + * @brief 4xkk - SNE Vx, byte + * @details Skip next instruction if Vx != kk. + */ +void System::Opcode_SNE_VX_KK() { + if (V[mOpcode.x] != mOpcode.kk) { + PC += sizeof(u16); + } +} + +/** + * @brief 5xy0 - SE Vx, Vy + * @details Skip next instruction if Vx = Vy. + */ +void System::Opcode_SE_VX_VY() { + if (V[mOpcode.x] == V[mOpcode.y]) { + PC += sizeof(u16); + } +} + +/** + * @brief 6xkk - LD Vx, byte + * @details Set Vx = kk. + */ +void System::Opcode_LD_VX_KK() { + V[mOpcode.x] = mOpcode.kk; +} + +/** + * @brief 7xkk - LD Vx, byte + * @details Set Vx = Vx + kk. + */ +void System::Opcode_ADD_VX_KK() { + V[mOpcode.x] += mOpcode.kk; +} + +/** + * @brief 8xy0 - LD Vx, Vy + * @details Set Vx = Vy. + */ +void System::Opcode_LD_VX_VY() { + V[mOpcode.x] = V[mOpcode.y]; +} + +/** + * @brief 8xy1 - OR Vx, Vy + * @details Set Vx = Vx OR Vy. + */ +void System::Opcode_OR() { + V[mOpcode.x] |= V[mOpcode.y]; +} + +/** + * @brief 8xy2 - AND Vx, Vy + * @details Set Vx = Vx AND Vy. + */ +void System::Opcode_AND() { + V[mOpcode.x] &= V[mOpcode.y]; +} + +/** + * @brief 8xy3 - XOR Vx, Vy + * @details Set Vx = Vx XOR Vy. + */ +void System::Opcode_XOR() { + V[mOpcode.x] ^= V[mOpcode.y]; +} + +/** + * @brief 8xy4 - ADD Vx, Vy + * @details Set Vx = Vx + Vy, set VF = carry. + */ +void System::Opcode_ADD_VX_VY() { + VF = V[mOpcode.x] + V[mOpcode.y] > 0xFF ? 1 : 0; + V[mOpcode.x] += V[mOpcode.y]; +} + +/** + * @brief 8xy5 - SUB Vx, Vy + * @details Set Vx = Vx - Vy, set VF = NOT borrow. + */ +void System::Opcode_SUB() { + VF = V[mOpcode.x] > V[mOpcode.y] ? 1 : 0; + V[mOpcode.x] -= V[mOpcode.y]; +} + +/** + * @brief 8xy6 - SHR Vx {, Vy} + * @details Set Vx = Vx SHR 1. + */ +void System::Opcode_SHR() { + VF = V[mOpcode.x] & 0b00000001; + V[mOpcode.x] >>= 1; +} + +/** + * @brief 8xy7 - SUBN Vx, Vy + * @details Set Vx = Vy - Vx, set VF = NOT borrow. + */ +void System::Opcode_SUBN() { + VF = V[mOpcode.y] > V[mOpcode.x]; + V[mOpcode.y] -= V[mOpcode.x]; +} + +/** + * @brief 8xyE - SHL Vx {, Vy} + * @details Set Vx = Vx SHL 1. + */ +void System::Opcode_SHL() { + VF = V[mOpcode.x] & 0b10000000; + V[mOpcode.x] <<= 1; +} + +/** + * @brief 9xy0 - SNE Vx, Vy + * @details Skip next instruction if Vx != Vy. + */ +void System::Opcode_SNE_VX_VY() { + if (V[mOpcode.x] != V[mOpcode.y]) { + PC += sizeof(u16); + } +} + +/** + * @brief Annn - LD I, addr + * @details Set I = nnn. + */ +void System::Opcode_LD_I_NNN() { + I = mOpcode.nnn; +} + +/** + * @brief Bnnn - JP V0, addr + * @details Jump to location nnn + V0. + */ +void System::Opcode_JP_V0_NNN() { + PC = mOpcode.nnn + V[0]; +} + +/** + * @brief Cxkk - RND Vx, byte + * @details Set Vx = random byte AND kk. + */ +void System::Opcode_RND() { + V[mOpcode.x] = mRandom.NextU32() & mOpcode.kk; +} + +/** + * @brief Dxyn - DRW Vx, Vy, nibble + * @details Display n-byte sprite starting at memory location I at (Vx, Vy), set + * VF = collision. + */ +void System::Opcode_DRW() { + K_ASSERT(I < MEMORY_SIZE); + +#if 0 + VF = false; + + u8 x = V[mOpcode.x] % FRAMEBUFFER_WIDTH; + u8 y = V[mOpcode.y] % FRAMEBUFFER_HEIGHT; + + // Sprite dimensions is Nx8 + for (u32 i = 0; i < mOpcode.n; i++, y++) { + K_ASSERT(I + i < MEMORY_SIZE); + K_ASSERT(y * (FRAMEBUFFER_WIDTH / 8) + (x / 8) < MEMORY_SIZE); + + // Sprite row at 1bpp + u8 row = mMemory[I + i]; + // Sprite position in memory + u8* p = &mMemory[y * (FRAMEBUFFER_WIDTH / 8) + (x / 8)]; + + // Sprites are clamped at edges + for (u32 i = 0; i < Min(SPRITE_WIDTH, FRAMEBUFFER_WIDTH - x); + i++, row >>= 1, x++) { + + // Next pixel is off + if (!(row & 1)) { + continue; + } + + VF |= *p & (1 << i); + *p ^= 1 << i; + } + } +#else + VF = false; + + u8 x = V[mOpcode.x] % FRAMEBUFFER_WIDTH; + u8 y = V[mOpcode.y] % FRAMEBUFFER_HEIGHT; + + // Sprite dimensions is Nx8 + for (u32 i = 0; i < mOpcode.n; i++, y++) { + K_ASSERT(I + i < MEMORY_SIZE); + K_ASSERT(y * FRAMEBUFFER_WIDTH + x < MEMORY_SIZE); + + // Sprite row at 1bpp + u8 row = mMemory[I + i]; + // Sprite position in memory + u8* p = &mFrameBuffer[y * FRAMEBUFFER_WIDTH + x]; + + // Sprites are clamped at edges + for (u32 j = 0; j < Min(SPRITE_WIDTH, FRAMEBUFFER_WIDTH - x); j++) { + // Next pixel is off + if (!(row & (0b10000000 >> j))) { + continue; + } + + VF |= p[j] != 0; + p[j] ^= 1; + } + } +#endif +} + +/** + * @brief Ex9E - SKP Vx + * @details Skip next instruction if key with the value of Vx is pressed. + */ +void System::Opcode_SKP() { + // Not all buttons are mapped + if ((V[mOpcode.x]) >= K_LENGTHOF(scButtonMap)) { + return; + } + + u32 mask = scButtonMap[V[mOpcode.x]]; + + const kiwi::WiiCtrl& rCtrl = + kiwi::CtrlMgr::GetInstance().GetWiiCtrl(kiwi::EPlayer_1); + + if (rCtrl.IsConnected() && rCtrl.IsHold(mask)) { + PC += sizeof(u16); + } +} + +/** + * @brief Ex9E - SKNP Vx + * @details Skip next instruction if key with the value of Vx is not pressed. + */ +void System::Opcode_SKNP() { + // Not all buttons are mapped + if ((V[mOpcode.x]) >= K_LENGTHOF(scButtonMap)) { + return; + } + + u32 mask = scButtonMap[V[mOpcode.x]]; + + const kiwi::WiiCtrl& rCtrl = + kiwi::CtrlMgr::GetInstance().GetWiiCtrl(kiwi::EPlayer_1); + + if (rCtrl.IsConnected() && !rCtrl.IsHold(mask)) { + PC += sizeof(u16); + } +} + +/** + * @brief Fx07 - LD Vx, DT + * @details Set Vx = delay timer value. + */ +void System::Opcode_LD_VX_DT() { + V[mOpcode.x] = mDelayTimer; +} + +/** + * @brief Fx0A - LD Vx, K + * @details Wait for a keypress, store the value of the key in Vx. + */ +void System::Opcode_LD_VX_K() { + // TODO (kiwi): Narrowing happens here!!! + mWaitKeyPressReg = mOpcode.x; +} + +/** + * @brief Fx15 - LD DT, Vx + * @details Set delay timer = Vx. + */ +void System::Opcode_LD_DT_VX() { + mDelayTimer = V[mOpcode.x]; +} + +/** + * @brief Fx18 - LD ST, Vx + * @details Set sound timer = Vx. + */ +void System::Opcode_LD_ST_VX() { + mSoundTimer = V[mOpcode.x]; +} + +/** + * @brief Fx1E - ADD I, Vx + * @details Set I = I + Vx. + */ +void System::Opcode_ADD_I_VX() { + I += V[mOpcode.x]; +} + +/** + * @brief Fx29 - LD F, Vx + * @details Set I = location of font sprite for digit Vx. + */ +void System::Opcode_LD_F_VX() { + K_ASSERT_PTR(mpFont); + + u8 index = V[mOpcode.x]; + K_ASSERT(index >= mpFont->GetMinChar()); + K_ASSERT(index < mpFont->GetMaxChar()); + + // Avoid potentially reading memory outside of the emulator + if (index < mpFont->GetMinChar() || index >= mpFont->GetMaxChar()) { + I = 0; + return; + } + + const u8* pSpriteData = mpFont->GetSpriteData(); + K_ASSERT_PTR(pSpriteData); + + u32 oneSize = mpFont->GetCharWidth() * mpFont->GetBitDepth() * + mpFont->GetCharHeight(); + I = mpFont->GetLoadAddr() + index * oneSize; +} + +/** + * @brief Fx33 - LD B, Vx + * @details Store BCD representation of Vx in memory locations I, I+1, and I+2. + */ +void System::Opcode_LD_B_VX() { + K_ASSERT(I <= MEMORY_SIZE - 3); + + u32 value = V[mOpcode.x]; + + for (int i = 0; i < 3; i++, value /= 10) { + mMemory[I + (2 - i)] = value % 10; + } +} + +/** + * @brief Fx55 - LD [I], Vx + * @details Store registers V0 through Vx in memory starting at location I. + */ +void System::Opcode_LD_I_VX() { + u32 regNum = mOpcode.x; + K_ASSERT(I <= MEMORY_SIZE - (regNum - 1)); + + for (u32 i = 0; i < regNum; i++) { + mMemory[I + i] = V[i]; + } +} + +/** + * @brief Fx65 - LD Vx, [I] + * @details Read registers V0 through Vx from memory starting at location I. + */ +void System::Opcode_LD_VX_I() { + u32 regNum = mOpcode.x; + K_ASSERT(I <= MEMORY_SIZE - (regNum - 1)); + + for (u32 i = 0; i < regNum; i++) { + V[i] = mMemory[I + i]; + } +} + +} // namespace chip8 +} // namespace kiwi diff --git a/lib/libkiwi/fun/kiwiChip8.h b/lib/libkiwi/fun/kiwiChip8.h new file mode 100644 index 0000000..ddb4cc7 --- /dev/null +++ b/lib/libkiwi/fun/kiwiChip8.h @@ -0,0 +1,548 @@ +#ifndef LIBKIWI_FUN_CHIP8_H +#define LIBKIWI_FUN_CHIP8_H +#include +#include +#include + +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_fun +//! @{ +namespace chip8 { +//! @addtogroup libkiwi_fun +//! @{ + +/****************************************************************************** + * + * Font + * + ******************************************************************************/ + +/** + * @brief Font interface + */ +class IFont { +public: + /** + * @brief Destructor + */ + virtual ~IFont() {} + + /** + * @brief Gets the width (in pixels) of font characters + */ + virtual u16 GetCharWidth() const { + return 8; + } + /** + * @brief Gets the height (in pixels) of font characters + */ + virtual u16 GetCharHeight() const { + return 5; + } + + /** + * @brief Gets the minimum supported character index + */ + virtual u8 GetMinChar() const { + return 0x00; + } + /** + * @brief Gets the maximum supported character index + */ + virtual u8 GetMaxChar() const { + return 0x0F; + } + + /** + * @brief Gets the number of bits per pixel + */ + virtual u8 GetBitDepth() const { + return 1; + } + + /** + * @brief Gets the destination address in CHIP-8 memory + */ + virtual u16 GetLoadAddr() const { + return 0; + } + + /** + * @brief Gets the font sprite data + */ + virtual const u8* GetSpriteData() = 0; + /** + * @brief Gets the size of the font sprite data + */ + virtual const u32 GetSpriteDataSize(); +}; + +/** + * @brief Default ROM font + */ +class DefaultFont : public IFont { +public: + /** + * @brief Gets the font sprite data + */ + virtual const u8* GetSpriteData() { + return scSpriteData; + } + +private: + //! Font sprite data + static const u8 scSpriteData[]; +}; + +/****************************************************************************** + * + * Renderer + * + ******************************************************************************/ + +/** + * @brief Renderer interface + */ +class IRenderer { +public: + /** + * @brief Rendering context + */ + struct Arg { + const u8* pBuffer; //!< Framebuffer (1bpp) + u32 width; //!< Display width + u32 height; //!< Display height + + Color off; //!< 'Off' pixel color + Color on; //!< 'On' pixel color + }; + +private: + //! Defauly Chip-8 pixel size + static const u32 DEFAULT_PIXEL_SIZE = 8; + +public: + /** + * @brief Constructor + */ + IRenderer() : mPixelSize(DEFAULT_PIXEL_SIZE) {} + + /** + * @brief Destructor + */ + virtual ~IRenderer() {} + + /** + * @brief Draws the emulator framebuffer + * + * @param rArg Rendering context + */ + virtual void Draw(const Arg& rArg) = 0; + + /** + * @brief Sets the size of Chip-8 pixels + * + * @param size Pixel size + */ + void SetPixelSize(u8 size) { + mPixelSize = size; + } + +protected: + //! Chip-8 pixel size + u8 mPixelSize; +}; + +/** + * @brief GX renderer + */ +class GXRenderer : public IRenderer { +public: + /** + * @brief Constructor + */ + GXRenderer(); + /** + * @brief Destructor + */ + virtual ~GXRenderer(); + + /** + * @brief Draws the emulator framebuffer + * + * @param rArg Rendering context + */ + virtual void Draw(const Arg& rArg); + +private: + //! CI8 texture block width, in pixels + static const u32 CI8_BLOCK_WIDTH = 8; + //! CI8 texture block height, in pixels + static const u32 CI8_BLOCK_HEIGHT = 4; + + //! 2 palette entries ('on'/'off' pixel color) + static const u32 PALETTE_ENTRY_NUM = 2; + +private: + /** + * @brief Creates CI8 texture data from the Chip-8 framebuffer + * + * @param rArg Rendering context + */ + void CreateTexture(const Arg& rArg); + + /** + * @brief Creates RGB565 palette data from the Chip-8 framebuffer + * + * @param rArg Rendering context + */ + void CreatePalette(const Arg& rArg); + +private: + //! Texture data + u8* mpTexture; + //! Texture data size + u32 mTextureSize; + + //! Palette data + u8* mpPalette; + + //! GX texture object + GXTexObj mTexObj; + //! GX palette object + GXTlutObj mTlutObj; +}; + +/****************************************************************************** + * + * System + * + ******************************************************************************/ + +/** + * @brief Emulator system + */ +class System { + //! Number of general purpose registers + static const u32 VREG_NUM = 16; + + /** + * @brief Illegal instruction handler + * @note This is useful for catching user-defined opcodes. + * + * @param opcode Illegal instruction opcode + * @param V Register state (mutable) + */ + typedef void (*IllegalInstCallback)(u16 opcode, u8 V[VREG_NUM]); + +public: + /** + * @brief Constructor + * + * @param pRenderer Renderer + */ + System(IRenderer* pRenderer); + + /** + * @brief Destructor + */ + ~System(); + + /** + * @brief Resets the emulator state + * @note This does not re-load the ROM. + */ + void Reset(); + + /** + * @brief Performs one frame of execution + */ + void Calculate(); + + /** + * @brief Draws the latest frame + */ + void Draw(); + + /** + * @brief Loads a ROM binary + * + * @param pBinary Binary data + * @param binarySize Binary data size + */ + void LoadROM(const void* pBinary, u32 binarySize); + + /** + * @brief Loads the test ROM binary + */ + void LoadTestROM(); + + /** + * @brief Sets the emulator renderer + * + * @param pRenderer New renderer + */ + void SetRenderer(IRenderer* pRenderer) { + K_ASSERT_PTR(pRenderer); + mpRenderer = pRenderer; + } + + /** + * @brief Sets the emulator font + * + * @param pFont New font + */ + void SetFont(IFont* pFont) { + K_ASSERT_PTR(pFont); + mpFont = pFont; + } + + /** + * @brief Sets the illegal instruction callback + * @details Supply NULL to switch back to the default callback. + * @note This is useful for catching user-defined opcodes. + * + * @param pCallback Callback function + */ + void SetIllegalInstCallback(IllegalInstCallback pCallback) { + mpIllegalInstCallback = + pCallback != nullptr ? pCallback : DefaultIllegalInstCallback; + } + + /** + * @brief Sets the emulator clock speed, in Hz + * + * @param clockSpeed New clock speed (Hz) + */ + void SetClockSpeed(u32 clockSpeed) { + mClockSpeed = clockSpeed; + } + + /** + * @brief Sets the emulator color palette + * + * @param off 'Off' pixel color + * @param on 'On' pixel color + */ + void SetColorPalette(Color off, Color on) { + mOffColor = off; + mOnColor = on; + } + +private: + /** + * @brief Opcode handler function + */ + typedef void (System::*OpcodeFunc)(); + + //! Sprite width, in pixels + static const u32 SPRITE_WIDTH = 8; + + //! RAM size + static const u32 MEMORY_SIZE = OS_MEM_KB_TO_B(4); + //! Font location in RAM + static const u32 FONT_ADDR = 0x000; + //! ROM location in RAM + static const u32 PROG_ADDR = 0x200; + + //! Framebuffer width + static const u32 FRAMEBUFFER_WIDTH = 64; + //! Framebuffer height + static const u32 FRAMEBUFFER_HEIGHT = 32; + + //! Framebuffer size + static const u32 FRAMEBUFFER_SIZE = + FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT /* / 8 */; + + //! Stack memory size + static const u32 STACK_SIZE = OS_MEM_KB_TO_B(1); + //! Stack array length + static const u32 STACK_LENGTH = STACK_SIZE / sizeof(u16); + + //! Default clock speed, in Hz + static const u32 DEFAULT_CLOCK_SPEED = 700; + +private: + /** + * @brief Performs the amount of CPU cycles corresponding to the specified + * time duration + * + * @param dt Delta time + */ + void Update(f32 dt) { + Update(static_cast(mClockSpeed * dt)); + } + + /** + * @brief Performs the specified amount of CPU cycles + * + * @param cycles Cycle count + */ + void Update(u32 cycles); + + /** + * @brief Updates waiting for keypress state + */ + void CalculateWaitKey(); + + /** + * @brief Default illegal instruction callback + * + * @param opcode Illegal instruction opcode + * @param V Register state (mutable) + */ + static void DefaultIllegalInstCallback(u16 opcode, u8 V[VREG_NUM]); + + /** + * @name Opcode group functions + */ + /**@{*/ + void Opcode_0XXX(); + void Opcode_8XXX(); + void Opcode_EXXX(); + void Opcode_FXXX(); + /**@}*/ + + /** + * @name Opcode handler functions + */ + /**@{*/ + void Opcode_Illegal(); + void Opcode_CLS(); + void Opcode_RET(); + void Opcode_JP_NNN(); + void Opcode_CALL_NNN(); + void Opcode_SE_VX_KK(); + void Opcode_SNE_VX_KK(); + void Opcode_SE_VX_VY(); + void Opcode_LD_VX_KK(); + void Opcode_ADD_VX_KK(); + void Opcode_LD_VX_VY(); + void Opcode_OR(); + void Opcode_AND(); + void Opcode_XOR(); + void Opcode_ADD_VX_VY(); + void Opcode_SUB(); + void Opcode_SHR(); + void Opcode_SUBN(); + void Opcode_SHL(); + void Opcode_SNE_VX_VY(); + void Opcode_LD_I_NNN(); + void Opcode_JP_V0_NNN(); + void Opcode_RND(); + void Opcode_DRW(); + void Opcode_SKP(); + void Opcode_SKNP(); + void Opcode_LD_VX_DT(); + void Opcode_LD_VX_K(); + void Opcode_LD_DT_VX(); + void Opcode_LD_ST_VX(); + void Opcode_ADD_I_VX(); + void Opcode_LD_F_VX(); + void Opcode_LD_B_VX(); + void Opcode_LD_I_VX(); + void Opcode_LD_VX_I(); + /**@}*/ + +private: + //! Random number generator + Random mRandom; + + //! Renderer + IRenderer* mpRenderer; + //! System font + IFont* mpFont; + + //! Illegal instruction callback + IllegalInstCallback mpIllegalInstCallback; + + //! Clock speed, in Hz + u32 mClockSpeed; + //! Previous tick OSTick + Optional mPrevOSTick; + + //! 'Off' pixel color + Color mOffColor; + //! 'On' pixel color + Color mOnColor; + + //! Memory space + u8 mMemory[MEMORY_SIZE]; + //! Display framebuffer + u8 mFrameBuffer[FRAMEBUFFER_SIZE]; + + //! Current opcode + union { + //! Entire value + u16 raw; + + //! nnn/addr nibbles + struct { + u16 type : 4; + u16 nnn : 12; + }; + + //! x/y/n nibbles + struct { + u16 _1 : 4; + u16 x : 4; + u16 y : 4; + u16 n : 4; + }; + + //! kk/byte nibbles + struct { + u16 _2 : 8; + u16 kk : 8; + }; + } mOpcode; + + //! General purpose registers + union { + u8 V[VREG_NUM]; + + //! 'VF' alias for last register + struct { + u8 _[VREG_NUM - 1]; + u8 VF; + }; + }; + + //! Index register + u16 I; + //! Program counter + u16 PC; + + //! Stack memory + u16 mStack[STACK_LENGTH]; + //! Stack pointer + u16 SP; + + //! 60Hz delay timer + u8 mDelayTimer; + //! Sound/beeping timer + u8 mSoundTimer; + + //! Register which is stalling execution for a keypress + Optional mWaitKeyPressReg; + +private: + //! Opcode group handler functions + static const OpcodeFunc scOpcodeGroupFuncs[]; + + //! Keyboard button map + static const u32 scButtonMap[]; + + //! Corax+ test ROM + static const u8 scTestRom[]; +}; + +//! @} +} // namespace chip8 +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/fun/kiwiChip8Lang.h b/lib/libkiwi/fun/kiwiChip8Lang.h new file mode 100644 index 0000000..f864e1a --- /dev/null +++ b/lib/libkiwi/fun/kiwiChip8Lang.h @@ -0,0 +1,11 @@ +#ifndef LIBKIWI_FUN_CHIP8_LANG_H +#define LIBKIWI_FUN_CHIP8_LANG_H + +//! @addtogroup libkiwi_fun +//! @{ + +/* */ #define CLS + +//! @} + +#endif diff --git a/lib/libkiwi/hostio/control/kiwiHostIOButtonControl.cpp b/lib/libkiwi/hostio/control/kiwiHostIOButtonControl.cpp new file mode 100644 index 0000000..9aaddf4 --- /dev/null +++ b/lib/libkiwi/hostio/control/kiwiHostIOButtonControl.cpp @@ -0,0 +1,18 @@ +#include + +namespace kiwi { +namespace hostio { + +/** + * @brief Handles property event from host client + * + * @param rEvent Event structure from the host + */ +void ButtonControl::ListenPropertyEvent(const PropertyEvent& rEvent) { + if (mpCallback != nullptr) { + mpCallback(this, mpCallbackArg); + } +} + +} // namespace hostio +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/hostio/control/kiwiHostIOButtonControl.h b/lib/libkiwi/hostio/control/kiwiHostIOButtonControl.h new file mode 100644 index 0000000..090d6a9 --- /dev/null +++ b/lib/libkiwi/hostio/control/kiwiHostIOButtonControl.h @@ -0,0 +1,63 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_BUTTON_CONTROL_H +#define LIBKIWI_HOSTIO_HOST_IO_BUTTON_CONTROL_H +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +/** + * @brief Button UI control + */ +class ButtonControl : public IControl { +public: + /** + * @brief Button click callback function + * + * @param pInvoker Button that invoked this callback + * @param pArg User argument + */ + typedef void (*Callback)(ButtonControl* pInvoker, void* pArg); + +public: + /** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param pCallback Callback function + * @param pCallbackArg Callback function user argument (optional) + */ + ButtonControl(const String& rName, u32 id, Callback pCallback, + void* pCallbackArg = nullptr); + + /** + * @brief Destructor + */ + virtual ~ButtonControl() {} + + /** + * @brief Handles property event from host client + * + * @param rEvent Event structure from the host + */ + virtual void ListenPropertyEvent(const PropertyEvent& rEvent); + +private: + //! Callback function + Callback mpCallback; + //! Callback function user argument + void* mpCallbackArg; +}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/control/kiwiHostIOCheckBoxControl.h b/lib/libkiwi/hostio/control/kiwiHostIOCheckBoxControl.h new file mode 100644 index 0000000..dda4e53 --- /dev/null +++ b/lib/libkiwi/hostio/control/kiwiHostIOCheckBoxControl.h @@ -0,0 +1,24 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_CHECK_BOX_CONTROL_H +#define LIBKIWI_HOSTIO_HOST_IO_CHECK_BOX_CONTROL_H +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +/** + * @brief Check box UI control + */ +class CheckBoxControl : public IControl {}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/control/kiwiHostIOComboBoxControl.h b/lib/libkiwi/hostio/control/kiwiHostIOComboBoxControl.h new file mode 100644 index 0000000..3dc05fe --- /dev/null +++ b/lib/libkiwi/hostio/control/kiwiHostIOComboBoxControl.h @@ -0,0 +1,24 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_COMBO_BOX_CONTROL_H +#define LIBKIWI_HOSTIO_HOST_IO_COMBO_BOX_CONTROL_H +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +/** + * @brief Combo box UI control + */ +class ComboBoxControl : public IControl {}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/control/kiwiHostIOLabelControl.h b/lib/libkiwi/hostio/control/kiwiHostIOLabelControl.h new file mode 100644 index 0000000..5e711c4 --- /dev/null +++ b/lib/libkiwi/hostio/control/kiwiHostIOLabelControl.h @@ -0,0 +1,34 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_LABEL_CONTROL_H +#define LIBKIWI_HOSTIO_HOST_IO_LABEL_CONTROL_H +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +/** + * @brief Label UI control + */ +class LabelControl : public IControl { +public: + /** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + */ + LabelControl(const String& rName, u32 id) + : IControl(EType_Label, rName, id) {} +}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/control/kiwiHostIORadioButtonControl.h b/lib/libkiwi/hostio/control/kiwiHostIORadioButtonControl.h new file mode 100644 index 0000000..a09d226 --- /dev/null +++ b/lib/libkiwi/hostio/control/kiwiHostIORadioButtonControl.h @@ -0,0 +1,24 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_RADIO_BUTTON_CONTROL_H +#define LIBKIWI_HOSTIO_HOST_IO_RADIO_BUTTON_CONTROL_H +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +/** + * @brief Radio button UI control + */ +class RadioButtonControl : public IControl {}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/control/kiwiHostIOSliderControl.cpp b/lib/libkiwi/hostio/control/kiwiHostIOSliderControl.cpp new file mode 100644 index 0000000..868388f --- /dev/null +++ b/lib/libkiwi/hostio/control/kiwiHostIOSliderControl.cpp @@ -0,0 +1,72 @@ +#include + +namespace kiwi { +namespace hostio { +namespace detail { + +/****************************************************************************** + * + * SliderControlImpl + * + ******************************************************************************/ + +/** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param type Value control type + * @param pValue Value storage + * @param min Minimum value (inclusive) + * @param max Maximum value (inclusive) + */ +template +SliderControlImpl::SliderControlImpl(const String& rName, u32 id, + ESliderType type, TValue* pValue, + TValue min, TValue max) + : IControl(IControl::EType_Value, rName, id), + mSliderType(type), + mpValue(pValue), + mMin(min), + mMax(max) { + + K_ASSERT_PTR(mpValue); +} + +/** + * @brief Generates object info for host client (derived implementation) + * + * @param rContext Message context + */ +template +void SliderControlImpl::GenMessageImpl(Context& rContext) { + K_ASSERT_PTR(mpValue); + MemStream& rStrm = rContext.GetMessageStream(); + + rStrm.Write_u8(mSliderType); + rStrm.Write_u32(BitCast(*mpValue)); + rStrm.Write_u32(BitCast(mMin)); + rStrm.Write_u32(BitCast(mMax)); +} + +/** + * @brief Handles property event from host client + * + * @param rEvent Event structure from the host + */ +template +void SliderControlImpl::ListenPropertyEvent( + const PropertyEvent& rEvent) { + + K_ASSERT_PTR(mpValue); + *mpValue = BitCast(rEvent.value); +} + +// Instantiate class templates +template class SliderControlImpl; +template class SliderControlImpl; +template class SliderControlImpl; + +} // namespace detail +} // namespace hostio +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/hostio/control/kiwiHostIOSliderControl.h b/lib/libkiwi/hostio/control/kiwiHostIOSliderControl.h new file mode 100644 index 0000000..479f2ae --- /dev/null +++ b/lib/libkiwi/hostio/control/kiwiHostIOSliderControl.h @@ -0,0 +1,192 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_SLIDER_CONTROL_H +#define LIBKIWI_HOSTIO_HOST_IO_SLIDER_CONTROL_H +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +/****************************************************************************** + * + * SliderControlImpl + * + ******************************************************************************/ +namespace detail { +//! @addtogroup libkiwi_hostio +//! @{ + +/** + * @brief Slider UI control + * + * @tparam TValue Property value type + */ +template class SliderControlImpl : public IControl { +public: + /** + * @brief Slider control type + */ + enum ESliderType { + ESliderType_U32, //!< Unsigned 32-bit value + ESliderType_S32, //!< Signed 32-bit value + ESliderType_F32, //!< Floating point value + + ESliderType_Max + }; + +public: + /** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param type Value control type + * @param pValue Value storage + * @param min Minimum value (inclusive) + * @param max Maximum value (inclusive) + */ + SliderControlImpl(const String& rName, u32 id, ESliderType type, + TValue* pValue, TValue min, TValue max); + + /** + * @brief Destructor + */ + virtual ~SliderControlImpl() {} + + /** + * @brief Handles property event from host client + * + * @param rEvent Event structure from the host + */ + virtual void ListenPropertyEvent(const PropertyEvent& rEvent); + +private: + /** + * @brief Generates object info for host client (derived implementation) + * + * @param rContext Message context + */ + virtual void GenMessageImpl(Context& rContext); + +private: + //! Slider control type + ESliderType mSliderType; + + //! Value storage + TValue* mpValue; + + //! Minimum value + TValue mMin; + //! Maximum value + TValue mMax; +}; + +//! @} +} // namespace detail + +/****************************************************************************** + * + * SliderControlU32 + * + ******************************************************************************/ + +/** + * @brief Slider UI control + * + * @tparam TValue Property value type + */ +class SliderControlU32 : public detail::SliderControlImpl { +public: + /** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param pValue Value storage + * @param min Minimum value (inclusive) + * @param max Maximum value (inclusive) + */ + SliderControlU32(const String& rName, u32 id, u32* pValue, u32 min, u32 max) + : SliderControlImpl(rName, id, ESliderType_U32, pValue, min, max) { + } + + /** + * @brief Destructor + */ + virtual ~SliderControlU32() {} +}; + +/****************************************************************************** + * + * SliderControlS32 + * + ******************************************************************************/ + +/** + * @brief Slider UI control + * + * @tparam TValue Property value type + */ +class SliderControlS32 : public detail::SliderControlImpl { +public: + /** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param pValue Value storage + * @param min Minimum value (inclusive) + * @param max Maximum value (inclusive) + */ + SliderControlS32(const String& rName, u32 id, s32* pValue, s32 min, s32 max) + : SliderControlImpl(rName, id, ESliderType_S32, pValue, min, max) { + } + + /** + * @brief Destructor + */ + virtual ~SliderControlS32() {} +}; + +/****************************************************************************** + * + * SliderControlF32 + * + ******************************************************************************/ + +/** + * @brief Slider UI control + * + * @tparam TValue Property value type + */ +class SliderControlF32 : public detail::SliderControlImpl { +public: + /** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param pValue Value storage + * @param min Minimum value (inclusive) + * @param max Maximum value (inclusive) + */ + SliderControlF32(const String& rName, u32 id, f32* pValue, f32 min, f32 max) + : SliderControlImpl(rName, id, ESliderType_F32, pValue, min, max) { + } + + /** + * @brief Destructor + */ + virtual ~SliderControlF32() {} +}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/control/kiwiHostIOValueControl.cpp b/lib/libkiwi/hostio/control/kiwiHostIOValueControl.cpp new file mode 100644 index 0000000..2acf941 --- /dev/null +++ b/lib/libkiwi/hostio/control/kiwiHostIOValueControl.cpp @@ -0,0 +1,76 @@ +#include + +namespace kiwi { +namespace hostio { +namespace detail { + +/****************************************************************************** + * + * ValueControlImpl + * + ******************************************************************************/ + +/** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param type Value control type + * @param pValue Value storage + * @param min Minimum value (inclusive) + * @param max Maximum value (inclusive) + */ +template +ValueControlImpl::ValueControlImpl(const String& rName, u32 id, + EValueType type, TValue* pValue, + TValue min, TValue max) + : IControl(IControl::EType_Value, rName, id), + mValueType(type), + mpValue(pValue), + mMin(min), + mMax(max) { + + K_ASSERT_PTR(mpValue); +} + +/** + * @brief Generates object info for host client (derived implementation) + * + * @param rContext Message context + */ +template +void ValueControlImpl::GenMessageImpl(Context& rContext) { + K_ASSERT_PTR(mpValue); + MemStream& rStrm = rContext.GetMessageStream(); + + rStrm.Write_u8(GetType()); + rStrm.Write_string(GetName()); + rStrm.Write_u32(GetID()); + + rStrm.Write_u8(mValueType); + rStrm.Write_u32(BitCast(*mpValue)); + rStrm.Write_u32(BitCast(mMin)); + rStrm.Write_u32(BitCast(mMax)); +} + +/** + * @brief Handles property event from host client + * + * @param rEvent Event structure from the host + */ +template +void ValueControlImpl::ListenPropertyEvent( + const PropertyEvent& rEvent) { + + K_ASSERT_PTR(mpValue); + *mpValue = BitCast(rEvent.value); +} + +// Instantiate class templates +template class ValueControlImpl; +template class ValueControlImpl; +template class ValueControlImpl; + +} // namespace detail +} // namespace hostio +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/hostio/control/kiwiHostIOValueControl.h b/lib/libkiwi/hostio/control/kiwiHostIOValueControl.h new file mode 100644 index 0000000..c375ab2 --- /dev/null +++ b/lib/libkiwi/hostio/control/kiwiHostIOValueControl.h @@ -0,0 +1,190 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_VALUE_CONTROL_H +#define LIBKIWI_HOSTIO_HOST_IO_VALUE_CONTROL_H +#include +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +/****************************************************************************** + * + * ValueControlImpl + * + ******************************************************************************/ +namespace detail { +//! @addtogroup libkiwi_hostio +//! @{ + +/** + * @brief Value UI control + * + * @tparam TValue Property value type + */ +template class ValueControlImpl : public IControl { +public: + /** + * @brief Value control type + */ + enum EValueType { + EValueType_U32, //!< Unsigned 32-bit value + EValueType_S32, //!< Signed 32-bit value + EValueType_F32, //!< Floating point value + + EValueType_Max + }; + +public: + /** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param type Value control type + * @param pValue Value storage + * @param min Minimum value (inclusive) + * @param max Maximum value (inclusive) + */ + ValueControlImpl(const String& rName, u32 id, EValueType type, + TValue* pValue, TValue min, TValue max); + + /** + * @brief Destructor + */ + virtual ~ValueControlImpl() {} + + /** + * @brief Handles property event from host client + * + * @param rEvent Event structure from the host + */ + virtual void ListenPropertyEvent(const PropertyEvent& rEvent); + +private: + /** + * @brief Generates object info for host client (derived implementation) + * + * @param rContext Message context + */ + virtual void GenMessageImpl(Context& rContext); + +private: + //! Value control type + EValueType mValueType; + + //! Value storage + TValue* mpValue; + + //! Minimum value + TValue mMin; + //! Maximum value + TValue mMax; +}; + +//! @} +} // namespace detail + +/****************************************************************************** + * + * ValueControlU32 + * + ******************************************************************************/ + +/** + * @brief Value UI control + * + * @tparam TValue Property value type + */ +class ValueControlU32 : public detail::ValueControlImpl { +public: + /** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param pValue Value storage + * @param min Minimum value (inclusive) + * @param max Maximum value (inclusive) + */ + ValueControlU32(const String& rName, u32 id, u32* pValue, u32 min, u32 max) + : ValueControlImpl(rName, id, EValueType_U32, pValue, min, max) {} + + /** + * @brief Destructor + */ + virtual ~ValueControlU32() {} +}; + +/****************************************************************************** + * + * ValueControlS32 + * + ******************************************************************************/ + +/** + * @brief Value UI control + * + * @tparam TValue Property value type + */ +class ValueControlS32 : public detail::ValueControlImpl { +public: + /** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param pValue Value storage + * @param min Minimum value (inclusive) + * @param max Maximum value (inclusive) + */ + ValueControlS32(const String& rName, u32 id, s32* pValue, s32 min, s32 max) + : ValueControlImpl(rName, id, EValueType_S32, pValue, min, max) {} + + /** + * @brief Destructor + */ + virtual ~ValueControlS32() {} +}; + +/****************************************************************************** + * + * ValueControlF32 + * + ******************************************************************************/ + +/** + * @brief Value UI control + * + * @tparam TValue Property value type + */ +class ValueControlF32 : public detail::ValueControlImpl { +public: + /** + * @brief Constructor + * + * @param rName Name + * @param id Unique ID + * @param pValue Value storage + * @param min Minimum value (inclusive) + * @param max Maximum value (inclusive) + */ + ValueControlF32(const String& rName, u32 id, f32* pValue, f32 min, f32 max) + : ValueControlImpl(rName, id, EValueType_F32, pValue, min, max) {} + + /** + * @brief Destructor + */ + virtual ~ValueControlF32() {} +}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/kiwiHostIOContext.cpp b/lib/libkiwi/hostio/kiwiHostIOContext.cpp new file mode 100644 index 0000000..17f02be --- /dev/null +++ b/lib/libkiwi/hostio/kiwiHostIOContext.cpp @@ -0,0 +1,69 @@ +#include + +namespace kiwi { +namespace hostio { + +/** + * @brief Constructor + */ +Context::Context() : mpMessageBuffer(nullptr) { + mpMessageBuffer = new u8[MESSAGE_BUFFER_SIZE]; + K_ASSERT_PTR(mpMessageBuffer); + + mMessageStream.Open(mpMessageBuffer, MESSAGE_BUFFER_SIZE); +} + +/** + * @brief Destructor + */ +Context::~Context() { + delete[] mpMessageBuffer; + mpMessageBuffer = nullptr; +} + +/** + * @brief Resets the message context + */ +void Context::Reset() { + mMessageStream.Seek(ESeekDir_Begin, 0); +} + +/** + * @brief Starts generation of a node message + * + * @param rNode Host I/O node + */ +void Context::StartGenNode(const Reflexible& rNode) { + K_ASSERT_EX(!mMessageStream.IsEOF(), "GenMessage overflow"); + + mMessageStream.Write_u8(ECommand_StartGenNode); + mMessageStream.Write_string(rNode.GetName()); +} + +/** + * @brief Ends generation of a node message + * + * @param rNode Host I/O node + */ +void Context::EndGenNode(const Reflexible& rNode) { + K_ASSERT_EX(!mMessageStream.IsEOF(), "GenMessage overflow"); + + mMessageStream.Write_u8(ECommand_EndGenNode); +} + +/** + * @brief Generates a control message + * + * @param rControl Host I/O control + */ +void Context::GenControl(IControl& rControl) { + K_ASSERT_EX(!mMessageStream.IsEOF(), "GenMessage overflow"); + + mMessageStream.Write_u8(rControl.GetType()); + mMessageStream.Write_string(rControl.GetName()); + mMessageStream.Write_u32(rControl.GetID()); + rControl.GenMessage(*this); +} + +} // namespace hostio +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/hostio/kiwiHostIOContext.h b/lib/libkiwi/hostio/kiwiHostIOContext.h new file mode 100644 index 0000000..d9369f3 --- /dev/null +++ b/lib/libkiwi/hostio/kiwiHostIOContext.h @@ -0,0 +1,97 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_CONTEXT_H +#define LIBKIWI_HOSTIO_HOST_IO_CONTEXT_H +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +// Forward declarations +class IControl; +class Reflexible; + +/** + * @brief Host I/O server message context + */ +class Context { +public: + /** + * @brief Constructor + */ + Context(); + + /** + * @brief Destructor + */ + virtual ~Context(); + + /** + * @brief Resets the message context + */ + void Reset(); + + /** + * @brief Starts generation of a node message + * + * @param rNode Host I/O node + */ + void StartGenNode(const Reflexible& rNode); + /** + * @brief Ends generation of a node message + * + * @param rNode Host I/O node + */ + void EndGenNode(const Reflexible& rNode); + + /** + * @brief Generates a control message + * + * @param rControl Host I/O control + */ + void GenControl(IControl& rControl); + + /** + * @brief Accesses the message data stream + */ + MemStream& GetMessageStream() { + return mMessageStream; + } + /** + * @brief Accesses the message data stream (const-view) + */ + const MemStream& GetMessageStream() const { + return mMessageStream; + } + +private: + /** + * @brief Message command type + */ + enum ECommand { + ECommand_StartGenNode, //!< Begin node data + ECommand_EndGenNode, //!< End node data + + ECommand_Max + }; + +private: + //! Client message buffer size + static const u32 MESSAGE_BUFFER_SIZE = K_MEM_KB_TO_B(64); + +private: + //! Message data buffer + u8* mpMessageBuffer; + //! Message data stream + MemStream mMessageStream; +}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/kiwiHostIOEvent.h b/lib/libkiwi/hostio/kiwiHostIOEvent.h new file mode 100644 index 0000000..788228a --- /dev/null +++ b/lib/libkiwi/hostio/kiwiHostIOEvent.h @@ -0,0 +1,49 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_EVENT_H +#define LIBKIWI_HOSTIO_HOST_IO_EVENT_H +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +/** + * @brief Event from client PC to server + */ +struct Event { + /** + * @brief Event type + */ + enum EType { + EType_GenObjectInfo, //!< Host client is requesting the node layout + EType_Property, //!< Host client has changed a property + + EType_Max, + }; + + u8 type; //! Event type + u8 reserved[3]; //! Reserved space + u32 size; //! Event size +}; + +/** + * @brief Property change event + */ +struct PropertyEvent : Event { + //! Control ID designated for this event + u32 id; + + //! New property value + union { + u32 value; + }; +}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/kiwiHostIOIControl.cpp b/lib/libkiwi/hostio/kiwiHostIOIControl.cpp new file mode 100644 index 0000000..ed2cd4b --- /dev/null +++ b/lib/libkiwi/hostio/kiwiHostIOIControl.cpp @@ -0,0 +1,23 @@ +#include + +namespace kiwi { +namespace hostio { + +/** + * @brief Generates object info for host client + * + * @param rContext Message context + */ +void IControl::GenMessage(Context& rContext) { + MemStream& rStrm = rContext.GetMessageStream(); + + rStrm.Write_u8(GetType()); + rStrm.Write_string(GetName()); + rStrm.Write_u32(GetID()); + + // Generate derived control message + GenMessageImpl(rContext); +} + +} // namespace hostio +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/hostio/kiwiHostIOIControl.h b/lib/libkiwi/hostio/kiwiHostIOIControl.h new file mode 100644 index 0000000..cab4a34 --- /dev/null +++ b/lib/libkiwi/hostio/kiwiHostIOIControl.h @@ -0,0 +1,116 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_I_CONTROL_H +#define LIBKIWI_HOSTIO_HOST_IO_I_CONTROL_H +#include +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +/****************************************************************************** + * + * IControl + * + ******************************************************************************/ + +/** + * @brief UI control + */ +class IControl { +public: + /** + * @brief Control type + */ + enum EType { + EType_Label, //!< Text label + EType_Button, //!< Clickable button + EType_Value, //!< Editable value + EType_Slider, //!< Value slider + EType_CheckBox, //!< Check box options + EType_ComboBox, //!< Combo box options + EType_RadioButton, //!< Radio button options + EType_SendFile, //!< Send file to server + EType_RecvFile, //!< Receive file from server + + EType_Max + }; + +public: + /** + * @brief Constructor + * + * @param type Control type + * @param rName Name + * @param id Unique ID + */ + IControl(EType type, const String& rName, u32 id) + : mType(type), mName(rName), mId(id) {} + + /** + * @brief Destructor + */ + virtual ~IControl() {} + + /** + * @brief Generates object info for host client + * + * @param rContext Message context + */ + void GenMessage(Context& rContext); + + /** + * @brief Handles property event from host client + * + * @param rEvent Event structure from the host + */ + virtual void ListenPropertyEvent(const PropertyEvent& rEvent) {} + + /** + * @brief Accesses this control's type + */ + EType GetType() const { + return mType; + } + + /** + * @brief Accesses this control's name + */ + const String& GetName() const { + return mName; + } + + /** + * @brief Accesses this control's unique ID + */ + u32 GetID() const { + return mId; + } + +private: + /** + * @brief Generates object info for host client (derived implementation) + * + * @param rContext Message context + */ + virtual void GenMessageImpl(Context& rContext) {} + +private: + //! Control type (for host client) + EType mType; + //! Control name (for host client) + String mName; + //! Unique ID + u32 mId; +}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/kiwiHostIOReflexible.cpp b/lib/libkiwi/hostio/kiwiHostIOReflexible.cpp new file mode 100644 index 0000000..5340da3 --- /dev/null +++ b/lib/libkiwi/hostio/kiwiHostIOReflexible.cpp @@ -0,0 +1,64 @@ +#include + +namespace kiwi { +namespace hostio { + +/** + * @brief Generates object info for host client + * + * @param rContext Message context + */ +void Reflexible::GenMessage(Context& rContext) { + MemStream& rStrm = rContext.GetMessageStream(); + + rContext.StartGenNode(*this); + { + rStrm.Write_string(mName); + GenMessageImpl(rContext); + } + rContext.EndGenNode(*this); +} + +/** + * @brief Event callback + * + * @param pEvent Event structure from the host + */ +void Reflexible::OnEvent(const Event* pEvent) { + K_ASSERT_PTR(pEvent); + + switch (pEvent->type) { + case Event::EType_GenObjectInfo: { + GenMessage(Server::GetInstance().GetMessageContext()); + break; + } + + case Event::EType_Property: { + if (pEvent->size != sizeof(PropertyEvent)) { + K_LOG_EX("Wrong PropertyEvent size (%d)\n", pEvent->size); + return; + } + + const PropertyEvent* pPropertyEvent = + static_cast(pEvent); + + ListenPropertyEvent(*pPropertyEvent); + + // Property event may change at most one control ID + K_FOREACH (it, mControls) { + if ((*it)->GetID() == pPropertyEvent->id) { + (*it)->ListenPropertyEvent(*pPropertyEvent); + } + } + + // Target node could be further down the tree + K_FOREACH (it, mChildren) { + (*it)->ListenPropertyEvent(*pPropertyEvent); + } + break; + } + } +} + +} // namespace hostio +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/hostio/kiwiHostIOReflexible.h b/lib/libkiwi/hostio/kiwiHostIOReflexible.h new file mode 100644 index 0000000..26b89da --- /dev/null +++ b/lib/libkiwi/hostio/kiwiHostIOReflexible.h @@ -0,0 +1,110 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_REFLEXIBLE_H +#define LIBKIWI_HOSTIO_HOST_IO_REFLEXIBLE_H +#include +#include +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +// Forward declarations +class IControl; + +/** + * @brief Host I/O node + */ +class Reflexible { + friend class Server; + +public: + /** + * @brief Constructor + * + * @param rName Node name + */ + explicit Reflexible(const String& rName) : mName(rName) {} + + /** + * @brief Destructor + */ + virtual ~Reflexible() {} + + /** + * @brief Generates object info for host client + * + * @param rContext Message context + */ + void GenMessage(Context& rContext); + + /** + * @brief Handles property event from host client + * @note Property events automatically propogate to children + * + * @param rEvent Event structure from the host + */ + virtual void ListenPropertyEvent(const PropertyEvent& rEvent) {} + + /** + * @brief Adds a new UI control to this node + * + * @param pControl UI control + */ + void AddControl(IControl* pControl) { + K_ASSERT_PTR(pControl); + mControls.PushBack(pControl); + } + + /** + * @brief Adds a new child to this node + * + * @param pNode Child node + */ + void AddChild(Reflexible* pNode) { + K_ASSERT_PTR(pNode); + mChildren.PushBack(pNode); + } + + /** + * @brief Accesses this node's name + */ + const String& GetName() const { + return mName; + } + +private: + /** + * @brief Generates object info for host client (derived implementation) + * + * @param rContext Message context + */ + virtual void GenMessageImpl(Context& rContext) {} + + /** + * @brief Event callback + * + * @param pEvent Event structure from the host + */ + virtual void OnEvent(const Event* pEvent); + +protected: + //! Node name + String mName; + + //! UI controls + TList mControls; + //! Children nodes + TList mChildren; +}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/hostio/kiwiHostIOServer.cpp b/lib/libkiwi/hostio/kiwiHostIOServer.cpp new file mode 100644 index 0000000..c4761e3 --- /dev/null +++ b/lib/libkiwi/hostio/kiwiHostIOServer.cpp @@ -0,0 +1,178 @@ +#include + +#include + +namespace kiwi { +namespace hostio { + +K_DYNAMIC_SINGLETON_IMPL(Server); + +/** + * @brief Constructor + */ +Server::Server() + : mpRootNode(nullptr), + mpMainThread(nullptr), + mpServerSocket(nullptr), + mpClientSocket(nullptr) { + + mpMainThread = new Thread(ThreadFunc, *this); + K_ASSERT_PTR(mpMainThread); +} + +/** + * @brief Destructor + */ +Server::~Server() { + mpRootNode = nullptr; + + delete mpMainThread; + mpMainThread = nullptr; + + CloseServer(); + + delete mpClientSocket; + mpClientSocket = nullptr; +} + +/** + * @brief Initializes the server connection + */ +void Server::RestartServer() { + // Close any sockets + if (mpServerSocket != nullptr) { + CloseServer(); + } + + mpServerSocket = new SyncSocket(SO_PF_INET, SO_SOCK_STREAM); + K_ASSERT_PTR(mpServerSocket); + + // Default local IP address + mServerAddr = SockAddr4(port::HOST_IO); + + bool success = mpServerSocket->Bind(mServerAddr); + K_ASSERT(success); + + success = mpServerSocket->Listen(); + K_ASSERT(success); + + // Host address now has the correct IP + u16 port = mServerAddr.port; + mpServerSocket->GetHostAddr(mServerAddr); + mServerAddr.port = port; +} + +/** + * @brief Closes the server connections + */ +void Server::CloseServer() { + // Close server socket + if (mpServerSocket != nullptr) { + bool success = mpServerSocket->Shutdown(SO_SHUT_RDWR); + K_ASSERT(success); + + delete mpServerSocket; + mpServerSocket = nullptr; + } + + // Close client socket + if (mpClientSocket != nullptr) { + bool success = mpClientSocket->Shutdown(SO_SHUT_RDWR); + K_ASSERT(success); + + delete mpClientSocket; + mpClientSocket = nullptr; + } +} + +/** + * @brief Thread function + */ +void Server::ThreadFunc() { + while (true) { + RestartServer(); + K_ASSERT_PTR(mpServerSocket); + + K_LOG_EX("Host I/O listening on %s\n", + kiwi::ToString(mServerAddr).CStr()); + + // Server socket is non-blocking + do { + mpClientSocket = mpServerSocket->Accept(); + } while (LibSO::GetLastError() == SO_EWOULDBLOCK); + + K_LOG("Host I/O client connected!\n"); + + // Event loop returns on disconnect, which will restart the server + K_ASSERT_PTR(mpClientSocket); + EventLoop(); + } +} + +/** + * @brief Event handler loop + */ +void Server::EventLoop() { + K_ASSERT_PTR(mpClientSocket); + + while (true) { + // First four bytes specify the event data size + u32 eventSize = 0; + Optional nrecv = mpClientSocket->Recv(eventSize); + + // Connection failure + if (!nrecv) { + return; + } + + // Socket is blocking + if (*nrecv == 0) { + continue; + } + + // Sanity check packet size for corruption + K_ASSERT(eventSize < MAX_EVENT_BUFFER_SIZE); + Packet packet(eventSize); + + // Fill event packet data + while (!packet.IsWriteComplete()) { + // Optional nrecv = packet.Recv(*mpClientSocket); + + // if (!nrecv) { + // return; + // } + } + + // Can't process events without a node tree + if (mpRootNode == nullptr) { + continue; + } + + // Dispatch event to root node so it can propogate + const Event* pEvent = static_cast(packet.GetContent()); + mpRootNode->OnEvent(pEvent); + + // Root node may have generated a message in response + const MemStream& rStrm = mMessageContext.GetMessageStream(); + u32 msgSize = rStrm.GetSize(); + + // Send it off to the host client + if (msgSize > 0) { + Packet packet(msgSize); + + u32 written = packet.Write(rStrm.GetBuffer(), msgSize); + K_ASSERT(written == msgSize); + + while (!packet.IsReadComplete()) { + // Optional nsend = packet.Send(*mpClientSocket); + + // if (!nsend) { + // K_ASSERT_EX(false, "Send message error"); + // } + } + } + } +} + +} // namespace hostio +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/hostio/kiwiHostIOServer.h b/lib/libkiwi/hostio/kiwiHostIOServer.h new file mode 100644 index 0000000..23ab08c --- /dev/null +++ b/lib/libkiwi/hostio/kiwiHostIOServer.h @@ -0,0 +1,111 @@ +#ifndef LIBKIWI_HOSTIO_HOST_IO_SERVER_H +#define LIBKIWI_HOSTIO_HOST_IO_SERVER_H +#include +#include +#include +#include +#include +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_hostio +//! @{ +namespace hostio { +//! @addtogroup libkiwi_hostio +//! @{ + +//! Forward declarations +class Reflexible; + +/** + * @brief Host I/O server + */ +class Server : public DynamicSingleton { + friend class DynamicSingleton; + +public: + /** + * @brief Sets the root tree node + * + * @param rNode New root node + */ + void SetRootNode(Reflexible& rNode) { + mpRootNode = &rNode; + } + + /** + * @brief Accesses the server's IP address + */ + const SockAddr4& GetServerAddr() const { + return mServerAddr; + } + + /** + * @brief Accesses the message data context + */ + Context& GetMessageContext() { + return mMessageContext; + } + +private: + /** + * @brief Constructor + */ + Server(); + + /** + * @brief Destructor + */ + virtual ~Server(); + + /** + * @brief Initializes the server connection + */ + void RestartServer(); + + /** + * @brief Closes the server connections + */ + void CloseServer(); + + /** + * @brief Thread function + */ + void ThreadFunc(); + + /** + * @brief Event handler loop + */ + void EventLoop(); + +private: + //! Maximum event buffer size + static const u32 MAX_EVENT_BUFFER_SIZE = K_MEM_KB_TO_B(4); + +private: + //! Tree root node (not owning!!!) + Reflexible* mpRootNode; + + //! Main loop thread + Thread* mpMainThread; + + //! Server socket + SyncSocket* mpServerSocket; + //! Server address + SockAddr4 mServerAddr; + + //! Client (peer) socket + SyncSocket* mpClientSocket; + + //! Message context + Context mMessageContext; +}; + +//! @} +} // namespace hostio +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/k_config.h b/lib/libkiwi/k_config.h index fb2019b..2904129 100644 --- a/lib/libkiwi/k_config.h +++ b/lib/libkiwi/k_config.h @@ -18,6 +18,11 @@ #error Please define a build target! #endif +// Precompiled header +#if defined(LIBKIWI_TARGET_RVL) +#define LIBKIWI_PRECOMPILE +#endif + // Inline assembly macros #if defined(LIBKIWI_TARGET_RVL) // Hide from VSCode @@ -56,11 +61,36 @@ // 'typeof' #define K_TYPEOF(x) __typeof__(x) + // 'decltype' +#ifndef __INTELLISENSE__ #define K_DECLTYPE(x) __decltype__(x) +#else +#define K_DECLTYPE(x) decltype(x) +#endif // Primitive array length #define K_LENGTHOF(x) static_cast(sizeof((x)) / sizeof((x)[0])) +#define K_ARRAY_SIZE(x) K_LENGTHOF(x) + +// Stringitize +#define K_STRINGITIZE(x) __K_STRINGITIZE(x) +#define __K_STRINGITIZE(x) #x + +// CodeWarrior fun :) +#if defined(LIBKIWI_TARGET_RVL) +#pragma warning off(10548) +#pragma warning off(10580) +#endif + +// Memory conversion +#define K_MEM_KB_TO_B(X) ((X) * 1024) +#define K_MEM_B_TO_KB(X) ((X) / 1024) +#define K_MEM_B_TO_MB(X) ((X) / 1024 / 1024) + +#define K_MEM_KB_TO_B(X) ((X) * 1024) +#define K_MEM_MB_TO_B(X) ((X) * 1024 * 1024) +#define K_MEM_B_TO_MB(X) ((X) / 1024 / 1024) // C++ exclusive options #if defined(__cplusplus) @@ -75,6 +105,7 @@ // nullptr evalutes to NULL when not supported #if !defined(LIBKIWI_CPP1X) #define nullptr NULL +#define noexcept throw() #endif #endif // __cplusplus diff --git a/lib/libkiwi/k_types.h b/lib/libkiwi/k_types.h index 15b121d..39ec600 100644 --- a/lib/libkiwi/k_types.h +++ b/lib/libkiwi/k_types.h @@ -64,8 +64,7 @@ typedef void (*funcptr_t)(void); #undef RP_GET_INSTANCE #endif -#define RP_GET_INSTANCE(T) \ - (K_ASSERT(T::getInstance() != nullptr), T::getInstance()) +#define RP_GET_INSTANCE(T) (K_ASSERT_PTR(T::instance()), T::instance()) #endif @@ -76,7 +75,7 @@ typedef void (*funcptr_t)(void); * @param rContainer Container reference */ #define K_FOREACH(name, rContainer) \ - for (K_DECLTYPE(rContainer.Begin()) name = rContainer.Begin(); \ - name != rContainer.End(); ++name) + for (K_DECLTYPE((rContainer).Begin()) name = (rContainer).Begin(); \ + name != (rContainer).End(); ++name) #endif // LIBKIWI_TYPES_H diff --git a/lib/libkiwi/libkiwi.h b/lib/libkiwi/libkiwi.h index ac8b4c5..0f0fcee 100644 --- a/lib/libkiwi/libkiwi.h +++ b/lib/libkiwi/libkiwi.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -32,13 +33,26 @@ #include #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -46,22 +60,30 @@ #include #include #include +#include #include #include #include #include -#include +#include +#include +#include +#include #include -#include #include #include #include #include #include +#include +#include +#include #include #include #include -#include +#include +#include +#include #include #include #include @@ -69,10 +91,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include diff --git a/lib/libkiwi/math/kiwiAlgorithm.h b/lib/libkiwi/math/kiwiAlgorithm.h index 7a5e2a6..7f7895b 100644 --- a/lib/libkiwi/math/kiwiAlgorithm.h +++ b/lib/libkiwi/math/kiwiAlgorithm.h @@ -1,6 +1,7 @@ #ifndef LIBKIWI_MATH_ALGORITHM_H #define LIBKIWI_MATH_ALGORITHM_H #include +#include #include @@ -165,6 +166,81 @@ K_INLINE const T* AddToPtr(const void* pAddr, ptrdiff_t ofs) { return reinterpret_cast(static_cast(pAddr) + ofs); } +/** + * @brief Performs the Fisher-Yates shuffle algorithm to generate a random + * permutation of the specified values + * + * @tparam TElem Shuffled array element type + * @tparam ElemNum Length of shuffled array + * + * @param[in,out] rArray Input array + */ +template +K_INLINE void Shuffle(TElem (&rArray)[ElemNum]) { + K_ASSERT(ElemNum > 0); + + Random r; + for (u32 i = ElemNum - 1; i >= 1; i--) { + u32 j = r.NextU32(i + 1); + std::swap(rArray[j], rArray[i]); + } +} + +/** + * @brief Performs the Fisher-Yates shuffle algorithm to generate a random + * permutation of numbers in the range [0, {array-length}) + * + * @tparam TElem Shuffled array element type + * @tparam ElemNum Length of shuffled array + * + * @param[out] rArray Input array + */ +template +K_INLINE void InitAndShuffle(TElem (&rArray)[ElemNum]) { + for (u32 i = 0; i < ElemNum; i++) { + rArray[i] = i; + } + + Shuffle(rArray); +} + +/** + * @brief "Un-shuffles" a previously shuffled array by moving values matching + * the specified keys back to their original position in the array. + * + * @tparam TKey Key element type + * @tparam KeyNum Length of keys array + * @tparam TElem Shuffled array element type + * @tparam ElemNum Length of shuffled array + * + * @param rKeys Keys to unshuffle + * @param[in, out] rArray Shuffled array + */ +template +K_INLINE void UnShuffle(const TKey (&rKeys)[KeyNum], TElem (&rArray)[ElemNum]) { + while (true) { + bool changed = false; + + for (u32 i = 0; i < ElemNum; i++) { + if (rArray[i] == i) { + continue; + } + + // TODO: Binary search through the keys? + for (u32 j = 0; j < KeyNum; j++) { + if (rArray[i] == rKeys[j]) { + std::swap(rArray[i], rArray[rArray[i]]); + changed = true; + } + } + } + + if (!changed) { + break; + } + } +} + //! @} } // namespace //! @} diff --git a/lib/libkiwi/math/kiwiMath.cpp b/lib/libkiwi/math/kiwiMath.cpp new file mode 100644 index 0000000..9b1917d --- /dev/null +++ b/lib/libkiwi/math/kiwiMath.cpp @@ -0,0 +1,381 @@ +#include + +#include + +#include +#include + +namespace kiwi { +namespace detail { + +/****************************************************************************** + * + * Constants + * + ******************************************************************************/ + +/** + * @brief pi + */ +template const T TMath::PI = 3.14159265358979323846; + +/** + * @brief 2pi (tau) + */ +template const T TMath::TWO_PI = 2 * PI; + +/** + * @brief pi/2 + */ +template const T TMath::PI_HALF = PI / 2; + +/** + * @brief pi/4 + */ +template const T TMath::PI_QUARTER = PI / 4; + +/** + * @brief ln(2) + */ +template const T TMath::LN2 = 0; + +/** + * @brief 1/ln(2) + */ +template const T TMath::LN2_INV = 0; + +/****************************************************************************** + * + * Common implementation + * + ******************************************************************************/ + +/** + * @brief Calculates the absolute value of the input value + * + * @param x Input value + */ +template T TMath::Abs(T x) { + return x < 0 ? Neg(x) : x; +} + +/** + * @brief Inverts the input value + * + * @param x Input value + */ +template T TMath::Inv(T x) { + return One() / x; +} + +/** + * @brief Calculates the square root of the input value + * + * @param x Input value + */ +template T TMath::Sqrt(T x) { + return nw4r::math::FSqrt(static_cast(x)); +} + +/** + * @brief Calculates a power of the input value + * + * @param base Base value + * @param exp Exponent + */ +template T TMath::Pow(T base, T exp) { + f64 result = std::pow(static_cast(base), static_cast(exp)); + return static_cast(result); +} + +/** + * @brief Calculates the sine of the input angle, in degrees + * + * @param x Input angle + */ +template T TMath::SinDeg(T x) { + f32 result = nw4r::math::SinDeg(static_cast(x)); + return static_cast(result); +} + +/** + * @brief Calculates the cosine of the input angle, in degrees + * + * @param x Input angle + */ +template T TMath::CosDeg(T x) { + f32 result = nw4r::math::CosDeg(static_cast(x)); + return static_cast(result); +} + +/** + * @brief Calculates the tangent of the input angle, in degrees + * + * @param x Input angle + */ +template T TMath::TanDeg(T x) { + f32 result = nw4r::math::TanDeg(static_cast(x)); + return static_cast(result); +} + +/** + * @brief Calculates the sine of the input angle, in radians + * + * @param x Input angle + */ +template T TMath::SinRad(T x) { + f32 result = nw4r::math::SinRad(static_cast(x)); + return static_cast(result); +} + +/** + * @brief Calculates the cosine of the input angle, in radians + * + * @param x Input angle + */ +template T TMath::CosRad(T x) { + f32 result = nw4r::math::CosRad(static_cast(x)); + return static_cast(result); +} + +/** + * @brief Calculates the tangent of the input angle, in radians + * + * @param x Input angle + */ +template T TMath::TanRad(T x) { + f32 result = nw4r::math::TanRad(static_cast(x)); + return static_cast(result); +} + +/****************************************************************************** + * + * Mathi (s32) + * + ******************************************************************************/ + +/** + * @brief Represents the smallest possible value + */ +template <> s32 TMath::MinNumber() { + return 0x80000000; +} + +/** + * @brief Represents the largest possible value + */ +template <> s32 TMath::MaxNumber() { + return 0x7FFFFFFF; +} + +/** + * @brief Represents the numerical constant Infinity + */ +template <> s32 TMath::Inf() { + K_NOT_IMPLEMENTED(); + return 0; +} + +/** + * @brief Represents a Quiet NaN + */ +template <> s32 TMath::QNaN() { + K_NOT_IMPLEMENTED(); + return 0; +} + +/** + * @brief Represents a Signaling NaN + */ +template <> s32 TMath::SNaN() { + K_NOT_IMPLEMENTED(); + return 0; +} + +/** + * @brief Represents the smallest difference between representable values + */ +template <> s32 TMath::Epsilon() { + K_NOT_IMPLEMENTED(); + return 0; +} + +/****************************************************************************** + * + * Mathu (u32) + * + ******************************************************************************/ + +/** + * @brief Represents the smallest possible value + */ +template <> u32 TMath::MinNumber() { + return 0; +} + +/** + * @brief Represents the largest possible value + */ +template <> u32 TMath::MaxNumber() { + return 0xFFFFFFFF; +} + +/** + * @brief Represents the numerical constant Infinity + */ +template <> u32 TMath::Inf() { + K_NOT_IMPLEMENTED(); + return 0; +} + +/** + * @brief Represents a Quiet NaN + */ +template <> u32 TMath::QNaN() { + K_NOT_IMPLEMENTED(); + return 0; +} + +/** + * @brief Represents a Signaling NaN + */ +template <> u32 TMath::SNaN() { + K_NOT_IMPLEMENTED(); + return 0; +} + +/** + * @brief Represents the smallest difference between representable values + */ +template <> u32 TMath::Epsilon() { + K_NOT_IMPLEMENTED(); + return 0; +} + +/****************************************************************************** + * + * Mathf (f32) + * + ******************************************************************************/ + +/** + * @brief Represents the smallest possible value + */ +template <> f32 TMath::MinNumber() { + return 1.17549435082228750797e-38f; +} + +/** + * @brief Represents the largest possible value + */ +template <> f32 TMath::MaxNumber() { + return 3.40282346638528859812e+38f; +} + +/** + * @brief Represents the numerical constant Infinity + */ +template <> f32 TMath::Inf() { + return BitCast(0x7FF00000); +} + +/** + * @brief Represents a Quiet NaN + */ +template <> f32 TMath::QNaN() { + return BitCast(0x7FC00000); +} + +/** + * @brief Represents a Signaling NaN + */ +template <> f32 TMath::SNaN() { + return BitCast(0x7FF00000); +} + +/** + * @brief Represents the smallest difference between representable values + */ +template <> f32 TMath::Epsilon() { + return 1.1920928955078125e-07f; +} + +/** + * @brief Inverts the input value + * + * @param x Input value + */ +template <> f32 TMath::Inv(f32 x) { + return nw4r::math::FInv(x); +} + +/** + * @brief Calculates the absolute value of the input value + * + * @param x Input value + */ +template <> f32 TMath::Abs(f32 x) { + return nw4r::math::FAbs(x); +} + +/****************************************************************************** + * + * Mathd (f64) + * + ******************************************************************************/ + +/** + * @brief Represents the smallest possible value + */ +template <> f64 TMath::MinNumber() { + return 2.22507385850720138309e-308l; +} + +/** + * @brief Represents the largest possible value + */ +template <> f64 TMath::MaxNumber() { + return 1.79769313486231570815e+308l; +} + +/** + * @brief Represents the numerical constant Infinity + */ +template <> f64 TMath::Inf() { + return BitCast(0x7FF0000000000000); +} + +/** + * @brief Represents a Quiet NaN + */ +template <> f64 TMath::QNaN() { + return BitCast(0x7FC0000000000000); +} + +/** + * @brief Represents a Signaling NaN + */ +template <> f64 TMath::SNaN() { + return BitCast(0x7FF0000000000000); +} + +/** + * @brief Represents the smallest difference between representable values + */ +template <> f64 TMath::Epsilon() { + return 2.22044604925031308085e-16l; +} + +/****************************************************************************** + * + * Instantiate class templates + * + ******************************************************************************/ + +template class TMath; +template class TMath; +template class TMath; +template class TMath; + +} // namespace detail +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/math/kiwiMath.h b/lib/libkiwi/math/kiwiMath.h new file mode 100644 index 0000000..8361a93 --- /dev/null +++ b/lib/libkiwi/math/kiwiMath.h @@ -0,0 +1,237 @@ +#ifndef LIBKIWI_MATH_MATH_H +#define LIBKIWI_MATH_MATH_H +#include + +namespace kiwi { +//! @addtogroup libkiwi_math +//! @{ + +namespace detail { +//! @addtogroup libkiwi_math +//! @{ + +/** + * @brief Primitive math utilities + * + * @tparam T Operand type + */ +template class TMath { +public: + /** + * @name Constants + */ + /**@{*/ + /** + * @brief Represents the numerical constant zero + */ + static T Zero() { + return static_cast(0); + } + /** + * @brief Represents the numerical constant one + */ + static T One() { + return static_cast(1); + } + + /** + * @brief Represents the numerical constant pi + */ + static T Pi() { + return PI; + } + /** + * @brief Represents the numerical constant 2pi + */ + static T TwoPi() { + return TWO_PI; + } + /** + * @brief Represents the numerical constant Tau (2pi) + */ + static T Tau() { + return TWO_PI; + } + + /** + * @brief Represents the numerical constant pi/2 + */ + static T PiHalf() { + return PI_HALF; + } + /** + * @brief Represents the numerical constant pi/4 + */ + static T PiQuart() { + return PI_QUARTER; + } + + /** + * @brief Represents the numerical constant ln(2) + */ + static T Ln2() { + return LN2; + } + /** + * @brief Represents the numerical constant 1/ln(2) + */ + static T Ln2Inv() { + return LN2_INV; + } + + /** + * @brief Represents the smallest possible value + */ + static T MinNumber(); + /** + * @brief Represents the largest possible value + */ + static T MaxNumber(); + + /** + * @brief Represents the numerical constant Infinity + */ + static T Inf(); + /** + * @brief Represents a Quiet NaN + */ + static T QNaN(); + /** + * @brief Represents a Signaling NaN + */ + static T SNaN(); + + /** + * @brief Represents the smallest difference between representable values + */ + static T Epsilon(); + /**@}*/ + + /** + * @name Basic operations + */ + /**@{*/ + /** + * @brief Calculates the sign of the input value + * + * @param x Input value + */ + static T Sign(T x) { + return x < 0 ? -1 : 1; + } + + /** + * @brief Calculates the absolute value of the input value + * + * @param x Input value + */ + static T Abs(T x); + + /** + * @brief Negates the input value + * + * @param x Input value + */ + static T Neg(T x) { + return -x; + } + + /** + * @brief Inverts the input value + * + * @param x Input value + */ + static T Inv(T x); + /**@}*/ + + /** + * @name Power functions + */ + /**@{*/ + /** + * @brief Calculates the square root of the input value + * + * @param x Input value + */ + static T Sqrt(T x); + + /** + * @brief Calculates a power of the input value + * + * @param base Base value + * @param exp Exponent + */ + static T Pow(T base, T exp); + /**@}*/ + + /** + * @name Trigonometric functions + */ + /**@{*/ + /** + * @brief Calculates the sine of the input angle, in degrees + * + * @param x Input angle + */ + static T SinDeg(T x); + /** + * @brief Calculates the cosine of the input angle, in degrees + * + * @param x Input angle + */ + static T CosDeg(T x); + /** + * @brief Calculates the tangent of the input angle, in degrees + * + * @param x Input angle + */ + static T TanDeg(T x); + + /** + * @brief Calculates the sine of the input angle, in radians + * + * @param x Input angle + */ + static T SinRad(T x); + /** + * @brief Calculates the cosine of the input angle, in radians + * + * @param x Input angle + */ + static T CosRad(T x); + /** + * @brief Calculates the tangent of the input angle, in radians + * + * @param x Input angle + */ + static T TanRad(T x); + /**@}*/ + +private: + //! pi + static const T PI; + //! 2pi + static const T TWO_PI; + //! pi/2 + static const T PI_HALF; + //! pi/4 + static const T PI_QUARTER; + + //! ln(2) + static const T LN2; + //! 1/ln(2) + static const T LN2_INV; +}; + +//! @} +} // namespace detail + +typedef detail::TMath Mathi; +typedef detail::TMath Mathu; +typedef detail::TMath Mathf; +typedef detail::TMath Mathd; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/math/kiwiVector.cpp b/lib/libkiwi/math/kiwiVector.cpp new file mode 100644 index 0000000..95d486d --- /dev/null +++ b/lib/libkiwi/math/kiwiVector.cpp @@ -0,0 +1,152 @@ +#include + +namespace kiwi { + +/****************************************************************************** + * + * Vec2f + * + ******************************************************************************/ + +/** + * @brief Zero vector + */ +const Vec2f Vec2f::ZERO(0.0f, 0.0f); + +/** + * @brief Unit vector pointing along the X-axis + */ +const Vec2f Vec2f::UX(1.0f, 0.0f); + +/** + * @brief Unit vector pointing along the Y-axis + */ +const Vec2f Vec2f::UY(0.0f, 1.0f); + +/** + * @brief Constructor + * + * @param pArray Component array + */ +Vec2f::Vec2f(const f32 pArray[2]) { + K_ASSERT_PTR(pArray); + + x = pArray[0]; + y = pArray[1]; +} + +/** + * @brief Gets the length/magnitude of the vector + */ +f32 Vec2f::Length() const { + return Mathf::Sqrt(Dot(*this)); +} + +/** + * @brief Scales the vector to have a magnitude of one + * + * @return f32 Original vector magnitude + */ +f32 Vec2f::Normalize() { + f32 length = Length(); + + if (length > 0.0f) { + *this /= length; + } + + return length; +} + +/** + * @brief Computes the dot product against another vector + * + * @param rOther Other vector + */ +f32 Vec2f::Dot(const Vec2f& rOther) const { + return x * rOther.x + y * rOther.y; +} + +/****************************************************************************** + * + * Vec3f + * + ******************************************************************************/ + +/** + * @brief Zero vector + */ +const Vec3f Vec3f::ZERO(0.0f, 0.0f, 0.0f); + +/** + * @brief Unit vector pointing along the X-axis + */ +const Vec3f Vec3f::UX(1.0f, 0.0f, 0.0f); + +/** + * @brief Unit vector pointing along the Y-axis + */ +const Vec3f Vec3f::UY(0.0f, 1.0f, 0.0f); + +/** + * @brief Unit vector pointing along the Z-axis + */ +const Vec3f Vec3f::UZ(0.0f, 0.0f, 1.0f); + +/** + * @brief Constructor + * + * @param pOther SDK vector + */ +Vec3f::Vec3f(const Vec* pOther) { + K_ASSERT_PTR(pOther); + + x = pOther->x; + y = pOther->y; + z = pOther->z; +} + +/** + * @brief Constructor + * + * @param pArray Component array + */ +Vec3f::Vec3f(const f32 pArray[3]) { + K_ASSERT_PTR(pArray); + + x = pArray[0]; + y = pArray[1]; + z = pArray[2]; +} + +/** + * @brief Gets the length/magnitude of the vector + */ +f32 Vec3f::Length() const { + return Mathf::Sqrt(Dot(*this)); +} + +/** + * @brief Scales the vector to have a length of one + * + * @return f32 Original vector length + */ +f32 Vec3f::Normalize() { + f32 length = Length(); + + if (length > 0.0f) { + *this /= length; + } + + return length; +} + +/** + * @brief Computes the dot product against another vector + * + * @param rOther Other vector + */ +f32 Vec3f::Dot(const Vec3f& rOther) const { + return x * rOther.x + y * rOther.y + z * rOther.z; +} + +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/math/kiwiVector.h b/lib/libkiwi/math/kiwiVector.h new file mode 100644 index 0000000..ddac2d3 --- /dev/null +++ b/lib/libkiwi/math/kiwiVector.h @@ -0,0 +1,171 @@ +#ifndef LIBKIWI_MATH_VECTOR_H +#define LIBKIWI_MATH_VECTOR_H +#include + +#include + +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_math +//! @{ + +/** + * @brief 3D, floating-point vector + */ +class Vec2f : public EGG::Vector2f { +public: + //! Zero vector + static const Vec2f ZERO; + + //! Unit vector pointing along the X-axis + static const Vec2f UX; + //! Unit vector pointing along the Y-axis + static const Vec2f UY; + +public: + /** + * @brief Constructor + */ + Vec2f() : EGG::Vector2f(0.0f, 0.0f) {} + + /** + * @brief Constructor + * + * @param fx X-component + * @param fy Y-component + */ + Vec2f(f32 fx, f32 fy) : EGG::Vector2f(fx, fy) {} + + /** + * @brief Constructor + * + * @param rOther EGG vector + */ + Vec2f(const EGG::Vector2f& rOther) : EGG::Vector2f(rOther) {} + + /** + * @brief Constructor + * + * @param rOther NW4R vector + */ + Vec2f(const nw4r::math::VEC2& rOther) : EGG::Vector2f(rOther) {} + + /** + * @brief Constructor + * + * @param pArray Component array + */ + Vec2f(const f32 pArray[2]); + + /** + * @brief Gets the length/magnitude of the vector + */ + f32 Length() const; + + /** + * @brief Scales the vector to have a magnitude of one + * + * @return f32 Original vector magnitude + */ + f32 Normalize(); + + /** + * @brief Computes the dot product against another vector + * + * @param rOther Other vector + */ + f32 Dot(const Vec2f& rOther) const; +}; + +/** + * @brief 3D, floating-point vector + */ +class Vec3f : public EGG::Vector3f { +public: + //! Zero vector + static const Vec3f ZERO; + + //! Unit vector pointing along the X-axis + static const Vec3f UX; + //! Unit vector pointing along the Y-axis + static const Vec3f UY; + //! Unit vector pointing along the Z-axis + static const Vec3f UZ; + +public: + operator Vec*() { + return reinterpret_cast(this); + } + operator const Vec*() const { + return reinterpret_cast(this); + } + + /** + * @brief Constructor + */ + Vec3f() : EGG::Vector3f(0.0f, 0.0f, 0.0f) {} + + /** + * @brief Constructor + * + * @param fx X-component + * @param fy Y-component + * @param fz Z-component + */ + Vec3f(f32 fx, f32 fy, f32 fz) : EGG::Vector3f(fx, fy, fz) {} + + /** + * @brief Constructor + * + * @param rOther EGG vector + */ + Vec3f(const EGG::Vector3f& rOther) : EGG::Vector3f(rOther) {} + + /** + * @brief Constructor + * + * @param rOther NW4R vector + */ + Vec3f(const nw4r::math::VEC3& rOther) : EGG::Vector3f(rOther) {} + + /** + * @brief Constructor + * + * @param pOther SDK vector + */ + Vec3f(const Vec* pOther); + + /** + * @brief Constructor + * + * @param pArray Component array + */ + Vec3f(const f32 pArray[3]); + + /** + * @brief Gets the length/magnitude of the vector + */ + f32 Length() const; + + /** + * @brief Scales the vector to have a magnitude of one + * + * @return f32 Original vector magnitude + */ + f32 Normalize(); + + /** + * @brief Computes the dot product against another vector + * + * @param rOther Other vector + */ + f32 Dot(const Vec3f& rOther) const; +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/kiwiAsyncSocket.cpp b/lib/libkiwi/net/kiwiAsyncSocket.cpp index a6f6399..da227e3 100644 --- a/lib/libkiwi/net/kiwiAsyncSocket.cpp +++ b/lib/libkiwi/net/kiwiAsyncSocket.cpp @@ -20,7 +20,7 @@ u8 AsyncSocket::sSocketThreadStack[scThreadStackSize]; /** * @brief Open async sockets */ -TList AsyncSocket::sSocketList; +TList AsyncSocket::sSocketList; /** * @brief Async receive operation @@ -191,10 +191,9 @@ void* AsyncSocket::ThreadFunc(void* pArg) { // Update all open sockets while (true) { - for (TList::Iterator it = sSocketList.Begin(); - it != sSocketList.End(); it++) { - K_ASSERT(it->IsOpen()); - it->Calc(); + K_FOREACH (it, sSocketList) { + K_ASSERT((*it)->IsOpen()); + (*it)->Calc(); } } @@ -238,10 +237,6 @@ AsyncSocket::AsyncSocket(SOSocket socket, SOProtoFamily family, SOSockType type) * @brief Prepares socket for async operation */ void AsyncSocket::Initialize() { - // Make socket non-blocking - bool success = SetBlocking(false); - K_ASSERT(success); - // Thread needs to see this socket sSocketList.PushBack(this); @@ -361,7 +356,7 @@ void AsyncSocket::CalcRecv() { } // Find next incomplete job (FIFO) - RecvJob& rJob = mRecvJobs.Front(); + RecvJob& rJob = *mRecvJobs.Front(); K_ASSERT_EX(!rJob.IsComplete(), "Completed job should be removed"); // Attempt to complete job @@ -384,7 +379,7 @@ void AsyncSocket::CalcSend() { } // Find next incomplete job (FIFO) - SendJob& rJob = mSendJobs.Front(); + SendJob& rJob = *mSendJobs.Front(); K_ASSERT_EX(!rJob.IsComplete(), "Completed job should be removed"); // Attempt to complete job diff --git a/lib/libkiwi/net/kiwiAsyncSocket.h b/lib/libkiwi/net/kiwiAsyncSocket.h index 80ae73a..6ac2430 100644 --- a/lib/libkiwi/net/kiwiAsyncSocket.h +++ b/lib/libkiwi/net/kiwiAsyncSocket.h @@ -2,7 +2,7 @@ #define LIBKIWI_NET_ASYNC_SOCKET_H #include #include -#include +#include #include @@ -11,7 +11,7 @@ namespace kiwi { //! @{ /** - * @brief Asynchronous (non-blocking) socket + * @brief Asynchronous socket */ class AsyncSocket : public SocketBase { public: @@ -137,8 +137,8 @@ class AsyncSocket : public SocketBase { volatile EState mState; //!< Current async task SockAddrAny mPeer; //!< Peer address - TList mRecvJobs; //!< Active receive jobs - TList mSendJobs; //!< Active send jobs + TList mRecvJobs; //!< Active receive jobs + TList mSendJobs; //!< Active send jobs Callback mpConnectCallback; //!< Connect callback void* mpConnectCallbackArg; //!< Connect callback user argument @@ -154,7 +154,7 @@ class AsyncSocket : public SocketBase { static u8 sSocketThreadStack[scThreadStackSize]; //! Open async sockets - static TList sSocketList; + static TList sSocketList; }; //! @} diff --git a/lib/libkiwi/net/kiwiEmuRichPresenceClient.cpp b/lib/libkiwi/net/kiwiEmuRichPresenceClient.cpp index 174e24f..e44d0d8 100644 --- a/lib/libkiwi/net/kiwiEmuRichPresenceClient.cpp +++ b/lib/libkiwi/net/kiwiEmuRichPresenceClient.cpp @@ -23,7 +23,7 @@ enum { */ u64 EmuRichPresenceClient::GetTimeNow() const { if (!IsConnected()) { - return; + return 0; } TVector input; diff --git a/lib/libkiwi/net/kiwiHttpRequest.cpp b/lib/libkiwi/net/kiwiHttpRequest.cpp index d277ca7..996eb04 100644 --- a/lib/libkiwi/net/kiwiHttpRequest.cpp +++ b/lib/libkiwi/net/kiwiHttpRequest.cpp @@ -7,12 +7,12 @@ namespace kiwi { /** * @brief HTTP request method names */ -const String HttpRequest::METHOD_NAMES[EMethod_Max] = {"GET", "POST"}; +const char* HttpRequest::METHOD_NAMES[EMethod_Max] = {"GET", "POST"}; /** * @brief HTTP protocol version */ -const String HttpRequest::PROTOCOL_VERSION = "HTTP/1.1"; +const char* HttpRequest::PROTOCOL_VERSION = "HTTP/1.1"; /** * @brief Constructor @@ -173,16 +173,16 @@ bool HttpRequest::Request() { K_FOREACH (it, mParams) { // Parameters delimited by ampersand String fmt = it == mParams.Begin() ? "?%s=%s" : "&%s=%s"; - request += Format(fmt, it.Key().CStr(), it.Value().CStr()); + request += Format(fmt, it->key.CStr(), it->value.CStr()); } // Finish request line - request = Format("%s %s %s\n", METHOD_NAMES[mMethod].CStr(), request.CStr(), - PROTOCOL_VERSION.CStr()); + request = Format("%s %s %s\n", METHOD_NAMES[mMethod], request.CStr(), + PROTOCOL_VERSION); // Build header fields K_FOREACH (it, mHeader) { - request += Format("%s: %s\n", it.Key().CStr(), it.Value().CStr()); + request += Format("%s: %s\n", it->key.CStr(), it->value.CStr()); } // Request ends with extra newline @@ -289,8 +289,8 @@ bool HttpRequest::Receive() { } // Extract status code - int num = - std::sscanf(lines[0], PROTOCOL_VERSION + " %d", &mResponse.status); + int num = std::sscanf(lines[0], Format("%s %%d", PROTOCOL_VERSION).CStr(), + &mResponse.status); if (num != 1) { mResponse.error = EHttpErr_BadResponse; mResponse.exError = LibSO::GetLastError(); diff --git a/lib/libkiwi/net/kiwiHttpRequest.h b/lib/libkiwi/net/kiwiHttpRequest.h index 66d56c2..4759f91 100644 --- a/lib/libkiwi/net/kiwiHttpRequest.h +++ b/lib/libkiwi/net/kiwiHttpRequest.h @@ -66,11 +66,11 @@ struct HttpResponse { HttpResponse() : error(EHttpErr_Success), exError(0), status(EHttpStatus_None) {} - EHttpErr error; //!< Error code - s32 exError; //!< Internal error code - EHttpStatus status; //!< Status code - TMap header; //!< Response header - String body; //!< Response body/payload + EHttpErr error; //!< Error code + s32 exError; //!< Internal error code + EHttpStatus status; //!< Status code + THashMap header; //!< Response header + String body; //!< Response body/payload }; /** @@ -227,9 +227,9 @@ class HttpRequest { static const int TEMP_BUFFER_SIZE = 512; //! HTTP request method names - static const String METHOD_NAMES[EMethod_Max]; + static const char* METHOD_NAMES[EMethod_Max]; //! HTTP protocol version - static const String PROTOCOL_VERSION; + static const char* PROTOCOL_VERSION; private: String mHost; //!< Server host name @@ -241,8 +241,8 @@ class HttpRequest { HttpResponse mResponse; //!< Server response u32 mTimeOut; //!< Connection timeout - TMap mParams; //!< URL parameters - TMap mHeader; //!< Header fields + THashMap mParams; //!< URL parameters + THashMap mHeader; //!< Header fields Callback mpCallback; //!< Response callback void* mpCallbackArg; //!< Callback user argument diff --git a/lib/libkiwi/net/kiwiPacket.h b/lib/libkiwi/net/kiwiPacket.h index 6f4e796..6e90ad3 100644 --- a/lib/libkiwi/net/kiwiPacket.h +++ b/lib/libkiwi/net/kiwiPacket.h @@ -2,6 +2,7 @@ #define LIBKIWI_NET_PACKET_H #include #include +#include #include #include @@ -26,7 +27,7 @@ class Packet { */ Packet(u32 size, const SockAddrAny* pAddr = nullptr) : mpBuffer(nullptr), mBufferSize(0), mReadOffset(0), mWriteOffset(0) { - OSInitMutex(&mBufferMutex); + Alloc(size); if (pAddr != nullptr) { @@ -178,9 +179,9 @@ class Packet { void Clear(); protected: - u8* mpBuffer; //!< Message buffer - u32 mBufferSize; //!< Message buffer size - OSMutex mBufferMutex; //!< Buffer access mutex + u8* mpBuffer; //!< Message buffer + u32 mBufferSize; //!< Message buffer size + Mutex mBufferMutex; //!< Buffer access mutex s32 mReadOffset; //!< Buffer read index s32 mWriteOffset; //!< Buffer write index diff --git a/lib/libkiwi/net/kiwiPortRegistry.h b/lib/libkiwi/net/kiwiPortRegistry.h new file mode 100644 index 0000000..ae8e7d1 --- /dev/null +++ b/lib/libkiwi/net/kiwiPortRegistry.h @@ -0,0 +1,20 @@ +#ifndef LIBKIWI_NET_PORT_REGISTRY_H +#define LIBKIWI_NET_PORT_REGISTRY_H +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ +namespace port { +//! @addtogroup libkiwi_net +//! @{ + +//! Port reserved for host I/O communications +static const u32 HOST_IO = 50000; + +//! @} +} // namespace port +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/kiwiRichPresenceMgr.cpp b/lib/libkiwi/net/kiwiRichPresenceMgr.cpp index 99a4459..2854760 100644 --- a/lib/libkiwi/net/kiwiRichPresenceMgr.cpp +++ b/lib/libkiwi/net/kiwiRichPresenceMgr.cpp @@ -88,7 +88,7 @@ void RichPresenceMgr::AlarmCallbackFunc(OSAlarm* pAlarm, OSContext* pCtx) { return; } - K_ASSERT(r.mpClient != nullptr); + K_ASSERT_PTR(r.mpClient); // Allow user to update activity r.mpProfile->AlarmCallback(*r.mpClient); diff --git a/lib/libkiwi/net/kiwiSocketBase.cpp b/lib/libkiwi/net/kiwiSocketBase.cpp index 30907e6..65ad4d7 100644 --- a/lib/libkiwi/net/kiwiSocketBase.cpp +++ b/lib/libkiwi/net/kiwiSocketBase.cpp @@ -19,6 +19,10 @@ SocketBase::SocketBase(SOProtoFamily family, SOSockType type) // By default, enable port reuse bool success = SetReuseAddr(true); K_ASSERT(success); + + // Always disable IOP blocking + success = SetBlockingIOP(false); + K_ASSERT(success); } /** @@ -32,6 +36,10 @@ SocketBase::SocketBase(SOSocket socket, SOProtoFamily family, SOSockType type) : mHandle(socket), mFamily(family), mType(type) { K_ASSERT_EX(IsOpen(), "Invalid socket descriptor provided"); + + // Always disable IOP blocking + bool success = SetBlockingIOP(false); + K_ASSERT(success); } /** @@ -149,35 +157,6 @@ bool SocketBase::GetPeerAddr(SockAddrAny& rAddr) const { return LibSO::GetPeerName(mHandle, rAddr) == SO_SUCCESS; } -/** - * @brief Tests whether socket is blocking - */ -bool SocketBase::IsBlocking() const { - K_ASSERT(IsOpen()); - - s32 flags = LibSO::Fcntl(mHandle, SO_F_GETFL, 0); - return (flags & SO_O_NONBLOCK) == 0; -} - -/** - * @brief Toggles socket blocking - * - * @param enable Whether to enable blocking - * @return Success - */ -bool SocketBase::SetBlocking(bool enable) const { - K_ASSERT(IsOpen()); - - s32 flags = LibSO::Fcntl(mHandle, SO_F_GETFL, 0); - if (enable) { - flags &= ~SO_O_NONBLOCK; - } else { - flags |= SO_O_NONBLOCK; - } - - return LibSO::Fcntl(mHandle, SO_F_SETFL, flags) >= 0; -} - /** * @brief Toggles port reuse * @@ -354,4 +333,33 @@ Optional SocketBase::SendBytesTo(const void* pSrc, u32 len, return kiwi::nullopt; } +/** + * @brief Tests whether socket is kernel-blocking (at the IOP level) + */ +bool SocketBase::IsBlockingIOP() const { + K_ASSERT(IsOpen()); + + s32 flags = LibSO::Fcntl(mHandle, SO_F_GETFL, 0); + return (flags & SO_O_NONBLOCK) == 0; +} + +/** + * @brief Toggles socket kernel-blocking (at the IOP level) + * + * @param enable Whether to enable blocking + * @return Success + */ +bool SocketBase::SetBlockingIOP(bool enable) const { + K_ASSERT(IsOpen()); + + s32 flags = LibSO::Fcntl(mHandle, SO_F_GETFL, 0); + if (enable) { + flags &= ~SO_O_NONBLOCK; + } else { + flags |= SO_O_NONBLOCK; + } + + return LibSO::Fcntl(mHandle, SO_F_SETFL, flags) >= 0; +} + } // namespace kiwi diff --git a/lib/libkiwi/net/kiwiSocketBase.h b/lib/libkiwi/net/kiwiSocketBase.h index 122b92d..00dbd99 100644 --- a/lib/libkiwi/net/kiwiSocketBase.h +++ b/lib/libkiwi/net/kiwiSocketBase.h @@ -128,18 +128,6 @@ class SocketBase : private NonCopyable { */ bool GetPeerAddr(SockAddrAny& rAddr) const; - /** - * @brief Tests whether socket is blocking - */ - bool IsBlocking() const; - /** - * @brief Toggles socket blocking - * - * @param enable Whether to enable blocking - * @return Success - */ - bool SetBlocking(bool enable) const; - /** * @brief Toggles port reuse * @@ -329,6 +317,18 @@ class SocketBase : private NonCopyable { */ SocketBase(SOSocket socket, SOProtoFamily family, SOSockType type); + /** + * @brief Tests whether socket is kernel-blocking (at the IOP level) + */ + bool IsBlockingIOP() const; + /** + * @brief Toggles socket kernel-blocking (at the IOP level) + * + * @param enable Whether to enable blocking + * @return Success + */ + bool SetBlockingIOP(bool enable) const; + private: /** * @brief Receives data and records sender address (internal implementation) diff --git a/lib/libkiwi/net/kiwiSyncSocket.cpp b/lib/libkiwi/net/kiwiSyncSocket.cpp index 9b56606..33b54f0 100644 --- a/lib/libkiwi/net/kiwiSyncSocket.cpp +++ b/lib/libkiwi/net/kiwiSyncSocket.cpp @@ -14,14 +14,20 @@ bool SyncSocket::Connect(const SockAddrAny& rAddr, Callback pCallback, void* pArg) { K_ASSERT(IsOpen()); - s32 result = LibSO::Connect(mHandle, rAddr); - bool success = result == SO_SUCCESS || result == SO_EISCONN; + while (true) { + s32 result = LibSO::Connect(mHandle, rAddr); + bool success = result == SO_SUCCESS || result == SO_EISCONN; - if (pCallback != nullptr) { - pCallback(LibSO::GetLastError(), pArg); - } + if (mIsBlocking && LibSO::GetLastError() == SO_EWOULDBLOCK) { + continue; + } + + if (pCallback != nullptr) { + pCallback(LibSO::GetLastError(), pArg); + } - return success; + return success; + } } /** @@ -34,22 +40,29 @@ bool SyncSocket::Connect(const SockAddrAny& rAddr, Callback pCallback, SyncSocket* SyncSocket::Accept(AcceptCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); - SyncSocket* pPeer = nullptr; - SockAddr4 addr; // TODO: Will forcing ipv4 cause problems? + while (true) { + // TODO: Will forcing ipv4 cause problems? + SyncSocket* pPeer = nullptr; + SockAddr4 addr; - s32 fd = LibSO::Accept(mHandle, addr); + s32 fd = LibSO::Accept(mHandle, addr); - // Result code is the peer descriptor - if (fd > 0) { - pPeer = new SyncSocket(fd, mFamily, mType); - K_ASSERT_PTR(pPeer); - } + if (mIsBlocking && LibSO::GetLastError() == SO_EWOULDBLOCK) { + continue; + } - if (pCallback != nullptr) { - pCallback(LibSO::GetLastError(), pPeer, addr, pArg); - } + // Result code is the peer descriptor + if (fd > 0) { + pPeer = new SyncSocket(fd, mFamily, mType); + K_ASSERT_PTR(pPeer); + } - return pPeer; + if (pCallback != nullptr) { + pCallback(LibSO::GetLastError(), pPeer, addr, pArg); + } + + return pPeer; + } } /** @@ -74,21 +87,28 @@ SOResult SyncSocket::RecvImpl(void* pDst, u32 len, u32& rRecv, rRecv = 0; SockAddr4 addr; - s32 result = LibSO::RecvFrom(mHandle, pDst, len, 0, addr); - if (result > 0) { - rRecv += result; - } + while (true) { + s32 result = LibSO::RecvFrom(mHandle, pDst, len, 0, addr); + if (result > 0) { + rRecv += result; + } - if (pAddr != nullptr) { - *pAddr = addr; - } + if (mIsBlocking && + (LibSO::GetLastError() == SO_EWOULDBLOCK || rRecv < len)) { + continue; + } - if (pCallback != nullptr) { - pCallback(LibSO::GetLastError(), pArg); - } + if (pAddr != nullptr) { + *pAddr = addr; + } + + if (pCallback != nullptr) { + pCallback(LibSO::GetLastError(), pArg); + } - // Successful if some amount of bytes read - return result >= 0 ? SO_SUCCESS : static_cast(result); + // Successful if some amount of bytes read + return result >= 0 ? SO_SUCCESS : static_cast(result); + } } /** @@ -112,23 +132,31 @@ SOResult SyncSocket::SendImpl(const void* pSrc, u32 len, u32& rSend, rSend = 0; - s32 result; - if (pAddr != nullptr) { - result = LibSO::SendTo(mHandle, pSrc, len - rSend, 0, *pAddr); - } else { - result = LibSO::Send(mHandle, pSrc, len - rSend, 0); - } + while (true) { + s32 result; - if (result > 0) { - rSend += result; - } + if (pAddr != nullptr) { + result = LibSO::SendTo(mHandle, pSrc, len - rSend, 0, *pAddr); + } else { + result = LibSO::Send(mHandle, pSrc, len - rSend, 0); + } - if (pCallback != nullptr) { - pCallback(LibSO::GetLastError(), pArg); - } + if (result > 0) { + rSend += result; + } + + if (mIsBlocking && + (LibSO::GetLastError() == SO_EWOULDBLOCK || rSend < len)) { + continue; + } - // Successful if some amount of bytes sent - return result >= 0 ? SO_SUCCESS : static_cast(result); + if (pCallback != nullptr) { + pCallback(LibSO::GetLastError(), pArg); + } + + // Successful if some amount of bytes sent + return result >= 0 ? SO_SUCCESS : static_cast(result); + } } } // namespace kiwi diff --git a/lib/libkiwi/net/kiwiSyncSocket.h b/lib/libkiwi/net/kiwiSyncSocket.h index 3287a7f..9e54cef 100644 --- a/lib/libkiwi/net/kiwiSyncSocket.h +++ b/lib/libkiwi/net/kiwiSyncSocket.h @@ -8,7 +8,7 @@ namespace kiwi { //! @{ /** - * @brief Synchronous (blocking) socket + * @brief Synchronous socket */ class SyncSocket : public SocketBase { public: @@ -19,7 +19,7 @@ class SyncSocket : public SocketBase { * @param type Socket type */ SyncSocket(SOProtoFamily family, SOSockType type) - : SocketBase(family, type) {} + : SocketBase(family, type), mIsBlocking(true) {} /** * @brief Connects to a peer @@ -42,6 +42,21 @@ class SyncSocket : public SocketBase { virtual SyncSocket* Accept(AcceptCallback pCallback = nullptr, void* pArg = nullptr); + /** + * @brief Tests whether the socket is thread-blocking (at the PPC level) + */ + bool IsBlocking() const { + return mIsBlocking; + } + /** + * @brief Toggles socket thread-blocking (at the PPC level) + * + * @param enable Whether to enable blocking + */ + void SetBlocking(bool enable) { + mIsBlocking = enable; + } + private: /** * @brief Constructor @@ -82,6 +97,10 @@ class SyncSocket : public SocketBase { virtual SOResult SendImpl(const void* pSrc, u32 len, u32& rSend, const SockAddrAny* pAddr, Callback pCallback, void* pArg); + +private: + //! Whether socket operations are thread-blocking (at the PPC level) + bool mIsBlocking; }; //! @} diff --git a/lib/libkiwi/net/kiwiWebSocket.cpp b/lib/libkiwi/net/kiwiWebSocket.cpp index ea2e80f..f659503 100644 --- a/lib/libkiwi/net/kiwiWebSocket.cpp +++ b/lib/libkiwi/net/kiwiWebSocket.cpp @@ -217,7 +217,7 @@ void WebSocket::SocketCallbackFunc(SOResult result, void* pArg) { K_LOG("SocketCallbackFunc...\n"); K_LOG_EX("result:%d, mState:%d\n", result, p->mState); - K_ASSERT(false); + K_UNREACHABLE(); // Dispatch state machine switch (p->mState) { diff --git a/lib/libkiwi/prim/kiwiAlgorithm.h b/lib/libkiwi/prim/kiwiAlgorithm.h new file mode 100644 index 0000000..a26cd23 --- /dev/null +++ b/lib/libkiwi/prim/kiwiAlgorithm.h @@ -0,0 +1,99 @@ +#ifndef LIBKIWI_PRIM_ALGORITHM_H +#define LIBKIWI_PRIM_ALGORITHM_H +#include +#include +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_prim +//! @{ + +namespace detail { +//! @addtogroup libkiwi_prim +//! @{ + +/** + * @brief Sorts the specified range of random-access iterators (internal + * implementation) + * + * @tparam TIterator Container iterator type (only random-access is supported) + * @tparam TComparator Iterator comparator type + * @param begin Beginning of the range + * @param end End of the range + * @param comparator Iterator comparator function + */ +template +K_INLINE void SortImpl(TIterator begin, TIterator end, TComparator comparator, + RandomAccessIteratorTag); + +/** + * @brief Sorts the specified range of bi-directional iterators (internal + * implementation) + * + * @tparam TIterator Container iterator type (only random-access is supported) + * @tparam TComparator Iterator comparator type + * @param begin Beginning of the range + * @param end End of the range + * @param comparator Iterator comparator function + */ +template +K_INLINE void SortImpl(TIterator begin, TIterator end, TComparator comparator, + BiDirectionalIteratorTag); + +//! @} +} // namespace detail + +/** + * @brief Comparator function for sorting containers in ascending order + * + * @tparam T Container element type + * @param rLhs Left-hand side element + * @param rRhs Right-hand side element + * @return Whether the left-hand side element should appear first in the order + */ +template K_INLINE bool Less(const T& rLhs, const T& rRhs) { + return rLhs < rRhs; +} + +/** + * @brief Comparator function for sorting containers in ascending order + * + * @tparam T Container element type + * @param rLhs Left-hand side element + * @param rRhs Right-hand side element + * @return Whether the left-hand side element should appear first in the order + */ +template K_INLINE bool Greater(const T& rLhs, const T& rRhs) { + return rLhs > rRhs; +} + +/** + * @brief Sorts the specified range of a collection using the provided + * comparator function to order elements + * @details The sort order defaults to ascending order when a comparator is not + * specified. + * + * @tparam TIterator Container iterator type (only random-access is supported) + * @tparam TComparator Iterator comparator type + * @param begin Beginning of the range + * @param end End of the range + * @param comparator Iterator comparator function + */ +template +K_INLINE void Sort(TIterator begin, TIterator end, + TComparator comparator = kiwi::Less) { + + detail::SortImpl(begin, end, comparator, typename TIterator::TagType()); +} + +//! @} +} // namespace kiwi + +// Implementation header +#ifndef LIBKIWI_PRIM_ALGORITHM_IMPL_HPP +#include +#endif + +#endif diff --git a/lib/libkiwi/prim/kiwiAlgorithmImpl.hpp b/lib/libkiwi/prim/kiwiAlgorithmImpl.hpp new file mode 100644 index 0000000..7c7fa31 --- /dev/null +++ b/lib/libkiwi/prim/kiwiAlgorithmImpl.hpp @@ -0,0 +1,71 @@ +// Implementation header +#ifndef LIBKIWI_PRIM_ALGORITHM_IMPL_HPP +#define LIBKIWI_PRIM_ALGORITHM_IMPL_HPP + +// Declaration header +#ifndef LIBKIWI_PRIM_ALGORITHM_H +#include +#endif + +namespace kiwi { +namespace detail { + +/** + * @brief Sorts the specified range of random-access iterators (internal + * implementation) + * + * @tparam TIterator Container iterator type (only random-access is supported) + * @tparam TComparator Iterator comparator type + * @param begin Beginning of the range + * @param end End of the range + * @param comparator Iterator comparator function + */ +template +K_INLINE void SortImpl(TIterator begin, TIterator end, TComparator comparator, + RandomAccessIteratorTag) { + + // Standard library implements random-access sort + std::sort(begin, end, comparator); +} + +/** + * @brief Sorts the specified range of bi-directional iterators (internal + * implementation) + * + * @tparam TIterator Container iterator type (only random-access is supported) + * @tparam TComparator Iterator comparator type + * @param begin Beginning of the range + * @param end End of the range + * @param comparator Iterator comparator function + */ +template +K_INLINE void SortImpl(TIterator begin, TIterator end, TComparator comparator, + BiDirectionalIteratorTag) { + + // Simple bubble sort + while (true) { + bool changed = false; + + for (TIterator it = begin; it != end; ++it) { + TIterator check = it; + ++check; + + for (; check != end; ++check) { + if (comparator(*check, *it)) { + std::swap(*it, *check); + changed = true; + break; + } + } + } + + if (!changed) { + break; + } + } +} + +} // namespace detail +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/prim/kiwiArray.h b/lib/libkiwi/prim/kiwiArray.h index 782e833..9c8282e 100644 --- a/lib/libkiwi/prim/kiwiArray.h +++ b/lib/libkiwi/prim/kiwiArray.h @@ -2,45 +2,208 @@ #define LIBKIWI_PRIM_ARRAY_H #include #include +#include +#include +#include namespace kiwi { //! @addtogroup libkiwi_prim //! @{ +namespace detail { +//! @addtogroup libkiwi_prim +//! @{ + /** - * @brief 1D array of fixed size + * @brief Common array implementation * - * @tparam T Array element type + * @tparam T Array value type * @tparam N Array size */ -template class TArray { +template class TArrayImpl { public: /** - * @brief Access array length + * @brief Array iterator */ - int Length() const { + template + class IteratorImpl + : public RandomAccessIterator, TValue> { + + // Allow promotion to const iterator + friend class IteratorImpl::type>; + + public: + /** + * @brief Constructor + * + * @param pArray Parent array + * @param index Array position + */ + IteratorImpl(TArrayImpl* pArray, int index) + : mpArray(pArray), mIndex(index) { + + K_ASSERT_PTR(mpArray); + K_ASSERT(mIndex >= 0); + K_ASSERT(mIndex <= mpArray->Size()); + } + /** + * @brief Constructor + * + * @param rOther Iterator + */ + template + IteratorImpl(const IteratorImpl& rOther) + : mpArray(rOther.mpArray), mIndex(rOther.mIndex) { + + K_ASSERT_PTR(mpArray); + K_ASSERT(mIndex >= 0); + K_ASSERT(mIndex <= mpArray->Size()); + } + + /** + * @brief Increments the iterator once + */ + void Next() { + mIndex++; + } + /** + * @brief Decrements the iterator once + */ + void Prev() { + mIndex--; + } + + /** + * @brief Advances the iterator by a specified amount + * + * @param n Amount to move + */ + void Move(int n) { + mIndex += n; + } + + /** + * @brief Computes the distance between iterators + * + * @param other Other iterator + */ + template + int Dist(IteratorImpl other) const { + K_ASSERT(mpArray == other.mpArray); + return other.mIndex - mIndex; + } + + /** + * @brief Accesses the iterator's value + */ + TValue& Get() { + K_ASSERT_PTR(mpArray); + K_ASSERT_EX(mIndex >= 0 && mIndex < mpArray->Size(), + "Invalid iterator (index: %d)", mIndex); + + return mpArray->At(mIndex); + } + + /** + * @brief Tests two iterators for equality + * + * @param other Other iterator + */ + template + bool Equals(IteratorImpl other) const { + return mpArray == other.mpArray && mIndex == other.mIndex; + } + + private: + //! Parent array + TArrayImpl* mpArray; + //! Array position + int mIndex; + }; + + // Autogen typedefs and const/reverse getters + K_GEN_ITERATOR_TYPEDEFS(IteratorImpl, T); + K_GEN_ITERATOR_METHODS(TArrayImpl); + +public: + /** + * @brief Gets an iterator to the beginning of the array + */ + Iterator Begin() { + return Iterator(this, 0); + } + /** + * @brief Gets an iterator to the end of the array + */ + Iterator End() { + return Iterator(this, Size()); + } + + /** + * @brief Accesses the array's size + */ + int Size() const { return N; } /** - * @brief Access array element by index + * @brief Gets a reference to the first element of the array + */ + T& Front() { + return mData[0]; + } + /** + * @brief Gets a reference to the first element of the array (const-view) + */ + const T& Front() const { + return mData[0]; + } + + /** + * @brief Gets a reference to the last element of the array + */ + T& Back() { + return mData[Size() - 1]; + } + /** + * @brief Gets a reference to the last element of the array (const-view) + */ + const T& Back() const { + return mData[Size() - 1]; + } + + /** + * @brief Accesses an array element by index * * @param i Element index */ T& At(int i) { - K_ASSERT(i >= 0 && i < N); + K_ASSERT(i >= 0 && i < Size()); return mData[i]; } /** - * @brief Access array element by index (read-only) + * @brief Accesses an array element by index (read-only) * * @param i Element index */ const T& At(int i) const { - K_ASSERT(i >= 0 && i < N); + K_ASSERT(i >= 0 && i < Size()); return mData[i]; } + /** + * @brief Accesses the underlying element data + */ + T* Data() { + return mData; + } + /** + * @brief Accesses the underlying element data (const-view) + */ + const T* Data() const { + return mData; + } + // clang-format off T& operator[](int i) { return At(i); } T& operator()(int i) { return At(i); } @@ -48,80 +211,98 @@ template class TArray { const T& operator()(int i) const { return At(i); } // clang-format on -private: - T mData[N]; // Internal array +protected: + //! Underlying array data + T mData[N]; }; +//! @} +} // namespace detail + /** - * @brief 2D array of fixed size + * @brief 1D array of fixed size + * @details Same concept as std::array * * @tparam T Array element type - * @tparam M Outer array size - * @tparam N Inner array size + * @tparam N Array size */ -template class TArray2D { +template class TArray : public detail::TArrayImpl { public: - /** - * @brief Access array length - */ - int Length() const { - return M; - } + typedef detail::TArrayImpl BaseType; + // Propogate iterator types up + typedef typename BaseType::Iterator Iterator; + typedef typename BaseType::ConstIterator ConstIterator; + typedef typename BaseType::RevIterator RevIterator; + typedef typename BaseType::ConstRevIterator ConstRevIterator; + +public: /** - * @brief Access array element by index + * @brief Sorts elements in the list using the specified comparator function + * @details The sort order defaults to ascending order when a comparator is + * not specified. * - * @param i Element index + * @param pComparator Function used to compare two elements. Returns true + * when the first element is less-than the second element. */ - TArray& At(int i) { - K_ASSERT(i >= 0 && i < N); - return mData[i]; + void Sort(bool (*pComparator)(const T&, const T&) = kiwi::Less) { + kiwi::Sort(BaseType::Begin(), BaseType::End(), pComparator); } +}; + +/** + * @brief 2D array of fixed size + * + * @tparam T Array element type + * @tparam M Outer array size (number of rows) + * @tparam N Inner array size (number of columns) + */ +template +class TArray2D : public detail::TArrayImpl, M> { +public: + typedef detail::TArrayImpl, M> BaseType; + + // Propogate iterator types up + typedef typename BaseType::Iterator Iterator; + typedef typename BaseType::ConstIterator ConstIterator; + typedef typename BaseType::RevIterator RevIterator; + typedef typename BaseType::ConstRevIterator ConstRevIterator; + +public: /** - * @brief Access array element by index (read-only) - * - * @param i Element index + * @brief Gets the inner arrays' size */ - const TArray& At(int i) const { - K_ASSERT(i >= 0 && i < N); - return mData[i]; + int InnerSize() const { + return N; } /** - * @brief Access array element by index + * @brief Accesses an array element by index * * @param i Element row * @param j Element column */ T& At(int i, int j) { - K_ASSERT(i >= 0 && i < M); - K_ASSERT(j >= 0 && j < N); - return mData[i][j]; + K_ASSERT(i >= 0 && i < BaseType::Size()); + K_ASSERT(j >= 0 && j < InnerSize()); + return BaseType::mData[i][j]; } /** - * @brief Access array element by index (read-only) + * @brief Accesses an array element by index (read-only) * * @param i Element row * @param j Element column */ const T& At(int i, int j) const { - K_ASSERT(i >= 0 && i < M); - K_ASSERT(j >= 0 && j < N); - return mData[i][j]; + K_ASSERT(i >= 0 && i < BaseType::Size()); + K_ASSERT(j >= 0 && j < InnerSize()); + return BaseType::mData[i][j]; } // clang-format off - TArray& operator[](int i) { return At(i); } - TArray& operator()(int i) { return At(i); } - const TArray& operator[](int i) const { return At(i); } - const TArray& operator()(int i) const { return At(i); } - - TArray& operator()(int i, int j) { return At(i).At(j); } - const TArray& operator()(int i, int j) const { return At(i).At(j); } + T& operator()(int i, int j) { return At(i, j); } + const T& operator()(int i, int j) const { return At(i, j); } // clang-format on - -private: - TArray mData[M]; // Internal array }; //! @} diff --git a/lib/libkiwi/prim/kiwiBitCast.h b/lib/libkiwi/prim/kiwiBitCast.h index a143619..14477f1 100644 --- a/lib/libkiwi/prim/kiwiBitCast.h +++ b/lib/libkiwi/prim/kiwiBitCast.h @@ -1,5 +1,5 @@ -#ifndef LIBKIWI_PRIM_BITCAST_H -#define LIBKIWI_PRIM_BITCAST_H +#ifndef LIBKIWI_PRIM_BIT_CAST_H +#define LIBKIWI_PRIM_BIT_CAST_H #include namespace kiwi { diff --git a/lib/libkiwi/prim/kiwiHashMap.cpp b/lib/libkiwi/prim/kiwiHashMap.cpp index 5789fa0..6d5b684 100644 --- a/lib/libkiwi/prim/kiwiHashMap.cpp +++ b/lib/libkiwi/prim/kiwiHashMap.cpp @@ -9,7 +9,7 @@ namespace { * @param x Initial value * @param r Number of bits to rotate */ -u32 rotl32(register u32 x, register int r) { +K_INLINE u32 rotl32(register u32 x, register int r) { // clang-format off asm { rotlw x, x, r @@ -24,11 +24,11 @@ u32 rotl32(register u32 x, register int r) { * * @param h Hash block */ -u32 fmix32(u32 h) { +K_INLINE u32 fmix32(u32 h) { h ^= h >> 16; - h *= 0x85ebca6b; + h *= 0x85EBCA6B; h ^= h >> 13; - h *= 0xc2b2ae35; + h *= 0xC2B2AE35; h ^= h >> 16; return h; @@ -43,12 +43,12 @@ u32 fmix32(u32 h) { * @param pKey Key * @param len Key length */ -hash_t HashImpl(const void* pKey, s32 len) { - K_ASSERT(pKey != nullptr); +hash_t MurmurHash(const void* pKey, s32 len) { + K_ASSERT_PTR(pKey); K_ASSERT(len > 0); const u8* pData = static_cast(pKey); - int nblocks = len / 4; + s32 nblocks = len / 4; u32 h1 = 0xC70F6907; u32 c1 = 0xCC9E2D51; @@ -71,18 +71,28 @@ hash_t HashImpl(const void* pKey, s32 len) { u32 k1 = 0; switch (len & 3) { - case 3: k1 ^= pTail[2] << 16; - case 2: k1 ^= pTail[1] << 8; - case 1: + case 3: { + k1 ^= pTail[2] << 16; + // fallthrough + } + + case 2: { + k1 ^= pTail[1] << 8; + // fallthrough + } + + case 1: { k1 ^= pTail[0]; k1 *= c1; k1 = rotl32(k1, 15); k1 *= c2; h1 ^= k1; + // fallthrough + } }; h1 ^= len; - return fmix32(h1); + return static_cast(fmix32(h1)); } } // namespace kiwi diff --git a/lib/libkiwi/prim/kiwiHashMap.h b/lib/libkiwi/prim/kiwiHashMap.h index f13cd5d..2ff8760 100644 --- a/lib/libkiwi/prim/kiwiHashMap.h +++ b/lib/libkiwi/prim/kiwiHashMap.h @@ -1,16 +1,22 @@ -#ifndef LIBKIWI_PRIM_HASHMAP_H -#define LIBKIWI_PRIM_HASHMAP_H +#ifndef LIBKIWI_PRIM_HASH_MAP_H +#define LIBKIWI_PRIM_HASH_MAP_H #include -#include +#include #include +#include namespace kiwi { //! @addtogroup libkiwi_prim //! @{ -// Hash value type +// Forward declarations +namespace detail { +template struct THashBucket; +} // namespace detail + +//! Hash value type typedef u32 hash_t; -// Largest representable hash +//! Largest representable hash static const hash_t HASH_MAX = (1 << (sizeof(hash_t) * 8)) - 1; /** @@ -20,7 +26,7 @@ static const hash_t HASH_MAX = (1 << (sizeof(hash_t) * 8)) - 1; * @param pKey Key * @param len Key length */ -hash_t HashImpl(const void* pKey, s32 len); +hash_t MurmurHash(const void* pKey, s32 len); /** * @brief Hashes a key of any type @@ -29,135 +35,134 @@ hash_t HashImpl(const void* pKey, s32 len); * @param rKey Key */ template K_INLINE hash_t Hash(const TKey& rKey) { - return HashImpl(&rKey, sizeof(TKey)); + return MurmurHash(&rKey, sizeof(TKey)); } /** - * @brief Key/value pair map + * @brief Hash map item * - * @todo Track load factor, expand + re-hash when high + * @tparam TKey Item key type + * @tparam TValue Item value type */ -template class TMap { - friend class ConstIterator; // Access 'Bucket' structure +template struct THashItem { + //! Key storage + TKey key; + //! Value storage + TValue value; -public: - // Default bucket count - static const u32 scDefaultCapacity = 32; - -private: - struct Bucket { - /** - * @brief Constructor - */ - Bucket() : used(false), pChained(nullptr) {} + /** + * @brief Constructor + * + * @param rKey Item key + */ + THashItem(const TKey& rKey) : key(rKey) {} - /** - * @brief Destructor - */ - ~Bucket() { - // Recurse - delete pChained; - } + /** + * @brief Constructor + * + * @param rKey Item key + * @param rValue Item value + */ + THashItem(const TKey& rKey, const TValue& rValue) + : key(rKey), value(rValue) {} +}; - Optional key; - Optional value; +/** + * @brief Key/value dictionary + * @details Same concept as std::unordered_map + * + * @tparam TKey Key type + * @tparam TValue Value type + */ +template class THashMap { +public: + // For readability + typedef detail::THashBucket HashBucket; + typedef typename HashBucket::Item HashItem; - bool used; // Bucket is in use - Bucket* pChained; // Chains - }; + /** + * @brief Hash map iterator + */ + template + class IteratorImpl : public ForwardIterator, TItem> { + friend class THashMap; -public: - class ConstIterator { - template friend class TMap; + // Allow promotion to const iterator + friend class IteratorImpl::type>; - private: + public: /** * @brief Constructor * - * @param capacity Map capacity - * @param pBuckets Array of buckets + * @param pHashMap Parent hash map + * @param index Bucket index */ - ConstIterator(u32 capacity, const Bucket* pBuckets) - : mIndex(0), - mCapacity(capacity), - mpBuckets(pBuckets), - mpIter(mpBuckets) { - // Find first non-empty value - if (mpIter != nullptr && !mpIter->used) { - ++*this; - } - } + IteratorImpl(THashMap* pHashMap, u32 index); - public: /** - * @brief Pre-increment operator - */ - ConstIterator& operator++(); - /** - * @brief Post-increment operator + * @brief Constructor + * + * @param rOther Iterator */ - ConstIterator operator++(int) { - ConstIterator clone(*this); - ++*this; - return clone; + template + IteratorImpl(const IteratorImpl& rOther) + : mpHashMap(rOther.mpHashMap), + mIndex(rOther.mIndex), + mpBucket(rOther.mpBucket) { + + K_ASSERT_PTR(mpHashMap); + K_ASSERT(mIndex <= mpHashMap->Capacity()); } /** - * @brief Get key from this element + * @brief Increments the iterator once */ - const TKey& Key() const { - K_ASSERT(mpIter != nullptr); - return *mpIter->key; - } - /** - * @brief Get value from this element - */ - const TValue& Value() const { - K_ASSERT(mpIter != nullptr); - return *mpIter->value; - } + void Next(); /** - * @brief Gets pointer to this value + * @brief Accesses the iterator's value */ - const TValue* operator->() const { - return &Value(); + TItem& Get() { + K_ASSERT_PTR(mpBucket); + K_ASSERT_EX(mpBucket->item.HasValue(), "Invalid iterator"); + + return *mpBucket->item; } + /** - * @brief Gets reference to this value + * @brief Tests two iterators for equality + * + * @param other Other iterator */ - const TValue& operator*() const { - return Value(); - } - - bool operator==(ConstIterator rhs) const { - return mpIter == rhs.mpIter; - } - bool operator!=(ConstIterator rhs) const { - return mpIter != rhs.mpIter; + template + bool Equals(IteratorImpl other) const { + return mpBucket == other.mpBucket; } private: - u32 mIndex; // Current bucket index - u32 mCapacity; // Maximum bucket index + //! Parent hash map + THashMap* mpHashMap; + //! Hash map position + u32 mIndex; - const Bucket* mpBuckets; // Current bucket root - const Bucket* mpIter; // Current bucket chain + //! Current bucket object + HashBucket* mpBucket; }; + // Autogen typedefs and const/reverse getters + K_GEN_ITERATOR_TYPEDEFS(IteratorImpl, HashItem); + K_GEN_ITERATOR_METHODS(THashMap); + public: /** * @brief Constructor - * - * @param capacity Starting number of buckets */ - TMap(u32 capacity = scDefaultCapacity) - : mSize(0), mCapacity(capacity), mpBuckets(nullptr) { + THashMap() : mSize(0), mCapacity(scDefaultCapacity), mpBuckets(nullptr) { K_ASSERT(mCapacity > 0); K_ASSERT(mCapacity < HASH_MAX); - mpBuckets = new Bucket[mCapacity]; - K_ASSERT(mpBuckets != nullptr); + mpBuckets = new HashBucket[mCapacity]; + K_ASSERT_PTR(mpBuckets); } /** @@ -166,38 +171,80 @@ template class TMap { * * @param rOther Map to copy */ - TMap(const TMap& rOther); + THashMap(const THashMap& rOther) + : mSize(0), mCapacity(0), mpBuckets(nullptr) { + + *this = rOther; + } /** * @brief Destructor */ - ~TMap() { + ~THashMap() { delete[] mpBuckets; + mpBuckets = nullptr; } /** - * @brief Access a value by key - * @note Inserts key if it does not already exist + * @brief Assignment operator + * @details Copy assignment * - * @param rKey Key - * @return Existing value, or new entry + * @param rOther Map to copy from */ - TValue& operator[](const TKey& rKey) { - return *Create(rKey).value; + THashMap& operator=(const THashMap& rOther); + + /** + * @brief Erases all elements from the map + */ + void Clear(); + + /** + * @brief Gets an iterator to the beginning of the map + */ + Iterator Begin() { + return Iterator(this, 0); + } + + /** + * @brief Gets an iterator to the end of the map + */ + Iterator End() { + return Iterator(this, mCapacity); + } + + /** + * @brief Get number of elements in the map + */ + u32 Size() const { + return mSize; + } + + /** + * @brief Gets the maximum number of elements in the map + */ + u32 Capacity() const { + return mCapacity; } /** - * @brief Insert a new key or update an existing value + * @brief Check whether the map contains no elements + */ + bool Empty() const { + return Size() == 0; + } + + /** + * @brief Inserts a new element or updates an existing element * * @param rKey Key * @param rValue Value */ void Insert(const TKey& rKey, const TValue& rValue) { - Create(rKey).value = rValue; + (*Create(rKey).item).value = rValue; } /** - * @brief Remove a key + * @brief Removes an element by key * * @param rKey Key * @param[out] pRemoved Removed value @@ -206,112 +253,154 @@ template class TMap { bool Remove(const TKey& rKey, TValue* pRemoved = nullptr); /** - * @brief Look for the value corresponding to a key + * @brief Removes all elements from the map satisfying the condition * - * @param rKey Key - * @return Value if it exists + * @param pPredicate Function to test if the element should be removed + * @return How many elements were removed */ - TValue* Find(const TKey& rKey) const { - Bucket* pBucket = Search(rKey); + u32 RemoveIf(bool (*pPredicate)(const HashItem&)); - if (pBucket != nullptr) { - return &*pBucket->value; - } + /** + * @brief Erases the element at the specified iterator's position + * + * @param it Iterator at which to erase the element + * @return Iterator to the next element after the erased element + */ + Iterator Erase(Iterator it); - return nullptr; + /** + * @brief Accesses an element by key + * @note Inserts the key if it does not already exist + * + * @param rKey Key + * @return Existing element, or new entry + */ + TValue& operator[](const TKey& rKey) { + return (*Create(rKey).item).value; } /** - * @brief Look for the value corresponding to a key + * @brief Searches for an existing element by key * * @param rKey Key - * @param rDefault Default value * @return Value if it exists */ - const TValue& Get(const TKey& rKey, - const TValue& rDefault = TValue()) const { - TValue* pValue = Find(rKey); - return pValue != nullptr ? *pValue : rDefault; - } + TValue* Find(const TKey& rKey) const; /** - * @brief Check whether a key exists + * @brief Accesses an element by key + * @details If the element doesn't exist, the provided default value is + * returned. * * @param rKey Key + * @param rDefault Default value + * @return Existing element, or default value */ - bool Contains(const TKey& rKey) const { - return Find(rKey) != nullptr; - } + TValue Get(const TKey& rKey, const TValue& rDefault = TValue()) const; /** - * @brief Get number of elements in the map + * @brief Tests whether an element exists with the specified key + * + * @param rKey Key */ - u32 Size() const { - return mSize; + bool Contains(const TKey& rKey) const { + return Search(rKey) != nullptr; } /** - * @brief Check whether the map contains no elements + * @brief Gets a list of all keys in the map */ - bool Empty() const { - return Size() == 0; - } - + TVector Keys() const; /** - * @brief Gets list of keys in the map + * @brief Gets a list of all values in the map */ - TList Keys() const { - TList keys; + TVector Values() const; - for (ConstIterator it = Begin(); it != End(); ++it) { - keys.PushBack(it.Key()); - } +private: + //! Default bucket count + static const u32 scDefaultCapacity = 32; - return keys; - } +private: + /** + * @brief Searches for an existing element by key + * + * @param rKey Key + * @returns Bucket that contains the element + */ + HashBucket* Search(const TKey& rKey) const; /** - * @brief Gets list of values in the map + * @brief Inserts a key if it does not already exist + * + * @param rKey Key + * @return Bucket that contains the key */ - TList Values() const { - TList values; + HashBucket& Create(const TKey& rKey); - for (ConstIterator it = Begin(); it != End(); ++it) { - values.PushBack(it.Value()); - } +private: + //! Number of elements in the map + u32 mSize; + //! Maximum number of elements + u32 mCapacity; - return values; - } + //! Element buckets + HashBucket* mpBuckets; +}; + +namespace detail { +//! @addtogroup libkiwi_prim +//! @{ + +/** + * @brief Hash map bucket + */ +template struct THashBucket { + // Stored item type + typedef THashItem Item; + + //! Key/value storage + Optional item; + //! Separate chaining list + THashBucket* pNext; /** - * @brief Gets iterator to beginning of map (const view) + * @brief Constructor */ - ConstIterator Begin() const { - return ConstIterator(mCapacity, mpBuckets); + THashBucket() : pNext(nullptr) {} + /** + * @brief Destructor + */ + ~THashBucket() { + Destroy(); } /** - * @brief Gets iterator to end of map (const-view) + * @brief Initializes this bucket with a new key + * + * @param rKey Key + */ + void Init(const TKey& rKey) { + item.Reset(); + item = Item(rKey); + } + /** + * @brief Clears this bucket's data */ - ConstIterator End() const { - return ConstIterator(0, nullptr); + void Destroy() { + item.Reset(); + delete pNext; + pNext = nullptr; } - -private: - Bucket* Search(const TKey& rKey) const; - Bucket& Create(const TKey& rKey); - -private: - u32 mSize; // Number of elements - u32 mCapacity; // Maximum number of elements - Bucket* mpBuckets; // Element buckets }; +//! @} +} // namespace detail + //! @} } // namespace kiwi // Implementation header -#ifndef LIBKIWI_PRIM_HASHMAP_IMPL_HPP +#ifndef LIBKIWI_PRIM_HASH_MAP_IMPL_HPP #include #endif diff --git a/lib/libkiwi/prim/kiwiHashMapImpl.hpp b/lib/libkiwi/prim/kiwiHashMapImpl.hpp index 914671b..f9088d5 100644 --- a/lib/libkiwi/prim/kiwiHashMapImpl.hpp +++ b/lib/libkiwi/prim/kiwiHashMapImpl.hpp @@ -1,122 +1,286 @@ // Implementation header -#ifndef LIBKIWI_PRIM_HASHMAP_IMPL_HPP -#define LIBKIWI_PRIM_HASHMAP_IMPL_HPP +#ifndef LIBKIWI_PRIM_HASH_MAP_IMPL_HPP +#define LIBKIWI_PRIM_HASH_MAP_IMPL_HPP // Declaration header -#ifndef LIBKIWI_PRIM_HASHMAP_H +#ifndef LIBKIWI_PRIM_HASH_MAP_H #include #endif namespace kiwi { +/****************************************************************************** + * + * IteratorImpl + * + ******************************************************************************/ + /** - * @brief Pre-increment operator + * @brief Constructor + * + * @param pHashMap Parent hash map + * @param index Bucket index */ template -K_INLINE typename TMap::ConstIterator& -TMap::ConstIterator::operator++() { - // Can't iterate - if (mpIter == nullptr) { - return *this; - } - - // Increment - mpIter = mpIter->pChained; - - // Find next non-empty chain - while (true) { - // End of chain, advance to next bucket - if (mpIter == nullptr) { - if (++mIndex >= mCapacity) { - break; - } +template +K_INLINE THashMap::IteratorImpl::IteratorImpl( + THashMap* pHashMap, u32 index) + : mpHashMap(pHashMap), mIndex(index), mpBucket(nullptr) { + + K_ASSERT_PTR(mpHashMap); + K_ASSERT(mIndex <= mpHashMap->Capacity()); + + // Grab the targeted bucket + if (mIndex < mpHashMap->Capacity()) { + mpBucket = &mpHashMap->mpBuckets[mIndex]; + } + + // Advance to the first non-empty bucket + if (mpBucket != nullptr && !mpBucket->item.HasValue()) { + Next(); + } +} + +/** + * @brief Increments the iterator once + */ +template +template +K_INLINE void THashMap::IteratorImpl::Next() { + K_ASSERT_PTR(mpHashMap); + + // Ignore end/invalid iterators + if (mpBucket == nullptr || mIndex >= mpHashMap->Capacity()) { + return; + } - mpIter = &mpBuckets[mIndex]; + // Find the next available bucket with a key + do { + // Try the separate chaining buckets first + mpBucket = mpBucket->pNext; + + for (; mpBucket != nullptr; mpBucket = mpBucket->pNext) { + if (mpBucket->item.HasValue()) { + return; + } } - // Did we find an item? - K_ASSERT(mpIter != nullptr); - if (mpIter->used) { - break; + // Move to the next top-level bucket if the chains had nothing + if (++mIndex >= mpHashMap->Capacity()) { + // Ignore end/invalid iterators + return; } - // Keep searching - mpIter = mpIter->pChained; - } + mpBucket = &mpHashMap->mpBuckets[mIndex]; - return *this; + } while (mpBucket == nullptr || !mpBucket->item.HasValue()); } +/****************************************************************************** + * + * THashMap + * + ******************************************************************************/ + /** - * @brief Constructor - * @details Copy constructor + * @brief Assignment operator + * @details Copy assignment * - * @param rOther Map to copy + * @param rOther Map to copy from */ template -K_INLINE TMap::TMap(const TMap& rOther) - : mCapacity(rOther.mCapacity) { - K_ASSERT(mCapacity > 0); - K_ASSERT(mCapacity < HASH_MAX); +K_INLINE THashMap& +THashMap::operator=(const THashMap& rOther) { + K_ASSERT(rOther.mCapacity > 0); + K_ASSERT(rOther.mCapacity < HASH_MAX); + + // Release old data + Clear(); - // Create buckets for copy - mpBuckets = new Bucket[mCapacity]; - K_ASSERT(mpBuckets != nullptr); + mCapacity = rOther.mCapacity; + mpBuckets = new HashBucket[mCapacity]; + K_ASSERT_PTR(mpBuckets); - // Re-insert all members - for (ConstIterator it = rOther.Begin(); it != rOther.End(); ++it) { - Insert(it.Key(), it.Value()); + K_FOREACH (it, rOther) { + Insert(it->key, it->value); } + + return *this; +} + +/** + * @brief Erases all elements from the map + */ +template +K_INLINE void THashMap::Clear() { + for (u32 i = 0; i < mCapacity; i++) { + mpBuckets[i].Destroy(); + } + + mSize = 0; } /** - * @brief Remove a key + * @brief Removes an element by key * * @param rKey Key * @param[out] pRemoved Removed value * @return Success */ template -K_INLINE bool TMap::Remove(const TKey& rKey, TValue* pRemoved) { - Bucket* pBucket = Search(rKey); +K_INLINE bool THashMap::Remove(const TKey& rKey, + TValue* pRemoved) { + HashBucket* pBucket = Search(rKey); - // Can't remove, doesn't exist if (pBucket == nullptr) { return false; } - // Write out value about to be removed if (pRemoved != nullptr) { - *pRemoved = *pBucket->value; + *pRemoved = (*pBucket->item).value; } - // Just mark as unused - pBucket->used = false; + // Clear key/value pair for later re-use + pBucket->item.Reset(); + mSize--; return true; } /** - * @brief Find key in hashmap + * @brief Removes all elements from the map satisfying the condition + * + * @param pPredicate Function to test if the element should be removed + * @return How many elements were removed + */ +template +K_INLINE u32 +THashMap::RemoveIf(bool (*pPredicate)(const HashItem&)) { + K_ASSERT_PTR(pPredicate); + + Iterator it = Begin(); + u32 eraseNum = 0; + + while (it != End()) { + if (!pPredicate(*it)) { + ++it; + continue; + } + + it = Erase(it); + eraseNum++; + } + + return eraseNum; +} + +/** + * @brief Erases the element at the specified iterator's position + * + * @param it Iterator at which to erase the element + * @return Iterator to the next element after the erased element + */ +template +K_INLINE typename THashMap::Iterator +THashMap::Erase(Iterator it) { + // Ignore invalid iterators + if (it.mpBucket == nullptr) { + return it; + } + + it.mpBucket->item.Reset(); + + mSize--; + return ++it; +} + +/** + * @brief Searches for an existing element by key + * + * @param rKey Key + * @return Value if it exists + */ +template +TValue* THashMap::Find(const TKey& rKey) const { + HashBucket* pBucket = Search(rKey); + + if (pBucket == nullptr) { + return nullptr; + } + + return &(*pBucket->item).value; +} + +/** + * @brief Accesses an element by key + * @details If the element doesn't exist, the provided default value is + * returned. + * + * @param rKey Key + * @param rDefault Default value + * @return Existing element, or default value + */ +template +TValue THashMap::Get(const TKey& rKey, + const TValue& rDefault) const { + HashBucket* pBucket = Search(rKey); + + if (pBucket == nullptr) { + return rDefault; + } + + return (*pBucket->item).value; +} + +/** + * @brief Gets list of keys in the map + */ +template +K_INLINE TVector THashMap::Keys() const { + TVector keys; + + K_FOREACH (it, *this) { + keys.PushBack((*it).key); + } + + return keys; +} + +/** + * @brief Gets list of values in the map + */ +template +K_INLINE TVector THashMap::Values() const { + TVector values; + + K_FOREACH (it, *this) { + values.PushBack((*it).value); + } + + return values; +} + +/** + * @brief Searches for an existing element by key * * @param rKey Key + * @returns Bucket that contains the element */ template -K_INLINE typename TMap::Bucket* -TMap::Search(const TKey& rKey) const { - // Calculate bucket index - u32 i = Hash(rKey) % mCapacity; - - // Iterate through chains - for (Bucket* pIt = &mpBuckets[i]; pIt != nullptr; pIt = pIt->pChained) { - // Unused entry - if (!pIt->used) { +K_INLINE typename THashMap::HashBucket* +THashMap::Search(const TKey& rKey) const { + // Hash function calculates the bucket index + u32 idx = Hash(rKey) % mCapacity; + HashBucket* pBucket = &mpBuckets[idx]; + + // Check separate chained buckets to allow hash collisions + for (; pBucket != nullptr; pBucket = pBucket->pNext) { + if (!pBucket->item.HasValue()) { continue; } - // Matches key - if (*pIt->key == rKey) { - return pIt; + if ((*pBucket->item).key == rKey) { + return pBucket; } } @@ -124,47 +288,56 @@ TMap::Search(const TKey& rKey) const { } /** - * @brief Create key in hashmap + * @brief Inserts a key if it does not already exist * * @param rKey Key + * @return Bucket that contains the key */ template -K_INLINE typename TMap::Bucket& -TMap::Create(const TKey& rKey) { - // Calculate bucket index - u32 i = Hash(rKey) % mCapacity; - - // Iterate through chains - Bucket* pLast = nullptr; - for (Bucket* pIt = &mpBuckets[i]; pIt != nullptr; pIt = pIt->pChained) { - // Unused entry - if (!pIt->used) { - // Override this entry - pIt->key = rKey; - pIt->value.Emplace(); - pIt->used = true; - mSize++; - return *pIt; +K_INLINE typename THashMap::HashBucket& +THashMap::Create(const TKey& rKey) { + // Hash function calculates the bucket index + u32 idx = Hash(rKey) % mCapacity; + HashBucket* pBucket = &mpBuckets[idx]; + + // The key may already exist + for (HashBucket* pIt = pBucket; pIt != nullptr; pIt = pIt->pNext) { + if (!pIt->item.HasValue()) { + continue; } - // Matches key - if (*pIt->key == rKey) { + if ((*pIt->item).key == rKey) { return *pIt; } + } - pLast = pIt; + // Re-use empty slots + HashBucket* pPrev = nullptr; + for (HashBucket* pIt = pBucket; pIt != nullptr; pIt = pIt->pNext) { + pPrev = pIt; + + if (pIt->item.HasValue()) { + continue; + } + + pIt->Init(rKey); + + mSize++; + return *pIt; } - // Chain new bucket - K_ASSERT(pLast != nullptr); - pLast->pChained = new Bucket(); - K_ASSERT(pLast->pChained != nullptr); + // Must create a new bucket + HashBucket* pNewBucket = new HashBucket(); + K_ASSERT_PTR(pNewBucket); + pNewBucket->Init(rKey); + + // Continue the chain + K_ASSERT_PTR(pPrev); + K_ASSERT(pPrev->item.HasValue()); + pPrev->pNext = pNewBucket; - pLast->pChained->key = rKey; - pLast->pChained->value.Emplace(); - pLast->pChained->used = true; mSize++; - return *pLast->pChained; + return *pNewBucket; } } // namespace kiwi diff --git a/lib/libkiwi/prim/kiwiIterator.h b/lib/libkiwi/prim/kiwiIterator.h new file mode 100644 index 0000000..b65054c --- /dev/null +++ b/lib/libkiwi/prim/kiwiIterator.h @@ -0,0 +1,650 @@ +#ifndef LIBKIWI_PRIM_ITERATOR_H +#define LIBKIWI_PRIM_ITERATOR_H +#include + +namespace kiwi { +//! @addtogroup libkiwi_prim +//! @{ + +namespace detail { +//! @addtogroup libkiwi_prim +//! @{ + +/** + * @brief Common iterator implementation + * + * @details The derived class must implement the following functions: + * - `void Next()` For incrementing the iterator once + * - `void Prev()` For decrementing the iterator once + * - `void Move(int n)` For advancing the iterator by a specified amount + * - `int Dist(it) const` For computing distance between iterators + * - `TValue& Get()` For accessing the iterator's value + * - `bool Equals(it) const` For comparing for equality with another iterator + * + * @tparam TDerived Derived iterator class type + * @tparam TValue Iterator value type + * @tparam TPointer Value pointer type + * @tparam TReference Value reference type + * @tparam TTag Iterator tag type + */ +template +class Iterator { +public: + // For readability + typedef Iterator SelfType; + typedef TDerived DerivedType; + typedef TPointer PointerType; + typedef TReference ReferenceType; + + // Expose TValue for iterator adapters + typedef TValue ValueType; + + // Expose TTag for algorithms + typedef TTag TagType; + +public: + /** + * @brief Pre-increment operator + */ + DerivedType& operator++() { + detail_DownCast().Next(); + return detail_DownCast(); + } + /** + * @brief Post-increment operator + */ + DerivedType operator++(int) { + DerivedType clone = detail_DownCast(); + detail_DownCast().Next(); + return clone; + } + + /** + * @brief Pre-decrement operator + */ + DerivedType& operator--() { + detail_DownCast().Prev(); + return detail_DownCast(); + } + /** + * @brief Post-decrement operator + */ + DerivedType operator--(int) { + DerivedType clone = detail_DownCast(); + detail_DownCast().Prev(); + return clone; + } + + /** + * @brief Increment operator + * + * @param n Distance to move + */ + DerivedType operator+(int n) const { + DerivedType clone = detail_DownCast(); + clone += n; + return clone; + } + /** + * @brief In-place increment operator + * + * @param n Distance to move + */ + DerivedType& operator+=(int n) { + detail_DownCast().Move(n); + return detail_DownCast(); + } + + /** + * @brief Decrement operator + * + * @param n Distance to move + */ + DerivedType operator-(int n) const { + DerivedType clone = detail_DownCast(); + clone -= n; + return clone; + } + /** + * @brief In-place decrement operator + * + * @param n Distance to move + */ + DerivedType& operator-=(int n) { + detail_DownCast().Move(-n); + return detail_DownCast(); + } + + /** + * @brief Accesses the value at the iterator's position (by reference) + */ + ReferenceType operator*() { + return detail_DownCast().Get(); + } + /** + * @brief Accesses the value at the iterator's position (by pointer) + */ + PointerType operator->() { + return &detail_DownCast().Get(); + } + +public: + /** + * @brief Views this iterator as its derived type + */ + K_INLINE DerivedType& detail_DownCast() { + return *static_cast(this); + } + /** + * @brief Views this iterator as its derived type (const-view) + */ + K_INLINE const DerivedType& detail_DownCast() const { + return *static_cast(this); + } +}; + +/** + * @brief Tests whether the left-hand-side iterator is positioned earlier than + * the right-hand-side iterator + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator<(const Iterator& rLhs, + const Iterator& rRhs) { + + return rLhs.detail_DownCast().Dist(rRhs.detail_DownCast()) > 0; +} + +/** + * @brief Tests whether the left-hand-side iterator is positioned earlier than + * or at the same position as the right-hand-side iterator + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator<=(const Iterator& rLhs, + const Iterator& rRhs) { + + return rLhs.detail_DownCast() < rRhs.detail_DownCast() || + rLhs.detail_DownCast() == rRhs.detail_DownCast(); +} + +/** + * @brief Tests whether the left-hand-side iterator is positioned later than + * the right-hand-side iterator + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator>(const Iterator& rLhs, + const Iterator& rRhs) { + + return rLhs.detail_DownCast().Dist(rRhs.detail_DownCast()) < 0; +} + +/** + * @brief Tests whether the left-hand-side iterator is positioned later than or + * at the same position as the right-hand-side iterator + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator>=(const Iterator& rLhs, + const Iterator& rRhs) { + + return rLhs.detail_DownCast() > rRhs.detail_DownCast() || + rLhs.detail_DownCast() == rRhs.detail_DownCast(); +} + +/** + * @brief Computes the distance between two iterators + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE int operator-(const Iterator& rLhs, + const Iterator& rRhs) { + + return rRhs.detail_DownCast().Dist(rLhs.detail_DownCast()); +} + +/** + * @brief Checks two iterators for equality + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator==(const Iterator& rLhs, + const Iterator& rRhs) { + + return rLhs.detail_DownCast().Equals(rRhs.detail_DownCast()); +} +/** + * @brief Checks two iterators for inequality + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator!=(const Iterator& rLhs, + const Iterator& rRhs) { + + return !rLhs.detail_DownCast().Equals(rRhs.detail_DownCast()); +} + +//! @} +} // namespace detail + +/****************************************************************************** + * + * Common iterator functionality + * + ******************************************************************************/ + +/** + * @brief Reverse iterator + * + * @tparam TIterator Base/adapted iterator type + */ +template class ReverseIterator { +public: + // For readability + typedef ReverseIterator SelfType; + typedef TIterator BaseType; + + // Access value types of underlying iterator + typedef typename TIterator::ValueType ValueType; + typedef typename TIterator::ReferenceType ReferenceType; + typedef typename TIterator::PointerType PointerType; + +public: + /** + * @brief Constructor + * + * @param it Base/adapted iterator + */ + explicit ReverseIterator(BaseType it) : mBase(it) {} + + /** + * @brief Accesses the base/adapted iterator + */ + BaseType GetBase() const { + return mBase; + } + + /** + * @brief Pre-increment operator + */ + SelfType& operator++() { + --mBase; + return *this; + } + /** + * @brief Post-increment operator + */ + SelfType operator++(int) const { + SelfType clone = *this; + --mBase; + return clone; + } + + /** + * @brief Pre-decrement operator + */ + SelfType& operator--() { + ++mBase; + return *this; + } + /** + * @brief Post-decrement operator + */ + SelfType operator--(int) const { + SelfType clone = *this; + ++mBase; + return clone; + } + + /** + * @brief Increment operator + * + * @param n Distance to move + */ + SelfType operator+(int n) const { + SelfType clone = *this; + clone.mBase -= n; + return clone; + } + /** + * @brief In-place increment operator + * + * @param n Distance to move + */ + SelfType& operator+=(int n) { + mBase -= n; + return *this; + } + + /** + * @brief Decrement operator + * + * @param n Distance to move + */ + SelfType operator-(int n) const { + SelfType clone = *this; + clone += n; + return clone; + } + /** + * @brief In-place decrement operator + * + * @param n Distance to move + */ + SelfType& operator-=(int n) { + mBase += n; + return *this; + } + + /** + * @brief Accesses the value at the iterator's position (by reference) + */ + ReferenceType operator*() const { + BaseType it = mBase; + return *--it; + } + /** + * @brief Accesses the value at the iterator's position (by pointer) + */ + PointerType operator->() const { + BaseType it = mBase; + return &*--it; + } + +private: + //! Base/adapted iterator + BaseType mBase; +}; + +/** + * @brief Tests whether the left-hand-side iterator is positioned earlier than + * the right-hand-side iterator + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator<(const ReverseIterator& rLhs, + const ReverseIterator& rRhs) { + return rLhs.GetBase() < rRhs.GetBase(); +} + +/** + * @brief Tests whether the left-hand-side iterator is positioned earlier than + * or at the same position as the right-hand-side iterator + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator<=(const ReverseIterator& rLhs, + const ReverseIterator& rRhs) { + return rLhs.GetBase() <= rRhs.GetBase(); +} + +/** + * @brief Tests whether the left-hand-side iterator is positioned later than + * the right-hand-side iterator + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator>(const ReverseIterator& rLhs, + const ReverseIterator& rRhs) { + return rLhs.GetBase() > rRhs.GetBase(); +} + +/** + * @brief Tests whether the left-hand-side iterator is positioned later than or + * at the same position as the right-hand-side iterator + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator>=(const ReverseIterator& rLhs, + const ReverseIterator& rRhs) { + return rLhs.GetBase() >= rRhs.GetBase(); +} + +/** + * @brief Computes the distance between two iterators + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE int operator-(const ReverseIterator& rLhs, + const ReverseIterator& rRhs) { + return rRhs.GetBase() - rLhs.GetBase(); +} + +/** + * @brief Checks two iterators for equality + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator==(const ReverseIterator& rLhs, + const ReverseIterator& rRhs) { + return rLhs.GetBase() == rRhs.GetBase(); +} +/** + * @brief Checks two iterators for inequality + * + * @param rLhs Left-hand side iterator + * @param rRhs Right-hand side iterator + */ +template +K_INLINE bool operator!=(const ReverseIterator& rLhs, + const ReverseIterator& rRhs) { + return rLhs.GetBase() != rRhs.GetBase(); +} + +/****************************************************************************** + * + * Specialized iterator types + * + ******************************************************************************/ + +/** + * @brief Random access iterator tag + */ +struct RandomAccessIteratorTag {}; + +/** + * @brief Random access iterator implementation + * + * @details The derived class must implement the following functions: + * - `void Next()` For incrementing the iterator once + * - `void Prev()` For decrementing the iterator once + * - `void Move(int n)` For advancing the iterator by a specified amount + * - `int Dist(it) const` For computing distance between iterators + * - `TValue& Get()` For accessing the iterator's value + * - `bool Equals(it) const` For comparing for equality with another iterator + * + * @tparam TDerived Derived iterator class type + * @tparam TValue Iterator value type + * @tparam TPointer Value pointer type + * @tparam TReference Value reference type + */ +template +class RandomAccessIterator + : public detail::Iterator { +public: + // For readability + typedef detail::Iterator + BaseType; + + typedef TDerived DerivedType; +}; + +/** + * @brief Bi-directional iterator tag + */ +struct BiDirectionalIteratorTag {}; + +/** + * @brief Bi-directional iterator implementation + * + * @details The derived class must implement the following functions: + * - `void Next()` For incrementing the iterator once + * - `void Prev()` For decrementing the iterator once + * - `TValue& Get()` For accessing the iterator's value + * + * @tparam TDerived Derived iterator class type + * @tparam TValue Iterator value type + * @tparam TPointer Value pointer type + * @tparam TReference Value reference type + */ +template +class BiDirectionalIterator + : public detail::Iterator { +public: + // For readability + typedef detail::Iterator + BaseType; + + typedef TDerived DerivedType; + +private: + void Move(int /* n */) { + K_ASSERT_EX(false, "Not for bi-directional iterators"); + } + + int Dist(DerivedType /* other */) const { + K_ASSERT_EX(false, "Not for bi-directional iterators"); + return 0; + } +}; + +/** + * @brief Forward iterator tag + */ +struct ForwardIteratorTag {}; + +/** + * @brief Forward iterator implementation + * + * @details The derived class must implement the following functions: + * - `void Next()` For incrementing the iterator once + * - `TValue& Get()` For accessing the iterator's value + * + * @tparam TDerived Derived iterator class type + * @tparam TValue Iterator value type + * @tparam TPointer Value pointer type + * @tparam TReference Value reference type + */ +template +class ForwardIterator + : public detail::Iterator { +public: + // For readability + typedef detail::Iterator + BaseType; + + typedef TDerived DerivedType; + +private: + void Prev() { + K_ASSERT_EX(false, "Not for forward iterators"); + } + + void Move(int /* n */) { + K_ASSERT_EX(false, "Not for forward iterators"); + } + + int Dist(DerivedType /* other */) const { + K_ASSERT_EX(false, "Not for forward iterators"); + return 0; + } +}; + +/****************************************************************************** + * + * Boilerplate macros + * + ******************************************************************************/ + +/** + * @brief Generates iterator typedefs for shorthand + * + * @param T_ITERATOR Iterator class type + * @param T_VALUE Iterator value type + */ +#define K_GEN_ITERATOR_TYPEDEFS(T_ITERATOR, T_VALUE) \ + typedef T_ITERATOR Iterator; \ + typedef T_ITERATOR ConstIterator; \ + typedef ReverseIterator > RevIterator; \ + typedef ReverseIterator > ConstRevIterator; + +/** + * @brief Generates const/reverse iterator methods + * @note Requires `Begin` and `End` to already be defined + * + * @param T Container class type + */ +#define K_GEN_ITERATOR_METHODS(T) \ + ConstIterator Begin() const { \ + return const_cast(this)->Begin(); \ + } \ + ConstIterator End() const { \ + return const_cast(this)->End(); \ + } \ + ConstIterator CBegin() const { \ + return Begin(); \ + } \ + ConstIterator CEnd() const { \ + return End(); \ + } \ + RevIterator RBegin() { \ + return RevIterator(End()); \ + } \ + RevIterator REnd() { \ + return RevIterator(Begin()); \ + } \ + ConstRevIterator CRBegin() const { \ + return ConstRevIterator(End()); \ + } \ + ConstRevIterator CREnd() const { \ + return ConstRevIterator(Begin()); \ + } + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/prim/kiwiLinkList.h b/lib/libkiwi/prim/kiwiLinkList.h deleted file mode 100644 index e18c3a5..0000000 --- a/lib/libkiwi/prim/kiwiLinkList.h +++ /dev/null @@ -1,390 +0,0 @@ -#ifndef LIBKIWI_PRIM_LINKLIST_H -#define LIBKIWI_PRIM_LINKLIST_H -#include -#include -#include - -namespace kiwi { -//! @addtogroup libkiwi_prim -//! @{ - -/** - * @brief Templated linked-list node - * @note List node DOES NOT OWN ELEMENT - */ -template class TListNode : private NonCopyable { - // List node should be completely hidden outside list implementation - template friend class TList; - friend class TList::Iterator; - friend class TList::ConstIterator; - -private: - /** - * @brief Constructor - * - * @param pElem Node element - */ - explicit TListNode(T* pElem) - : mpNext(nullptr), mpPrev(nullptr), mpElement(pElem) {} - - TListNode* mpNext; // Next node in the linked-list - TListNode* mpPrev; // Previous node in the linked-list - T* mpElement; // Underlying element -}; - -/** - * @brief Templated linked-list - */ -template class TList : private NonCopyable { -public: - // Forward declarations - class ConstIterator; - - /** - * @brief Linked-list iterator - */ - class Iterator { - template friend class TList; - friend class ConstIterator; - - public: - /** - * @brief Constructor - * - * @param pNode Iterator node - */ - explicit Iterator(TListNode* pNode) : mpNode(pNode) { - K_ASSERT(mpNode); - } - - /** - * @brief Pre-increment operator - */ - Iterator& operator++() { - mpNode = mpNode->mpNext; - return *this; - } - /** - * @brief Post-increment operator - */ - Iterator operator++(int) { - Iterator clone(*this); - ++*this; - return clone; - } - - /** - * @brief Pre-decrement operator - */ - Iterator& operator--() { - mpNode = mpNode->mpPrev; - return *this; - } - /** - * @brief Post-decrement operator - */ - Iterator operator--(int) { - Iterator clone(*this); - --*this; - return clone; - } - - // clang-format off - T* operator->() const { return mpNode->mpElement; } - T& operator*() const { K_ASSERT(mpNode->mpElement != nullptr); return *mpNode->mpElement; } - - bool operator==(Iterator rhs) const { return mpNode == rhs.mpNode; } - bool operator!=(Iterator rhs) const { return mpNode != rhs.mpNode; } - // clang-format on - - private: - TListNode* mpNode; - }; - - /** - * @brief Linked-list iterator (const view) - */ - class ConstIterator { - template friend class TList; - - public: - /** - * @brief Constructor - * - * @param pNode Iterator node - */ - explicit ConstIterator(TListNode* pNode) : mpNode(pNode) { - K_ASSERT(mpNode != nullptr); - } - - /** - * @brief Constructor - * - * @param iter Iterator - */ - ConstIterator(Iterator iter) : mpNode(iter.mpNode) { - K_ASSERT(mpNode != nullptr); - } - - /** - * @brief Pre-increment operator - */ - ConstIterator& operator++() { - mpNode = mpNode->mpNext; - return *this; - } - /** - * @brief Post-increment operator - */ - ConstIterator operator++(int) { - ConstIterator clone(*this); - ++*this; - return clone; - } - - /** - * @brief Pre-decrement operator - */ - ConstIterator& operator--() { - mpNode = mpNode->mpPrev; - return *this; - } - /** - * @brief Post-decrement operator - */ - ConstIterator operator--(int) { - ConstIterator clone(*this); - --*this; - return clone; - } - - // clang-format off - const T* operator->() const { return mpNode->mpElement; } - const T& operator*() const { K_ASSERT(mpNode->mpElement != nullptr); return *mpNode->mpElement; } - - bool operator==(ConstIterator rhs) const { return mpNode == rhs.mpNode; } - bool operator!=(ConstIterator rhs) const { return mpNode != rhs.mpNode; } - // clang-format on - - private: - TListNode* mpNode; - }; - - typedef void (*ForEachFunc)(T& rElem); - typedef void (*ForEachFuncConst)(const T& rElem); - -public: - /** - * @brief Constructor - */ - TList() : mSize(0), mEndNode(nullptr) { - mEndNode.mpNext = &mEndNode; - mEndNode.mpPrev = &mEndNode; - } - /** - * @brief Destructor - */ - ~TList() { - Clear(); - } - - /** - * @brief Erase all list elements - */ - void Clear() { - Erase(Begin(), End()); - } - - /** - * @brief Gets iterator to beginning of list - */ - Iterator Begin() { - return Iterator(mEndNode.mpNext); - } - /** - * @brief Gets iterator to beginning of list (const view) - */ - ConstIterator Begin() const { - return ConstIterator(const_cast(this)->Begin()); - } - - /** - * @brief Gets iterator to end of list - */ - Iterator End() { - return Iterator(&mEndNode); - } - /** - * @brief Gets iterator to end of list (const-view) - */ - ConstIterator End() const { - return ConstIterator(const_cast(this)->End()); - } - - /** - * @brief Gets list size - */ - u32 Size() const { - return mSize; - } - - /** - * @brief Tests whether list is empty - */ - bool Empty() const { - return Size() == 0; - } - - /** - * @brief Erases beginning element from list - */ - void PopFront() { - Erase(Begin()); - } - - /** - * @brief Erases end element from list - */ - void PopBack() { - Erase(--End()); - } - - /** - * @brief Prepends element to front of list - * - * @param pElem New element - */ - void PushFront(T* pElem) { - Insert(Begin(), new TListNode(pElem)); - } - - /** - * @brief Appends element to end of list - * - * @param pElem New element - */ - void PushBack(T* pElem) { - Insert(End(), new TListNode(pElem)); - } - - /** - * @brief Gets reference to first element of list - */ - T& Front() { - K_ASSERT(!Empty()); - return *Begin(); - } - /** - * @brief Gets reference to first element of list (const-view) - */ - const T& Front() const { - K_ASSERT(!Empty()); - return *Begin(); - } - - /** - * @brief Gets reference to last element of list - */ - T& Back() { - K_ASSERT(!Empty()); - return *--End(); - } - /** - * @brief Gets reference to last element of list (const-view) - */ - const T& Back() const { - K_ASSERT(!Empty()); - return *--End(); - } - - /** - * @brief Inserts node at iterator - * - * @param iter Iterator at which to insert node - * @param pNode Node to insert - * @return Iterator to new node - */ - Iterator Insert(Iterator iter, TListNode* pNode); - - /** - * @brief Erases node at iterator - * - * @param iter Iterator at which to erase node - * @return Iterator to next node - */ - Iterator Erase(Iterator iter) { - Iterator copy(iter); - return Erase(iter, ++copy); - } - - /** - * @brief Erases node from list - * - * @param pNode Node to erase - * @return Iterator to next node - */ - Iterator Erase(TListNode* pNode); - - /** - * @brief Erases range of nodes - * - * @param begin Beginning of range (inclusive) - * @param end End of range (exclusive) - * @return Iterator to end of range - */ - Iterator Erase(Iterator begin, Iterator end); - - /** - * @brief Removes first occurrence of element from list - * - * @param pElem - */ - void Remove(const T* pElem) { - for (Iterator it = Begin(); it != End(); ++it) { - if (&*it == pElem) { - Erase(it); - } - } - } - - /** - * @brief Applies the specified function to every element in the list - * - * @param pFunc For-each function - */ - void ForEach(ForEachFunc pFunc) { - K_ASSERT(pFunc != nullptr); - - for (Iterator it = Begin(); it != End(); ++it) { - pFunc(it); - } - } - - /** - * @brief Applies the specified function to every element in the list - * (read-only) - * - * @param pFunc For-each function (const-view) - */ - void ForEach(ForEachFuncConst pFunc) { - K_ASSERT(pFunc != nullptr); - - for (Iterator it = Begin(); it != End(); ++it) { - pFunc(it); - } - } - -private: - u32 mSize; // List size - TListNode mEndNode; // List end node -}; - -//! @} -} // namespace kiwi - -// Implementation header -#ifndef LIBKIWI_PRIM_LINKLIST_IMPL_HPP -#include -#endif - -#endif diff --git a/lib/libkiwi/prim/kiwiLinkListImpl.hpp b/lib/libkiwi/prim/kiwiLinkListImpl.hpp deleted file mode 100644 index 19c569d..0000000 --- a/lib/libkiwi/prim/kiwiLinkListImpl.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// Implementation header -#ifndef LIBKIWI_PRIM_LINKLIST_IMPL_HPP -#define LIBKIWI_PRIM_LINKLIST_IMPL_HPP - -// Declaration header -#ifndef LIBKIWI_PRIM_LINKLIST_H -#include -#endif - -namespace kiwi { - -/** - * @brief Inserts node at iterator - * - * @param iter Iterator at which to insert node - * @param pNode Node to insert - * @return Iterator to new node - */ -template -K_INLINE typename TList::Iterator TList::Insert(Iterator iter, - TListNode* pNode) { - K_ASSERT(pNode != nullptr); - - TListNode* pNext = iter.mpNode; - TListNode* pPrev = pNext->mpPrev; - - // pPrev <- pNode -> pNext - pNode->mpNext = pNext; - pNode->mpPrev = pPrev; - // pPrev <-> pNode <-> pNext - pNext->mpPrev = pNode; - pPrev->mpNext = pNode; - - mSize++; - - return Iterator(pNode); -} - -/** - * @brief Erases node from list - * - * @param pNode Node to erase - * @return Iterator to next node - */ -template -K_INLINE typename TList::Iterator TList::Erase(TListNode* pNode) { - K_ASSERT(pNode != nullptr); - - TListNode* pNext = pNode->mpNext; - TListNode* pPrev = pNode->mpPrev; - - // Remove connections to node - pNext->mpPrev = pPrev; - pPrev->mpNext = pNext; - // Isolate node - pNode->mpNext = nullptr; - pNode->mpPrev = nullptr; - // Free memory - delete pNode; - - mSize--; - - return Iterator(pNext); -} - -/** - * @brief Erases range of nodes - * - * @param begin Beginning of range (inclusive) - * @param end End of range (exclusive) - * @return Iterator to end of range - */ -template -K_INLINE typename TList::Iterator TList::Erase(Iterator begin, - Iterator end) { - TListNode* pCurr = begin.mpNode; - TListNode* pEnd = end.mpNode; - - while (pCurr != pEnd) { - // Preserve next node before erasing pointers - TListNode* pNext = pCurr->mpNext; - // Erase current node - Erase(pCurr); - pCurr = pNext; - } - - return Iterator(pEnd); -} - -} // namespace kiwi - -#endif diff --git a/lib/libkiwi/prim/kiwiList.h b/lib/libkiwi/prim/kiwiList.h new file mode 100644 index 0000000..5cf09a5 --- /dev/null +++ b/lib/libkiwi/prim/kiwiList.h @@ -0,0 +1,369 @@ +#ifndef LIBKIWI_PRIM_LIST_H +#define LIBKIWI_PRIM_LIST_H +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_prim +//! @{ + +// Forward declarations +template class TListNode; + +/** + * @brief Templated linked-list + * @details Same concept as std::list + */ +template class TList { +public: + /** + * @brief Linked-list iterator + */ + template + class IteratorImpl + : public BiDirectionalIterator, TValue> { + friend class TList; + + public: + // Constness of TValue is moved to the TListNode + typedef typename mp::move_const< // + TValue, // + TListNode::type> // + >::type NodeType; + + // Allow promotion to const iterator + friend class IteratorImpl::type>; + + public: + /** + * @brief Constructor + * + * @param pNode Iterator node + */ + explicit IteratorImpl(NodeType* pNode) : mpNode(pNode) { + K_ASSERT_PTR(mpNode); + } + /** + * @brief Constructor + * + * @param rOther Iterator + */ + template + IteratorImpl(const IteratorImpl& rOther) + : mpNode(rOther.mpNode) { + + K_ASSERT_PTR(mpNode); + } + + /** + * @brief Increments the iterator once + */ + void Next() { + K_ASSERT_PTR(mpNode); + mpNode = mpNode->mpNext; + } + /** + * @brief Decrements the iterator once + */ + void Prev() { + K_ASSERT_PTR(mpNode); + mpNode = mpNode->mpPrev; + } + + /** + * @brief Accesses the iterator's value + */ + TValue& Get() { + K_ASSERT_PTR(mpNode); + K_ASSERT_EX(mpNode->mElement.HasValue(), "Invalid iterator"); + return *mpNode->mElement; + } + + /** + * @brief Tests two iterators for equality + * + * @param other Other iterator + */ + template + bool Equals(IteratorImpl other) const { + return mpNode == other.mpNode; + } + + private: + //! Underlying list node + NodeType* mpNode; + }; + + // Autogen typedefs and const/reverse getters + K_GEN_ITERATOR_TYPEDEFS(IteratorImpl, T); + K_GEN_ITERATOR_METHODS(TList); + +public: + /** + * @brief Constructor + */ + TList() { + Init(); + } + + /** + * @brief Constructor + * @details Copy constructor + * + * @param rOther List to copy + */ + TList(const TList& rOther) { + Init(); + *this = rOther; + } + + /** + * @brief Destructor + */ + ~TList() { + Clear(); + } + + /** + * @brief Assignment operator + * @details Copy assignment + * + * @param rOther List to copy from + */ + TList& operator=(const TList& rOther); + + /** + * @brief Erases all elements from the list + */ + void Clear() { + Erase(Begin(), End()); + } + + /** + * @brief Gets an iterator to the beginning of the list + */ + Iterator Begin() { + return Iterator(mEndNode.mpNext); + } + /** + * @brief Gets an iterator to the end of the list + */ + Iterator End() { + return Iterator(&mEndNode); + } + + /** + * @brief Gets the number of elements in the list + */ + u32 Size() const { + return mSize; + } + /** + * @brief Tests whether the list is empty + */ + bool Empty() const { + return Size() == 0; + } + + /** + * @brief Erases the first element from the list + * + * @return The element that was just erased + */ + T PopFront(); + /** + * @brief Erases the last element from the list + * + * @returns The element that was just erased + */ + T PopBack(); + + /** + * @brief Prepends an element to the front of the list + * + * @param rElement New element + */ + void PushFront(const T& rElement) { + Insert(Begin(), rElement); + } + /** + * @brief Appends an element to the end of the list + * + * @param rElement New element + */ + void PushBack(const T& rElement) { + Insert(End(), rElement); + } + + /** + * @brief Gets a reference to the first element of the list + */ + T& Front() { + K_ASSERT(!Empty()); + return *Begin(); + } + /** + * @brief Gets reference to the first element of the list (const-view) + */ + const T& Front() const { + K_ASSERT(!Empty()); + return *Begin(); + } + + /** + * @brief Gets reference to the last element of the list + */ + T& Back() { + K_ASSERT(!Empty()); + return *--End(); + } + /** + * @brief Gets reference to the last element of the list (const-view) + */ + const T& Back() const { + K_ASSERT(!Empty()); + return *--End(); + } + + /** + * @brief Removes the first occurrence of an element from the list + * + * @param rElement Element to remove + * @return Whether the element was found and removed + */ + bool Remove(const T& rElement); + + /** + * @brief Removes all elements from the list satisfying the condition + * + * @param pPredicate Function to test if the element should be removed + * @return How many elements were removed + */ + u32 RemoveIf(bool (*pPredicate)(const T&)); + + /** + * @brief Inserts an element at the specified iterator's position + * @details Value is inserted before the given iterator + * + * @param it Iterator at which to insert the element + * @param rElement Element to insert + * @return Iterator to the new element + */ + Iterator Insert(Iterator it, const T& rElement) { + return InsertNode(it, new TListNode(rElement)); + } + + /** + * @brief Erases the element at the specified iterator's position + * + * @param it Iterator at which to erase element + * @return Iterator to the next element after the erased element + */ + Iterator Erase(Iterator it) { + Iterator copy(it); + return Erase(it, ++copy); + } + + /** + * @brief Erases range of nodes + * + * @param begin Beginning of range (inclusive) + * @param end End of range (exclusive) + * @return Iterator to end of range + */ + Iterator Erase(Iterator begin, Iterator end); + + /** + * @brief Sorts elements in the list using the specified comparator function + * @details The sort order defaults to ascending order when a comparator is + * not specified. + * + * @param pComparator Function used to compare two elements. Returns true + * when the first element is less-than the second element. + */ + void Sort(bool (*pComparator)(const T&, const T&) = kiwi::Less) { + kiwi::Sort(Begin(), End(), pComparator); + } + +private: + /** + * @brief Inserts node at iterator + * + * @param it Iterator at which to insert node + * @param pNode Node to insert + * @return Iterator to new node + */ + Iterator InsertNode(Iterator it, TListNode* pNode); + + /** + * @brief Erases node from list + * + * @param pNode Node to erase + * @return Iterator to next node + */ + Iterator EraseNode(TListNode* pNode); + + /** + * @brief Initializes the list's size/end node + */ + void Init() { + mSize = 0; + mEndNode.mpNext = &mEndNode; + mEndNode.mpPrev = &mEndNode; + } + +private: + //! Number of elements in the list + u32 mSize; + //! List end node + TListNode mEndNode; +}; + +/** + * @brief Templated linked-list node + */ +template class TListNode : private NonCopyable { + friend class TList; + friend class TList::Iterator; + friend class TList::ConstIterator; + +private: + /** + * @brief Constructor + */ + TListNode() : mpNext(nullptr), mpPrev(nullptr) {} + + /** + * @brief Constructor + * + * @param element Node element + */ + explicit TListNode(const T& rElement) + : mpNext(nullptr), mpPrev(nullptr), mElement(rElement) {} + +private: + //! Next node in the linked-list + TListNode* mpNext; + //! Previous node in the linked-list + TListNode* mpPrev; + + //! Underlying element + Optional mElement; +}; + +//! @} +} // namespace kiwi + +// Implementation header +#ifndef LIBKIWI_PRIM_LIST_IMPL_HPP +#include +#endif + +#endif diff --git a/lib/libkiwi/prim/kiwiListImpl.hpp b/lib/libkiwi/prim/kiwiListImpl.hpp new file mode 100644 index 0000000..086b252 --- /dev/null +++ b/lib/libkiwi/prim/kiwiListImpl.hpp @@ -0,0 +1,184 @@ +// Implementation header +#ifndef LIBKIWI_PRIM_LIST_IMPL_HPP +#define LIBKIWI_PRIM_LIST_IMPL_HPP + +// Declaration header +#ifndef LIBKIWI_PRIM_LIST_H +#include +#endif + +namespace kiwi { + +/** + * @brief Assignment operator + * @details Copy assignment + * + * @param rOther List to copy from + */ +template +K_INLINE TList& TList::operator=(const TList& rOther) { + // Release old data + Clear(); + Init(); + + K_FOREACH (it, rOther) { + PushBack(*it); + } + + return *this; +} + +/** + * @brief Erases the first element from the list + * + * @return The element that was just erased + */ +template K_INLINE T TList::PopFront() { + K_ASSERT(!Empty()); + + Iterator front = Begin(); + T element = *front; + + Erase(front); + return element; +} + +/** + * @brief Erases the last element from the list + * + * @returns The element that was just erased + */ +template K_INLINE T TList::PopBack() { + K_ASSERT(!Empty()); + + Iterator back = --End(); + T element = *back; + + Erase(back); + return element; +} + +/** + * @brief Removes first occurrence of element from list + * + * @param rElement Element to remove + * @return Whether the element was found and removed + */ +template K_INLINE bool TList::Remove(const T& rElement) { + K_FOREACH (it, *this) { + if (*it == rElement) { + Erase(it); + return true; + } + } + + return false; +} + +/** + * @brief Removes all elements from the list satisfying the condition + * + * @param pPredicate Function to test if the element should be removed + * @return How many elements were removed + */ +template +K_INLINE u32 TList::RemoveIf(bool (*pPredicate)(const T&)) { + K_ASSERT_PTR(pPredicate); + + Iterator it = Begin(); + u32 eraseNum = 0; + + while (it != End()) { + if (!pPredicate(*it)) { + ++it; + continue; + } + + it = Erase(it); + eraseNum++; + } + + return eraseNum; +} + +/** + * @brief Erases range of nodes + * + * @param begin Beginning of range (inclusive) + * @param end End of range (exclusive) + * @return Iterator to end of range + */ +template +K_INLINE typename TList::Iterator TList::Erase(Iterator begin, + Iterator end) { + TListNode* pCurr = begin.mpNode; + TListNode* pEnd = end.mpNode; + + while (pCurr != pEnd) { + // Preserve next node before erasing pointers + TListNode* pNext = pCurr->mpNext; + + EraseNode(pCurr); + pCurr = pNext; + } + + return end; +} + +/** + * @brief Inserts node at iterator + * + * @param iter Iterator at which to insert node + * @param pNode Node to insert + * @return Iterator to new node + */ +template +K_INLINE typename TList::Iterator TList::InsertNode(Iterator iter, + TListNode* pNode) { + K_ASSERT_PTR(pNode); + + TListNode* pNext = iter.mpNode; + TListNode* pPrev = pNext->mpPrev; + + // pPrev <- pNode -> pNext + pNode->mpNext = pNext; + pNode->mpPrev = pPrev; + // pPrev <-> pNode <-> pNext + pNext->mpPrev = pNode; + pPrev->mpNext = pNode; + + mSize++; + + return Iterator(pNode); +} + +/** + * @brief Erases node from list + * + * @param pNode Node to erase + * @return Iterator to next node + */ +template +K_INLINE typename TList::Iterator TList::EraseNode(TListNode* pNode) { + K_ASSERT_PTR(pNode); + + TListNode* pNext = pNode->mpNext; + TListNode* pPrev = pNode->mpPrev; + + // Remove connections to node + pNext->mpPrev = pPrev; + pPrev->mpNext = pNext; + // Isolate node + pNode->mpNext = nullptr; + pNode->mpPrev = nullptr; + // Free memory + delete pNode; + + mSize--; + + return Iterator(pNext); +} + +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/prim/kiwiMeta.h b/lib/libkiwi/prim/kiwiMeta.h new file mode 100644 index 0000000..64b7e49 --- /dev/null +++ b/lib/libkiwi/prim/kiwiMeta.h @@ -0,0 +1,148 @@ +#ifndef LIBKIWI_PRIM_META_H +#define LIBKIWI_PRIM_META_H +#include + +namespace kiwi { +//! @addtogroup libkiwi_prim +//! @{ + +namespace mp { +//! @addtogroup libkiwi_mp +//! @{ + +/****************************************************************************** + * + * Type trait constants + * + ******************************************************************************/ + +/** + * @name Primitive constants + */ +/**@{*/ +template struct integral_constant { + static const T value = V; +}; + +struct true_type : integral_constant {}; +struct false_type : integral_constant {}; +/**@}*/ + +/****************************************************************************** + * + * Type categories + * + ******************************************************************************/ + +/** + * @name Tests whether the specified type is a pointer + */ +/**@{*/ +template struct is_pointer : false_type {}; + +template struct is_pointer : true_type {}; +template struct is_pointer : true_type {}; +template struct is_pointer : true_type {}; +template struct is_pointer : true_type {}; +/**@}*/ + +/****************************************************************************** + * + * Type properties + * + ******************************************************************************/ + +/** + * @name Tests whether the specified type is const-qualified + */ +/**@{*/ +template struct is_const : false_type {}; +template struct is_const : true_type {}; +/**@}*/ + +/****************************************************************************** + * + * Type modifications + * + ******************************************************************************/ + +/** + * @name Adds a const qualifier to the specified type + */ +/**@{*/ +template struct add_const { + typedef const T type; +}; +/**@}*/ + +/** + * @name Removes the const qualifier from the specified type + */ +/**@{*/ +template struct remove_const { + typedef T type; +}; +template struct remove_const { + typedef T type; +}; +/**@}*/ + +/** + * @name Moves the const qualifier from the first type to the second type + */ +/**@{*/ +template struct move_const { + typedef TTo type; +}; + +template +struct move_const { + typedef const typename remove_const::type type; +}; + +template struct move_const { + typedef const typename remove_const::type type; +}; + +template struct move_const { + typedef const typename remove_const::type type; +}; +/**@}*/ + +/****************************************************************************** + * + * Type transformations + * + ******************************************************************************/ + +/** + * @name Conditional expression + */ +/**@{*/ +template struct conditional { + typedef T type; +}; + +template struct conditional { + typedef F type; +}; +/**@}*/ + +/** + * @name Conditional enable + */ +/**@{*/ +template struct enable_if {}; + +template struct enable_if { + typedef T type; +}; +/**@}*/ + +//! @} +} // namespace mp + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/prim/kiwiMutex.h b/lib/libkiwi/prim/kiwiMutex.h new file mode 100644 index 0000000..040536d --- /dev/null +++ b/lib/libkiwi/prim/kiwiMutex.h @@ -0,0 +1,224 @@ +#ifndef LIBKIWI_PRIM_MUTEX_H +#define LIBKIWI_PRIM_MUTEX_H +#include +#include +#include +#include +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_prim +//! @{ + +/** + * @name Functions for lockable types + */ +/**@{*/ +/** + * @brief Initializes a mutex/lockable object + * @details Default specialization does nothing. + * + * @tparam T Mutex/lockable type + * @param rLockable Lockable object + */ +template K_INLINE void InitMutex(T& rLockable) {} +/** + * @brief Locks a mutex/lockable object + * @details Default specialization expects a "Lock" method. + * + * @tparam T Mutex/lockable type + * @param rLockable Lockable object + */ +template K_INLINE void LockMutex(T& rLockable) { + rLockable.Lock(); +} +/** + * @brief Unlocks a mutex/lockable object + * @details Default specialization expects a "Lock" method. + * + * @tparam T Mutex/lockable type + * @param rLockable Lockable object + */ +template K_INLINE void UnlockMutex(T& rLockable) { + rLockable.Unlock(); +} +/** + * @brief Unlocks a mutex/lockable object + * @details Default specialization expects a "TryLock" method, returning its + * success. + * + * @tparam T Mutex/lockable type + * @param rLockable Lockable object + */ +template K_INLINE bool TryLockMutex(T& rLockable) { + return rLockable.TryLock(); +} +/** + * @brief Tests whether an OS mutex object is locked + * @details Default specialization expects a "IsLocked" method, returning its + * result. + * + * @param rMutex OS mutex + */ +template K_INLINE bool CheckLockMutex(const T& rMutex) { + return rMutex.IsLocked(); +} +/**@}*/ + +/** + * @name Function specializations for OS types + */ +/**@{*/ +/** + * @brief Initializes an OS mutex object + * + * @param rMutex OS mutex + */ +template <> K_INLINE void InitMutex(OSMutex& rMutex) { + OSInitMutex(&rMutex); +} +/** + * @brief Locks an OS mutex object + * + * @param rMutex OS mutex + */ +template <> K_INLINE void LockMutex(OSMutex& rMutex) { + if (OSGetCurrentThread() != nullptr) { + OSLockMutex(&rMutex); + } +} +/** + * @brief Unlocks an OS mutex object + * + * @param rMutex OS mutex + */ +template <> K_INLINE void UnlockMutex(OSMutex& rMutex) { + if (OSGetCurrentThread() != nullptr) { + OSUnlockMutex(&rMutex); + } +} +/** + * @brief Unlocks an OS mutex object + * + * @param rMutex OS mutex + */ +template <> K_INLINE bool TryLockMutex(OSMutex& rMutex) { + return OSTryLockMutex(&rMutex); +} +/** + * @brief Tests whether an OS mutex object is locked + * + * @param rMutex OS mutex + */ +template <> K_INLINE bool CheckLockMutex(const OSMutex& rMutex) { + return rMutex.lock != 0; +} +/**@}*/ + +/** + * @brief Mutex synchronization primitive + * + * @tparam T Lockable object type + */ +template class TMutex : private NonCopyable { +public: + /** + * @brief Constructor + */ + TMutex() { + InitMutex(mMutexImpl); + } + /** + * @brief Destructor + */ + ~TMutex() { + K_ASSERT(!CheckLockMutex(mMutexImpl)); + } + + /** + * @brief Locks the mutex + */ + void Lock() { + LockMutex(mMutexImpl); + } + /** + * @brief Unlocks the mutex + */ + void Unlock() { + UnlockMutex(mMutexImpl); + } + + bool TryLock() { + return TryLockMutex(mMutexImpl); + } + +private: + //! Mutex implementation + T mMutexImpl; +}; + +//! Shorthand for OS mutex +typedef TMutex Mutex; + +/** + * @brief Scoped auto-lock + * + * @tparam T Mutex/lockable type + */ +template class TAutoMutexLock : private NonCopyable { +public: + /** + * @brief Constructor + * + * @param rLockable Lockable object + */ + TAutoMutexLock(T& rLockable) : mrLockable(rLockable) { + LockMutex(mrLockable); + } + /** + * @brief Destructor + */ + ~TAutoMutexLock() { + UnlockMutex(mrLockable); + } + +private: + //! Lockable object + T& mrLockable; +}; + +//! Shorthand for OS mutex auto-lock +typedef TAutoMutexLock AutoMutexLock; + +/** + * @brief Scoped auto-lock for OS hardware interrupts + */ +class AutoInterruptLock : private NonCopyable { +public: + /** + * @brief Constructor + * @details The default setting disables interrupts. + * + * @param enable Initial interrupt status for the lock + */ + AutoInterruptLock(bool enable = false) + : mEnabled(enable ? OSEnableInterrupts() : OSDisableInterrupts()) {} + + /** + * @brief Destructor + */ + ~AutoInterruptLock() { + OSRestoreInterrupts(mEnabled); + } + +private: + //! Hardware interrupt status + BOOL mEnabled; +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/prim/kiwiPair.h b/lib/libkiwi/prim/kiwiPair.h deleted file mode 100644 index 261c66d..0000000 --- a/lib/libkiwi/prim/kiwiPair.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef LIBKIWI_PRIM_PAIR_H -#define LIBKIWI_PRIM_PAIR_H -#include - -namespace kiwi { -//! @addtogroup libkiwi_prim -//! @{ - -/** - * @brief std::pair replacement - */ -template struct TPair { - /** - * @brief Constructor - * - * @param rFirst First element - * @param rSecond Second element - */ - TPair(const TFirst& rFirst, const TSecond& rSecond) - : first(rFirst), second(rSecond) {} - - //! First element - TFirst first; - //! Second element - TSecond second; -}; - -namespace { -//! @addtogroup libkiwi_prim -//! @{ - -/** - * @brief Pair construction helper - * - * @param rFirst First element - * @param rSecond Second element - */ -template -TPair MakePair(const TFirst& rFirst, const TSecond& rSecond) { - return TPair(rFirst, rSecond); -} - -//! @} -} // namespace -//! @} -} // namespace kiwi - -#endif diff --git a/lib/libkiwi/prim/kiwiSTL.cpp b/lib/libkiwi/prim/kiwiSTL.cpp index ad3159d..d0bf400 100644 --- a/lib/libkiwi/prim/kiwiSTL.cpp +++ b/lib/libkiwi/prim/kiwiSTL.cpp @@ -69,7 +69,7 @@ char* strchr(const char* pStr, char c) { * @param pSeq Sequence to search for */ const char* strstr(const char* pStr, const char* pSeq) { - K_ASSERT(pStr != nullptr); + K_ASSERT_PTR(pStr); // No sequence/empty sequence if (pSeq == nullptr || *pSeq == '\0') { @@ -137,7 +137,7 @@ size_t strnlen(const char* pStr, size_t maxlen) { * @param base Number base (specify 0 to auto-detect) */ s32 strtol(const char* pStr, char** pEndPtr, int base) { - K_ASSERT(pStr != nullptr); + K_ASSERT_PTR(pStr); // Trim leading whitespace while (*pStr == ' ') { @@ -237,7 +237,7 @@ u32 strtoul(const char* pStr, char** pEndPtr, int base) { * @param pStr String to convert */ f64 atof(const char* pStr) { - K_ASSERT(pStr != nullptr); + K_ASSERT_PTR(pStr); // Skip whitespace while (*pStr == ' ') { @@ -265,8 +265,8 @@ f64 atof(const char* pStr) { * @param maxlen Maximum number of characters to concatenate */ wchar_t* wcsncat(wchar_t* pwDst, const wchar_t* pwSrc, size_t maxlen) { - K_ASSERT(pwDst != nullptr); - K_ASSERT(pwSrc != nullptr); + K_ASSERT_PTR(pwDst); + K_ASSERT_PTR(pwSrc); // Backup original argument wchar_t* pBackup = pwDst; @@ -300,8 +300,8 @@ wchar_t* wcsncat(wchar_t* pwDst, const wchar_t* pwSrc, size_t maxlen) { * @param maxlen Maximum number of characters to compare */ int wcsncmp(const wchar_t* pwStr1, const wchar_t* pwStr2, size_t maxlen) { - K_ASSERT(pwStr1 != nullptr); - K_ASSERT(pwStr2 != nullptr); + K_ASSERT_PTR(pwStr1); + K_ASSERT_PTR(pwStr2); for (int i = 0; i < maxlen; i++) { if (*pwStr1 != *pwStr2) { @@ -326,7 +326,7 @@ int wcsncmp(const wchar_t* pwStr1, const wchar_t* pwStr2, size_t maxlen) { * @param pwSeq Sequence to search for */ const wchar_t* wcsstr(const wchar_t* pwStr, const wchar_t* pwSeq) { - K_ASSERT(pwStr != nullptr); + K_ASSERT_PTR(pwStr); // No sequence/empty sequence if (pwSeq == nullptr || *pwSeq == L'\0') { diff --git a/lib/libkiwi/prim/kiwiSmartPtr.h b/lib/libkiwi/prim/kiwiSmartPtr.h index b285e78..4e66b60 100644 --- a/lib/libkiwi/prim/kiwiSmartPtr.h +++ b/lib/libkiwi/prim/kiwiSmartPtr.h @@ -1,10 +1,11 @@ #ifndef LIBKIWI_PRIM_SMART_PTR_H #define LIBKIWI_PRIM_SMART_PTR_H -#include #include #include #include +#include + namespace kiwi { //! @addtogroup libkiwi_prim //! @{ @@ -128,8 +129,8 @@ template class SmartPtr : private NonCopyable { T* operator->() { return Get(); } const T* operator->() const { return Get(); } - T& operator*() { K_ASSERT(mpData != nullptr); return *Get(); } - const T& operator*() const { K_ASSERT(mpData != nullptr); return *Get(); } + T& operator*() { K_ASSERT_PTR(mpData); return *Get(); } + const T& operator*() const { K_ASSERT_PTR(mpData); return *Get(); } // clang-format on private: diff --git a/lib/libkiwi/prim/kiwiStack.h b/lib/libkiwi/prim/kiwiStack.h index 547a6a4..d581d06 100644 --- a/lib/libkiwi/prim/kiwiStack.h +++ b/lib/libkiwi/prim/kiwiStack.h @@ -2,70 +2,91 @@ #define LIBKIWI_PRIM_STACK_H #include #include -#include +#include +#include namespace kiwi { //! @addtogroup libkiwi_prim //! @{ /** - * @brief Templated stack + * @brief Templated stack (LI-FO structure) */ -template class TStack : private TList { -private: - // TODO!!!!! BAD - typedef TList BaseType; - typedef T* ElemType; - typedef T& RefType; +template class TStack { +public: + // Stack iteration will be in the reverse order of the list + typedef typename TList::RevIterator Iterator; + typedef typename TList::ConstRevIterator ConstIterator; + typedef typename TList::Iterator RevIterator; + typedef typename TList::ConstIterator ConstRevIterator; + +public: + // Autogen const/reverse getters + K_GEN_ITERATOR_METHODS(TStack); public: /** * @brief Gets the number of elements in the stack */ u32 Size() const { - return TList::Size(); + return mList.Size(); } /** * @brief Tests whether the stack is empty */ bool Empty() const { - return Size() == 0; + return mList.Empty(); + } + + /** + * @brief Gets an iterator to the top of the stack + */ + Iterator Begin() { + return mList.REnd(); + } + /** + * @brief Gets an iterator to the bottom of the stack + */ + Iterator End() { + return mList.RBegin(); } /** * @brief Pushes an element to the stack * - * @param pElem New element + * @param rElement New element */ - void Push(ElemType pElem) { - K_ASSERT(pElem != nullptr); - TList::PushBack(pElem); + void Push(const T& rElement) { + mList.PushBack(rElement); } /** - * @brief Pops an element from the stack - * @details No element is returned to prevent undefined behavior. + * @brief Pops the element from the top of the stack * - * @param pElem New element + * @returns The element that was just erased */ - void Pop() { + T Pop() { K_ASSERT(!Empty()); - TList::PopBack(); + return mList.PopBack(); } /** * @brief Accesses the element at the top of the stack */ - RefType Top() { + T& Top() { K_ASSERT(!Empty()); - return TList::Back(); + return mList.Back(); } /** * @brief Accesses the element at the top of the stack (const-view) */ - const RefType Top() const { + const T& Top() const { K_ASSERT(!Empty()); - return TList::Back(); + return mList.Back(); } + +private: + //! Internal list + TList mList; }; //! @} diff --git a/lib/libkiwi/prim/kiwiString.cpp b/lib/libkiwi/prim/kiwiString.cpp index 2caff46..678c704 100644 --- a/lib/libkiwi/prim/kiwiString.cpp +++ b/lib/libkiwi/prim/kiwiString.cpp @@ -139,7 +139,7 @@ u32 StringImpl::Find(const StringImpl& rStr, u32 pos) const { * @return Match position if found, otherwise npos */ template u32 StringImpl::Find(const T* pStr, u32 pos) const { - K_ASSERT(pStr != nullptr); + K_ASSERT_PTR(pStr); // Cannot match past end of string if (pos >= mLength) { @@ -199,7 +199,7 @@ bool StringImpl::StartsWith(const StringImpl& rStr) const { * @param pStr Prefix sequence */ template bool StringImpl::StartsWith(const T* pStr) const { - K_ASSERT(pStr != nullptr); + K_ASSERT_PTR(pStr); return Find(pStr) == 0; } @@ -220,7 +220,7 @@ bool StringImpl::EndsWith(const StringImpl& rStr) const { * @param pStr Suffix sequence */ template bool StringImpl::EndsWith(const T* pStr) const { - K_ASSERT(pStr != nullptr); + K_ASSERT_PTR(pStr); size_t pos = mLength - StrLen(pStr); return Find(pStr, pos) == pos; @@ -286,7 +286,7 @@ bool StringImpl::operator==(const StringImpl& rStr) const { * @param pStr C-style string to compare against */ template bool StringImpl::operator==(const T* pStr) const { - K_ASSERT(pStr != nullptr); + K_ASSERT_PTR(pStr); // Compare string data return StrNCmp(mpBuffer, pStr, mLength) == 0; @@ -316,7 +316,7 @@ template void StringImpl::Assign(const StringImpl& rStr) { * @param n Number of characters to copy */ template void StringImpl::Assign(const T* pStr, u32 n) { - K_ASSERT(pStr != nullptr); + K_ASSERT_PTR(pStr); // Reserve string buffer u32 len = n != npos ? n : StrLen(pStr); @@ -411,7 +411,7 @@ template <> String StringImpl::ToMultiByte() const { */ template <> String StringImpl::ToMultiByte() const { char* pMultiByteBuffer = new char[Length()]; - K_ASSERT(pMultiByteBuffer != nullptr); + K_ASSERT_PTR(pMultiByteBuffer); std::wcstombs(pMultiByteBuffer, CStr(), Length()); String str(pMultiByteBuffer); @@ -425,7 +425,7 @@ template <> String StringImpl::ToMultiByte() const { */ template <> WString StringImpl::ToWideChar() const { wchar_t* pWideCharBuffer = new wchar_t[Length()]; - K_ASSERT(pWideCharBuffer != nullptr); + K_ASSERT_PTR(pWideCharBuffer); std::mbstowcs(pWideCharBuffer, CStr(), Length()); WString wstr(pWideCharBuffer); diff --git a/lib/libkiwi/prim/kiwiString.h b/lib/libkiwi/prim/kiwiString.h index 81619f4..461ddac 100644 --- a/lib/libkiwi/prim/kiwiString.h +++ b/lib/libkiwi/prim/kiwiString.h @@ -239,11 +239,11 @@ template class StringImpl { // clang-format off StringImpl& operator=(const StringImpl& rStr) { Assign(rStr); return *this; } - StringImpl& operator=(const T* pStr) { K_ASSERT(pStr != nullptr); Assign(pStr); return *this; } + StringImpl& operator=(const T* pStr) { K_ASSERT_PTR(pStr); Assign(pStr); return *this; } StringImpl& operator=(T c) { Assign(c); return *this; } StringImpl& operator+=(const StringImpl& rStr) { Append(rStr); return *this; } - StringImpl& operator+=(const T* pStr) { K_ASSERT(pStr != nullptr); Append(pStr); return *this; } + StringImpl& operator+=(const T* pStr) { K_ASSERT_PTR(pStr); Append(pStr); return *this; } StringImpl& operator+=(T c) { Append(c); return *this; } bool operator==(const StringImpl& rStr) const; @@ -366,7 +366,7 @@ template StringImpl Format(const T* pFmt, ...); * @param rKey Key */ template K_INLINE hash_t Hash(const StringImpl& rKey) { - return HashImpl(rKey.CStr(), rKey.Length() * sizeof(T)); + return MurmurHash(rKey.CStr(), rKey.Length() * sizeof(T)); } #define TO_STRING_PRIM(T, pFmt, val) \ diff --git a/lib/libkiwi/prim/kiwiVector.h b/lib/libkiwi/prim/kiwiVector.h index fd59f6d..3072dd0 100644 --- a/lib/libkiwi/prim/kiwiVector.h +++ b/lib/libkiwi/prim/kiwiVector.h @@ -10,202 +10,113 @@ namespace kiwi { //! @{ /** - * @brief Dynamically-sized, contiguous array (std::vector) + * @brief Dynamically-sized array with contiguous elements + * @details Same concept as std::vector */ template class TVector { public: - // Forward declarations - class ConstIterator; - /** * @brief Vector iterator */ - class Iterator { - template friend class TVector; - friend class ConstIterator; + template + class IteratorImpl + : public RandomAccessIterator, TValue> { + friend class TVector; + + // Allow promotion to const iterator + friend class IteratorImpl::type>; public: /** * @brief Constructor * - * @param pVector Parent container - * @param index Element index + * @param pVector Parent vector + * @param index Vector position */ - explicit Iterator(TVector* pVector, u32 index) - : mpParent(pVector), mIndex(index) { + IteratorImpl(TVector* pVector, u32 index) + : mpVector(pVector), mIndex(index) { - K_ASSERT(pVector != nullptr); - K_ASSERT(0 <= index && index <= pVector->Size()); + K_ASSERT_PTR(mpVector); + K_ASSERT(mIndex <= mpVector->Size()); } - /** - * @brief Pre-increment operator + * @brief Constructor + * + * @param rOther Iterator */ - Iterator& operator++() { - // Can't iterate - if (mIndex >= mpParent->Size()) { - return *this; - } + template + IteratorImpl(const IteratorImpl& rOther) + : mpVector(rOther.mpVector), mIndex(rOther.mIndex) { - mIndex++; - return *this; - } - /** - * @brief Post-increment operator - */ - Iterator operator++(int) { - Iterator clone(*this); - ++*this; - return clone; + K_ASSERT_PTR(mpVector); + K_ASSERT(mIndex <= mpVector->Size()); } /** - * @brief Pre-decrement operator + * @brief Increments the iterator once */ - Iterator& operator--() { - // Can't iterate - if (mIndex == 0) { - return *this; - } - - mIndex--; - return *this; + void Next() { + mIndex++; } /** - * @brief Post-decrement operator + * @brief Decrements the iterator once */ - Iterator operator--(int) { - Iterator clone(*this); - --*this; - return clone; - } - - T* operator->() const { - K_ASSERT(mpParent != nullptr); - - if (mIndex >= mpParent->Size()) { - return nullptr; - } - - return &(*mpParent)[mIndex]; - } - T& operator*() const { - K_ASSERT(mpParent != nullptr); - K_ASSERT(0 <= mIndex && mIndex < mpParent->Size()); - - return (*mpParent)[mIndex]; + void Prev() { + mIndex--; } - // clang-format off - bool operator==(Iterator rhs) const { return mpParent == rhs.mpParent && mIndex == rhs.mIndex; } - bool operator!=(Iterator rhs) const { return mpParent != rhs.mpParent || mIndex != rhs.mIndex; } - // clang-format on - - private: - TVector* mpParent; //!< Parent vector - u32 mIndex; //!< Element index - }; - - /** - * @brief Vector iterator (const-view) - */ - class ConstIterator { - template friend class TVector; - - public: /** - * @brief Constructor + * @brief Advances the iterator by a specified amount * - * @param pVector Parent container - * @param index Element index + * @param n Amount to move */ - explicit ConstIterator(TVector* pVector, u32 index) - : mpParent(pVector), mIndex(index) { - - K_ASSERT(pVector != nullptr); - K_ASSERT(0 <= index && index <= pVector->Size()); + void Move(int n) { + mIndex += n; } /** - * @brief Constructor + * @brief Computes the distance between iterators * - * @param iter Iterator + * @param other Other iterator */ - ConstIterator(Iterator iter) - : mpParent(iter.mpParent), mIndex(iter.mIndex) { - - K_ASSERT(mpParent != nullptr); - K_ASSERT(0 <= mIndex && mIndex <= mpParent->Size()); + template + int Dist(IteratorImpl other) const { + K_ASSERT(mpVector == other.mpVector); + return other.mIndex - mIndex; } /** - * @brief Pre-increment operator + * @brief Accesses the iterator's value */ - ConstIterator& operator++() { - // Can't iterate - if (mIndex >= mpParent->Size()) { - return *this; - } + TValue& Get() { + K_ASSERT_PTR(mpVector); + K_ASSERT_EX(mIndex < mpVector->Size(), + "Invalid iterator (index: %d)", mIndex); - mIndex++; - return *this; - } - /** - * @brief Post-increment operator - */ - ConstIterator operator++(int) { - ConstIterator clone(*this); - ++*this; - return clone; + return mpVector->At(mIndex); } /** - * @brief Pre-decrement operator - */ - ConstIterator& operator--() { - // Can't iterate - if (mIndex == 0) { - return *this; - } - - mIndex--; - return *this; - } - /** - * @brief Post-decrement operator + * @brief Tests two iterators for equality + * + * @param other Other iterator */ - ConstIterator operator--(int) { - ConstIterator clone(*this); - --*this; - return clone; + template + bool Equals(IteratorImpl other) const { + return mpVector == other.mpVector && mIndex == other.mIndex; } - const T* operator->() const { - K_ASSERT(mpParent != nullptr); - - if (mIndex >= mpParent->Size()) { - return nullptr; - } - - return &(*mpParent)[mIndex]; - } - const T& operator*() const { - K_ASSERT(mpParent != nullptr); - K_ASSERT(0 <= mIndex && mIndex < mpParent->Size()); - - return (*mpParent)[mIndex]; - } - - // clang-format off - bool operator==(ConstIterator rhs) const { return mpParent == rhs.mpParent && mIndex == rhs.mIndex; } - bool operator!=(ConstIterator rhs) const { return mpParent != rhs.mpParent || mIndex != rhs.mIndex; } - // clang-format on - private: - TVector* mpParent; //!< Parent vector - u32 mIndex; //!< Element index + //! Parent vector + TVector* mpVector; + //! Vector position + int mIndex; }; + // Autogen typedefs and const/reverse getters + K_GEN_ITERATOR_TYPEDEFS(IteratorImpl, T); + K_GEN_ITERATOR_METHODS(TVector); + public: /** * @brief Constructor @@ -228,190 +139,225 @@ template class TVector { * @param rOther Vector to copy */ TVector(const TVector& rOther) : mpData(nullptr), mCapacity(0), mSize(0) { - CopyFrom(rOther); - } - -#ifdef LIBKIWI_CPP1X - /** - * @brief Constructor - * @details Move constructor - * - * @param rOther Vector to move - */ - TVector(TVector&& rOther) : mpData(nullptr), mCapacity(0), mSize(0) { - MoveFrom(std::move(rOther)); + *this = rOther; } -#endif /** * @brief Destructor */ - ~TVector() { - // Destroy contents - Clear(); - - // Free array buffer - delete mpData; - } + ~TVector(); /** * @brief Vector copy assignment * * @param rOther Vector to copy */ - TVector& operator=(const TVector& rOther) { - CopyFrom(rOther); - return *this; - } + TVector& operator=(const TVector& rOther); -#ifdef LIBKIWI_CPP1X /** - * @brief Vector move assignment - * - * @param rOther Vector to move + * @brief Erases all elements from the vector */ - TVector& operator=(TVector&& rOther) { - MoveFrom(std::move(rOther)); - return *this; + void Clear() { + Erase(Begin(), End()); } -#endif + /** + * @brief Reserves space for elements in the vector + * + * @param capacity New capacity + */ + void Reserve(u32 capacity); /** - * @brief Gets iterator to beginning of vector + * @brief Gets an iterator to beginning of the vector */ Iterator Begin() { return Iterator(this, 0); } /** - * @brief Gets iterator to beginning of vector (const view) + * @brief Gets an iterator to the end of the vector */ - ConstIterator Begin() const { - return ConstIterator(const_cast(this)->Begin()); + Iterator End() { + return Iterator(this, Size()); } /** - * @brief Gets iterator to end of vector + * @brief Gets the number of elements in the vector */ - Iterator End() { - return Iterator(this, Size()); + u32 Size() const { + return mSize; } /** - * @brief Gets iterator to end of vector (const-view) + * @brief Tests whether the vector is empty */ - ConstIterator End() const { - return ConstIterator(const_cast(this)->End()); + bool Empty() const { + return Size() == 0; } /** - * @brief Gets the number of elements in the vector + * @brief Erases the last element from the vector + * + * @returns The element that was just erased */ - u32 Size() const { - return mSize; + T PopBack(); + /** + * @brief Appends an element to the end of the vector + * + * @param rElement New element + */ + void PushBack(const T& rElement) { + Insert(End(), rElement); } /** - * @brief Tests whether the vector is empty + * @brief Gets a reference to the first element of the vector */ - bool Empty() const { - return mSize == 0; + T& Front() { + K_ASSERT_PTR(mpData); + K_ASSERT(!Empty()); + return Data()[0]; + } + /** + * @brief Gets a reference to the first element of the vector (const-view) + */ + const T& Front() const { + K_ASSERT_PTR(mpData); + K_ASSERT(!Empty()); + return Data()[0]; + } + + /** + * @brief Gets a reference to the last element of the vector + */ + T& Back() { + K_ASSERT_PTR(mpData); + K_ASSERT(!Empty()); + return Data()[Size() - 1]; + } + /** + * @brief Gets a reference to the last element of the vector (const-view) + */ + const T& Back() const { + K_ASSERT_PTR(mpData); + K_ASSERT(!Empty()); + return Data()[Size() - 1]; } /** - * @brief Accesses element + * @brief Accesses an element by index * * @param i Element index - * @return Reference to element */ - T& operator[](u32 i) { - K_ASSERT(i < mSize); - K_ASSERT(mpData != nullptr); - return Buffer()[i]; + T& At(u32 i) { + K_ASSERT(i < Size()); + return Data()[i]; } /** - * @brief Accesses element (read-only) + * @brief Accesses an element by index (const-view) * * @param i Element index - * @return Reference to element */ - const T& operator[](u32 i) const { - K_ASSERT(i < mSize); - K_ASSERT(mpData != nullptr); - return Buffer()[i]; + const T& At(u32 i) const { + K_ASSERT(i < Size()); + return Data()[i]; } /** - * @brief Clears vector contents + * @brief Accesses the underlying element data */ - void Clear(); - + T* Data() { + return reinterpret_cast(mpData); + } /** - * @brief Inserts a new element at the specified position - * - * @param rElem New element - * @param pos Element position + * @brief Accesses the underlying element data (const-view) */ - void Insert(const T& rElem, u32 pos); + const T* Data() const { + return reinterpret_cast(mpData); + } /** - * @brief Removes an element if it exists in the vector + * @brief Removes the first occurrence of an element from the vector * - * @param rElem Element to remove - * @return Whether the element existed and was removed + * @param rElement Element to remove + * @return Whether the element was found and removed */ - bool Remove(const T& rElem); + bool Remove(const T& rElement); /** * @brief Removes an element at the specified position * * @param pos Element position */ - void RemoveAt(u32 pos); + void RemoveAt(u32 pos) { + K_ASSERT(pos < Size()); + Erase(Begin() + pos); + } /** - * @brief Inserts a new element at the back of the vector + * @brief Removes all elements from the list satisfying the condition * - * @param rElem New element + * @param pPredicate Function to test if the element should be removed + * @return How many elements were removed */ - void PushBack(const T& rElem); + u32 RemoveIf(bool (*pPredicate)(const T&)); /** - * @brief Removes the last element from the vector + * @brief Inserts a new element at the specified position + * @details Value is inserted before the given iterator + * + * @param it Iterator at which to insert the element + * @param rElement Element to insert + * @returns Iterator to the new element */ - void PopBack(); + Iterator Insert(Iterator it, const T& rElement); -private: /** - * @brief Accesses underlying array buffer + * @brief Erases the element at the specified iterator's position + * + * @param it Iterator at which to erase element + * @return Iterator to the next element after the erased element */ - T* Buffer() const { - return reinterpret_cast(mpData); + Iterator Erase(Iterator it) { + Iterator copy(it); + return Erase(it, ++copy); } /** - * @brief Reserves space for elements in the vector + * @brief Erases range of nodes * - * @param capacity New capacity + * @param begin Beginning of range (inclusive) + * @param end End of range (exclusive) + * @return Iterator to end of range */ - void Reserve(u32 capacity); + Iterator Erase(Iterator begin, Iterator end); /** - * @brief Copies vector contents + * @brief Sorts elements in the vector using the specified comparator + * function + * @details The sort order defaults to ascending order when a comparator is + * not specified. * - * @param other Vector to copy from + * @param pComparator Function used to compare two elements. Returns true + * when the first element is less-than the second element. */ - void CopyFrom(const TVector& rOther); + void Sort(bool (*pComparator)(const T&, const T&) = kiwi::Less) { + kiwi::Sort(Begin(), End(), pComparator); + } - /** - * @brief Moves vector contents - * - * @param other Vector to move - */ - void MoveFrom(TVector&& rOther); + // clang-format off + T& operator[](u32 i) { return At(i); } + T& operator()(u32 i) { return At(i); } + const T& operator[](u32 i) const { return At(i); } + const T& operator()(u32 i) const { return At(i); } + // clang-format on private: - u8* mpData; // Allocated buffer - u32 mCapacity; // Buffer size - u32 mSize; // Number of elements + //! Number of elements in the vector + u32 mSize; + //! Maximum number of elements + u32 mCapacity; + + //! Element data buffer + u8* mpData; }; //! @} diff --git a/lib/libkiwi/prim/kiwiVectorImpl.hpp b/lib/libkiwi/prim/kiwiVectorImpl.hpp index 1ded77b..144384e 100644 --- a/lib/libkiwi/prim/kiwiVectorImpl.hpp +++ b/lib/libkiwi/prim/kiwiVectorImpl.hpp @@ -12,161 +12,175 @@ namespace kiwi { /** - * @brief Clears vector contents + * @brief Destructor */ -template K_INLINE void TVector::Clear() { - K_ASSERT(mSize == 0 || mpData != nullptr); - - for (u32 i = 0; i < mSize; i++) { - Buffer()[i].~T(); - } +template K_INLINE TVector::~TVector() { + Clear(); - mSize = 0; + delete mpData; + mpData = nullptr; } /** - * @brief Inserts a new element at the specified position + * @brief Vector copy assignment * - * @param rElem New element - * @param pos Element position + * @param rOther Vector to copy */ template -K_INLINE void TVector::Insert(const T& rElem, u32 pos) { - K_ASSERT(pos <= mSize); - - // Make space for one extra element - Reserve(mSize + 1); - - K_ASSERT(mpData != nullptr); +K_INLINE TVector& TVector::operator=(const TVector& rOther) { + // Release old data + Clear(); + Reserve(rOther.mSize); - // Inserted in the middle, copy forward - if (pos < mSize) { - std::memcpy(Buffer() + pos + 1, Buffer() + pos, - (mSize - pos) * sizeof(T)); + if (rOther.mSize > 0) { + K_ASSERT_PTR(rOther.mpData); + std::memcpy(mpData, rOther.mpData, rOther.mSize * sizeof(T)); } - // Copy construct in-place - new (&Buffer()[pos]) T(rElem); - mSize++; + mSize = rOther.mSize; + return *this; } /** - * @brief Removes an element if it exists in the vector + * @brief Reserves space for elements in the vector * - * @param rElem Element to remove - * @return Whether the element existed and was removed + * @param capacity New capacity */ -template K_INLINE bool TVector::Remove(const T& rElem) { - K_ASSERT(mSize == 0 || mpData != nullptr); +template K_INLINE void TVector::Reserve(u32 capacity) { + if (mCapacity >= capacity) { + return; + } - // Linear search for the target - for (u32 i = 0; i < mSize; i++) { - if (Buffer()[i] == rElem) { - RemoveAt(i); - return true; - } + u8* pBuffer = new u8[capacity * sizeof(T)]; + K_ASSERT_PTR(pBuffer); + + // Copy in old data + if (mSize > 0) { + K_ASSERT_PTR(mpData); + std::memcpy(pBuffer, mpData, mSize * sizeof(T)); + delete mpData; } - // Element not in the vector - return false; + mpData = pBuffer; + mCapacity = capacity; } /** - * @brief Removes an element at the specified position + * @brief Erases the last element from the vector * - * @param pos Element position + * @returns The element that was just erased */ -template K_INLINE void TVector::RemoveAt(u32 pos) { - K_ASSERT(pos < mSize); - K_ASSERT(mpData != nullptr); +template K_INLINE T TVector::PopBack() { + K_ASSERT(!Empty()); - // Destroy element - Buffer()[pos].~T(); - - // Removed from the middle, copy backward - if (pos < mSize) { - std::memcpy(Buffer() + pos, Buffer() + pos + 1, - (mSize - pos) * sizeof(T)); - } + Iterator back = --End(); + T element = *back; - mSize--; + Erase(back); + return element; } /** - * @brief Inserts a new element at the back of the vector + * @brief Removes the first occurrence of an element from the vector * - * @param rElem New element + * @param rElement Element to remove + * @return Whether the element was found and removed */ -template K_INLINE void TVector::PushBack(const T& rElem) { - Insert(rElem, mSize); -} +template K_INLINE bool TVector::Remove(const T& rElement) { + K_FOREACH (it, *this) { + if (*it == rElement) { + Erase(it); + return true; + } + } -/** - * @brief Removes the last element from the vector - */ -template K_INLINE void TVector::PopBack() { - K_ASSERT(mSize > 0); - Remove(mSize - 1); + return false; } /** - * @brief Reserves space for elements in the vector + * @brief Removes all elements from the list satisfying the condition * - * @param capacity New capacity + * @param pPredicate Function to test if the element should be removed + * @return How many elements were removed */ -template K_INLINE void TVector::Reserve(u32 capacity) { - // All good! - if (mCapacity >= capacity) { - return; - } +template +K_INLINE u32 TVector::RemoveIf(bool (*pPredicate)(const T&)) { + K_ASSERT_PTR(pPredicate); - // Need to reallocate - u8* pBuffer = new u8[capacity * sizeof(T)]; - K_ASSERT(pBuffer != nullptr); + Iterator it = Begin(); + u32 eraseNum = 0; - // Copy in old data - if (mpData != nullptr) { - std::memcpy(pBuffer, mpData, mSize * sizeof(T)); - delete mpData; + while (it != End()) { + if (!pPredicate(*it)) { + ++it; + continue; + } + + it = Erase(it); + eraseNum++; } - // Swap buffer - mpData = pBuffer; - mCapacity = capacity; + return eraseNum; } /** - * @brief Copies vector contents + * @brief Inserts a new element at the specified position + * @details Value is inserted before the given iterator * - * @param rOther Vector to copy from + * @param it Iterator at which to insert the element + * @param rElement Element to insert + * @returns Iterator to the new element */ template -K_INLINE void TVector::CopyFrom(const TVector& rOther) { - // Destroy existing contents - Clear(); +K_INLINE typename TVector::Iterator TVector::Insert(Iterator it, + const T& rElement) { + // Fit one more element + Reserve(mSize + 1); + K_ASSERT_PTR(mpData); - // Make sure we can fit the contents - Reserve(rOther.mSize); - std::memcpy(mpData, rOther.mpData, rOther.mSize * sizeof(T)); + // Front/middle insert requires copying forward + if (it.mIndex < mSize) { + std::memcpy(Data() + it.mIndex + 1, // + Data() + it.mIndex, // + (mSize - it.mIndex) * sizeof(T)); + } + + // Construct in-place + new (&Data()[it.mIndex]) T(rElement); + mSize++; + + // Input iterator will end up pointing at the new element + return it; } /** - * @brief Moves vector contents + * @brief Erases range of nodes * - * @param rOther Vector to move + * @param begin Beginning of range (inclusive) + * @param end End of range (exclusive) + * @return Iterator to end of range */ -template K_INLINE void TVector::MoveFrom(TVector&& rOther) { - // Destroy contents & free buffer - Clear(); - delete mpData; +template +K_INLINE typename TVector::Iterator TVector::Erase(Iterator begin, + Iterator end) { + K_ASSERT(begin <= end); - mpData = rOther.mpData; - mCapacity = rOther.mCapacity; - mSize = rOther.mSize; + // Destroy objects + for (Iterator it = begin; it != end; ++it) { + (*it).~T(); + } + + // Front/middle erase requires copying back + if (end.mIndex < mSize) { + std::memcpy(Data() + begin.mIndex, // + Data() + end.mIndex, // + (mSize - end.mIndex) * sizeof(T)); + } + + mSize -= end - begin; - rOther.mpData = nullptr; - rOther.mCapacity = 0; - rOther.mSize = 0; + // Next element will end up at the range start + return begin; } } // namespace kiwi diff --git a/lib/libkiwi/resource/kiwiMultiArchive.cpp b/lib/libkiwi/resource/kiwiMultiArchive.cpp new file mode 100644 index 0000000..4a4d838 --- /dev/null +++ b/lib/libkiwi/resource/kiwiMultiArchive.cpp @@ -0,0 +1,149 @@ +// TODO(kiwi) Needs changes for WSR +#if !defined(PACK_RESORT) + +// Implementation must be visible to the extension +#define private protected +#include +#undef private + +#include +#include + +#include + +#include + +#include + +namespace kiwi { + +/** + * @brief Destructor + */ +MultiArchive::~MultiArchive() { + K_FOREACH (it, mPatchArchives) { + delete *it; + } +} + +/** + * @brief Attempts to mount a resource file + * + * @param rResource Resource file + * @param pHeap Heap to use for archive allocation (defaults to current + * heap) + * @param align Alignment to use for archive allocation + */ +MultiArchive* MultiArchive::Mount(const Resource& rResource, EGG::Heap* pHeap, + s32 align) { + + if (pHeap == nullptr) { + pHeap = EGG::Heap::getCurrentHeap(); + } + + K_ASSERT_PTR(pHeap); + + MultiArchive* pArchive = FindArchive(rResource); + if (pArchive != nullptr) { + pArchive->mRefCount++; + return pArchive; + } + + pArchive = new (align, pHeap) MultiArchive(rResource); + K_ASSERT_PTR(pArchive); + + const void* pBaseData = rResource.GetBaseFile().GetData(); + K_ASSERT_PTR(pBaseData); + + bool success = ARCInitHandle(pBaseData, &pArchive->mHandle); + K_ASSERT(success); + + pArchive->mMountType = success ? MOUNT_TYPE_MEM : MOUNT_TYPE_NONE; + + K_FOREACH (it, rResource.GetPatchFiles()) { + K_ASSERT_PTR(*it); + + void* pPatchData = const_cast((*it)->GetData()); + + EGG::Archive* pPatchArchive = + EGG::Archive::mount(pPatchData, pHeap, align); + + K_ASSERT_PTR(pPatchArchive); + pArchive->mPatchArchives.PushBack(pPatchArchive); + } + + return pArchive; +} + +/** + * @brief Attempts to get a file from one of the open archives + * @details The patch archives take precedence over the base archive. + * @note The hierarchy of patch archives is the order they were mounted. + * + * @param pPath File path + * @param[out] pInfo File info + * @return File data + */ +void* MultiArchive::GetFile(const char* pPath, FileInfo* pInfo) { + K_ASSERT_PTR(pPath); + K_ASSERT_EX(mMountType != MOUNT_TYPE_NONE, + "Please mount a base archive first"); + + void* pFileData = nullptr; + EGG::Archive::FileInfo eggInfo; + + // Patch archives take precedence over the base archive + K_FOREACH (it, mPatchArchives) { + K_ASSERT_PTR(*it); + + if ((pFileData = (*it)->getFile(pPath, &eggInfo))) { + if (pInfo != nullptr) { + pInfo->offset = eggInfo.getStartOffset(); + pInfo->length = eggInfo.getLength(); + } + + return pFileData; + } + } + + if ((pFileData = EGG::Archive::getFile(pPath, &eggInfo))) { + if (pInfo != nullptr) { + pInfo->offset = eggInfo.getStartOffset(); + pInfo->length = eggInfo.getLength(); + } + + return pFileData; + } + + return nullptr; +} + +/** + * @brief Attempts to find the archive mounting the specified resource file + * + * @param rResource Resource file + * @return Cached archive (if it exists) + */ +MultiArchive* MultiArchive::FindArchive(const Resource& rResource) { + if (!sIsArchiveListInitialized) { + return nullptr; + } + + // Mounted archive will have a handle to the base data + const void* pBaseData = rResource.GetBaseFile().GetData(); + + NW4R_UT_LIST_FOREACH(Archive, it, sArchiveList, { + K_ASSERT_PTR(it); + MultiArchive* pArchive = static_cast(it); + + if (pArchive->mHandle.archiveStartAddr == pBaseData) { + return pArchive; + } + }); + + return nullptr; +} + +} // namespace kiwi + +#endif \ No newline at end of file diff --git a/lib/libkiwi/resource/kiwiMultiArchive.h b/lib/libkiwi/resource/kiwiMultiArchive.h new file mode 100644 index 0000000..9673a1b --- /dev/null +++ b/lib/libkiwi/resource/kiwiMultiArchive.h @@ -0,0 +1,94 @@ +// TODO(kiwi) Needs changes for WSR +#if !defined(PACK_RESORT) + +#ifndef LIBKIWI_RESOURCE_MULTI_ARCHIVE_H +#define LIBKIWI_RESOURCE_MULTI_ARCHIVE_H +#include +#include +#include +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_resource +//! @{ + +/** + * @brief Multi-handle archive + */ +class MultiArchive : public EGG::Archive { +public: + /** + * @brief Archive file info + */ + struct FileInfo { + u32 offset; //! File offset into the archive + u32 length; //! File size, in bytes + + /** + * @brief Constructor + */ + FileInfo() : offset(0), length(0) {} + }; + +public: + /** + * @brief Attempts to mount a resource file + * + * @param rResource Resource file + * @param pHeap Heap to use for archive allocation (defaults to current + * heap) + * @param align Alignment to use for archive allocation + */ + static MultiArchive* Mount(const Resource& rResource, + EGG::Heap* pHeap = nullptr, s32 align = 4); + + /** + * @brief Destructor + */ + virtual ~MultiArchive(); + + /** + * @brief Attempts to get a file from one of the open archives + * @details The patch archives take precedence over the base archive. + * @note The hierarchy of patch archives is the order they were mounted. + * + * @param pPath File path + * @param[out] pInfo File info + * @return File data + */ + void* GetFile(const char* pPath, FileInfo* pInfo = nullptr); + +private: + /** + * @brief Constructor + * + * @param rResource Mounted resource file + */ + MultiArchive(const Resource& rResource) : mrResource(rResource) { + K_ASSERT_PTR(rResource.GetBaseFile().GetData()); + } + + /** + * @brief Attempts to find the archive mounting the specified resource file + * + * @param rResource Resource file + * @return Cached archive (if it exists) + */ + static MultiArchive* FindArchive(const Resource& rResource); + +private: + //! Currently mounted resource file (non-owning view) + const Resource& mrResource; + + //! Patched/delta resource archives + TList mPatchArchives; +}; + +//! @} +} // namespace kiwi + +#endif + +#endif \ No newline at end of file diff --git a/lib/libkiwi/resource/kiwiResource.cpp b/lib/libkiwi/resource/kiwiResource.cpp new file mode 100644 index 0000000..30c347c --- /dev/null +++ b/lib/libkiwi/resource/kiwiResource.cpp @@ -0,0 +1,46 @@ +// TODO(kiwi) Needs changes for WSR +#if !defined(PACK_RESORT) + +#include + +#include + +#include + +#include + +namespace kiwi { + +/** + * @brief Constructor + * + * @param pPath Archive file path + * @param size Archive file size + * @param pData Archive file data + */ +Resource::Resource(const char* pPath, u32 size, const void* pData) + : mBaseFile(pPath, size, static_cast(pData)) { + + K_ASSERT_PTR(pPath); + K_ASSERT_PTR(pData); + + u32 pathLen = std::strlen(pPath); + K_ASSERT(pathLen <= PATH_MAX); + + K_ASSERT(!PtrUtil::IsLibKiwi(pData)); +} + +/** + * @brief Destructor + */ +Resource::~Resource() { + ResourceMgr::RemoveResourceFromCache(*this); + + K_FOREACH (it, mPatchFiles) { + delete *it; + } +} + +} // namespace kiwi + +#endif \ No newline at end of file diff --git a/lib/libkiwi/resource/kiwiResource.h b/lib/libkiwi/resource/kiwiResource.h new file mode 100644 index 0000000..fabca24 --- /dev/null +++ b/lib/libkiwi/resource/kiwiResource.h @@ -0,0 +1,77 @@ +// TODO(kiwi) Needs changes for WSR +#if !defined(PACK_RESORT) + +#ifndef LIBKIWI_RESOURCE_RESOURCE_H +#define LIBKIWI_RESOURCE_RESOURCE_H +#include +#include +#include + +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_resource +//! @{ + +/** + * @brief In-memory resource file + */ +class Resource : public EGG::Disposer { +public: + /** + * @brief Constructor + * + * @param pPath Archive file path + * @param size Archive file size + * @param pData Archive file data + */ + Resource(const char* pPath, u32 size, const void* pData); + /** + * @brief Destructor + */ + virtual ~Resource(); + + /** + * @brief Registers a new patch file + * + * @param rPatchFile New patch file + */ + void RegistPatch(RPSysFile& rPatchFile) { + K_ASSERT_PTR(rPatchFile.GetData()); + mPatchFiles.PushBack(&rPatchFile); + } + + /** + * @brief Gets the base file for this resource + */ + const RPSysFile& GetBaseFile() const { + return mBaseFile; + } + + /** + * @brief Gets the list of patch files for this resource + */ + const TList& GetPatchFiles() const { + return mPatchFiles; + } + +private: + //! Maximum file path length + static const int PATH_MAX = FS_MAX_PATH; + +private: + //! Base archive file + RPSysFile mBaseFile; + + //! Patch archive files + TList mPatchFiles; +}; + +//! @} +} // namespace kiwi + +#endif + +#endif \ No newline at end of file diff --git a/lib/libkiwi/resource/kiwiResourceMgr.cpp b/lib/libkiwi/resource/kiwiResourceMgr.cpp new file mode 100644 index 0000000..93a8886 --- /dev/null +++ b/lib/libkiwi/resource/kiwiResourceMgr.cpp @@ -0,0 +1,526 @@ +// TODO(kiwi) Needs changes for WSR +#if !defined(PACK_RESORT) + +// Implementation must be visible to the extension +#define private protected +#include +#undef private + +#include +#include +#include + +#include + +#include + +#include + +#include + +#include + +namespace kiwi { +namespace { + +/** + * @brief Gets the current locale directory name + */ +String GetLocalDirectory() { + char buffer[32]; + std::memset(buffer, 0, sizeof(buffer)); + + RP_GET_INSTANCE(RPSysProjectLocal)->appendLocalDirectory(buffer); + buffer[sizeof(buffer) - 1] = '\0'; + + return String(buffer); +} + +} // namespace + +/** + * @brief Patch archive file extension + */ +const char* ResourceMgr::scPatchExtension = ".wpatch"; + +/** + * @brief Static/shared directory names + */ +const char* ResourceMgr::scStaticDirs[kiwi::EPackID_Max] = { + "SportsStatic/", // EPackID_SportsPack + "PartyStatic/", // EPackID_PartyPack + "HealthStatic/", // EPackID_HealthPack + "MusicStatic/", // EPackID_MusicPack + "AllPackStatic/", // EPackID_AllPack +}; + +/** + * @brief Scenes with cached archives + */ +const kiwi::ESceneID ResourceMgr::scCachedScenes[] = { +#if defined(PACK_SPORTS) + ESceneID_RPSysPlayerSelectScene, + ESceneID_RPSysNunchukScene, + ESceneID_RPBsbScene, + ESceneID_RPBowScene, + ESceneID_RPGolScene, + ESceneID_RPTnsScene, + ESceneID_RPBoxScene, + ESceneID_RPSportsTitleScene, + ESceneID_RPSportsMenuScene, + ESceneID_RPSportsTrainingMenuScene, + ESceneID_RPSportsPhysicalMenuScene, + ESceneID_RPSportsPhysicalPreviewScene, + ESceneID_RPSportsPhysicalResultScene, + ESceneID_RPGolSelectScene, +#elif defined(PACK_PLAY) + ESceneID_RPSysPlayerSelectScene, + ESceneID_RPSysNunchukScene, + ESceneID_RPFshScene, + ESceneID_RPHkyScene, + ESceneID_RPDucScene, + ESceneID_RPPnpScene, + ESceneID_RPBilScene, + ESceneID_RPCowScene, + ESceneID_RPWlyScene, + ESceneID_RPTnkScene, + ESceneID_RPBomScene, + ESceneID_RPPartyTitleScene, + ESceneID_RPPartyMenuScene, +#else +#error Not yet implemented for WSR +#endif +}; + +/** + * @brief Resource file cache + */ +THashMap ResourceMgr::sResourceCache; + +/** + * @brief Decompressed resource file cache + */ +THashMap ResourceMgr::sDecompCache; + +/** + * @brief Attempts to get the specified file from the archive + * + * @param pArchive Archive containing the file + * @param pPath File path + * @param[out] pSize File size, in bytes + */ +void* ResourceMgr::GetFileFromArchive(MultiArchive* pArchive, const char* pPath, + u32* pSize) { + + K_ASSERT_PTR(pArchive); + K_ASSERT_PTR(pPath); + + MultiArchive::FileInfo info; + void* pFileData = pArchive->GetFile(pPath, &info); + + K_ASSERT_PTR_EX(pFileData, "Can't find file: %s", pPath); + + if (pSize != nullptr) { + *pSize = info.length; + } + + return pFileData; +} +KOKESHI_BY_PACK(KOKESHI_NOTIMPLEMENTED, // Wii Sports + KM_BRANCH(0x801871E0, ResourceMgr::GetFileFromArchive), // Wii Play + KOKESHI_NOTIMPLEMENTED); // Wii Sports Resort + +/** + * @brief Removes the specified resource file from the cache + * + * @param rResource Resource file + */ +void ResourceMgr::RemoveResourceFromCache(const Resource& rResource) { + K_FOREACH (it, sResourceCache) { + if (it->value == &rResource) { + sResourceCache.Remove(it->key); + break; + } + } + + K_FOREACH (it, sDecompCache) { + if (it->value == &rResource) { + sDecompCache.Remove(it->key); + break; + } + } +} + +/** + * @brief Attempts to get the specified message data (BMG) + * + * @param pPath Message file path + * @return Message file data + */ +void* ResourceMgr::GetMessageResource(const char* pPath) { + return GetFileFromArchive( + static_cast(GetInstance().mpMessageArchive), pPath); +} +KOKESHI_BY_PACK(KOKESHI_NOTIMPLEMENTED, // Wii Sports + KM_BRANCH(0x801871A4, ResourceMgr::GetMessageResource), // Wii Play + KOKESHI_NOTIMPLEMENTED); // Wii Sports Resort + +/** + * @brief Attempts to load the common archive for the specified scene + * + * @note The "common" archive must always be named `common.carc`. + * + * @param scene Scene ID + * @param pHeap Heap from which to allocate the buffer + * @return Multi-handle archive containing any patches + */ +MultiArchive* ResourceMgr::LoadGameCommonArchive(s32 scene, EGG::Heap* pHeap) { + if (pHeap == nullptr) { + pHeap = EGG::Heap::getCurrentHeap(); + } + + K_ASSERT_PTR(pHeap); + + const char* pResDir = SceneCreator::GetInstance().GetSceneDirectory(scene); + K_ASSERT_PTR(pResDir); + + const Resource* pResource = LoadDecomp( // + Format("Common/%scommon.carc", // + pResDir), // + pHeap); + + K_ASSERT_PTR(pResource); + + MultiArchive* pArchive = MultiArchive::Mount(*pResource, pHeap); + K_ASSERT_PTR(pArchive); + + return pArchive; +} +KOKESHI_BY_PACK(KOKESHI_NOTIMPLEMENTED, // Wii Sports + KM_BRANCH(0x801872D4, ResourceMgr::LoadGameCommonArchive), // Wii Play + KOKESHI_NOTIMPLEMENTED); // Wii Sports Resort + +/** + * @brief Attempts to load the local archive for the specified scene + * + * @note The "local" archive must always be named `local.carc`. + * + * @param scene Scene ID + * @param pHeap Heap from which to allocate the buffer + * @return Multi-handle archive containing any patches + */ +MultiArchive* ResourceMgr::LoadGameLocalArchive(s32 scene, EGG::Heap* pHeap) { + if (pHeap == nullptr) { + pHeap = EGG::Heap::getCurrentHeap(); + } + + K_ASSERT_PTR(pHeap); + + const char* pResDir = SceneCreator::GetInstance().GetSceneDirectory(scene); + K_ASSERT_PTR(pResDir); + + const Resource* pResource = LoadDecomp( // + Format("%s%slocal.carc", // + GetLocalDirectory().CStr(), // + pResDir), // + pHeap); + + K_ASSERT_PTR(pResource); + + MultiArchive* pArchive = MultiArchive::Mount(*pResource, pHeap); + K_ASSERT_PTR(pArchive); + + return pArchive; +} +KOKESHI_BY_PACK(KOKESHI_NOTIMPLEMENTED, // Wii Sports + KM_BRANCH(0x8018722C, ResourceMgr::LoadGameLocalArchive), // Wii Play + KOKESHI_NOTIMPLEMENTED); // Wii Sports Resort + +/** + * @brief Loads all resources with static lifetime + */ +void ResourceMgr::LoadStaticArchives() { + const char* pStaticDir = + scStaticDirs[RP_GET_INSTANCE(RPSysProjectLocal)->getPack()]; + + EGG::Heap* pResHeap = RP_GET_INSTANCE(RPSysSystem)->getResourceHeap(); + K_ASSERT_PTR(pResHeap); + + const Resource* pResource = nullptr; + + // Common static archive + pResource = + LoadDecomp(Format("Common/%scommon.carc", pStaticDir), pResHeap); + + K_ASSERT_PTR(pResource); + mpStaticCommonArchive = MultiArchive::Mount(*pResource, pResHeap); + K_ASSERT_PTR(mpStaticCommonArchive); + + // Locale static archive + pResource = LoadDecomp( + Format("%s%slocal.carc", GetLocalDirectory().CStr(), pStaticDir), + pResHeap); + + K_ASSERT_PTR(pResource); + mpStaticLocalArchive = MultiArchive::Mount(*pResource, pResHeap); + K_ASSERT_PTR(mpStaticLocalArchive); + + // Message archive + pResource = LoadDecomp( + Format("%sMessage/message.carc", GetLocalDirectory().CStr()), pResHeap); + + K_ASSERT_PTR(pResource); + mpMessageArchive = MultiArchive::Mount(*pResource, pResHeap); + K_ASSERT_PTR(mpMessageArchive); + + // Font archive + pResource = LoadDecomp( + Format("%sFont/font.carc", GetLocalDirectory().CStr()), pResHeap); + + K_ASSERT_PTR(pResource); + mpFontArchive = MultiArchive::Mount(*pResource, pResHeap); + K_ASSERT_PTR(mpFontArchive); + + RPPartyBodyManager* pBodyManager = new (pResHeap) RPPartyBodyManager(); + K_ASSERT_PTR(pBodyManager); + RP_GET_INSTANCE(RPSysKokeshiManager)->SetBodyManager(pBodyManager); + + RP_GET_INSTANCE(RPSysFontManager)->LoadResFonts(); +} +KOKESHI_BY_PACK(KOKESHI_NOTIMPLEMENTED, // Wii Sports + KM_BRANCH_MF(0x80186FA4, ResourceMgr, LoadStaticArchives), // Wii Play + KOKESHI_NOTIMPLEMENTED); // Wii Sports Resort + +/** + * @brief Loads all cached resources + */ +void ResourceMgr::LoadCacheArchives() { + EGG::Heap* pResHeap = RP_GET_INSTANCE(RPSysSystem)->getResourceHeap(); + K_ASSERT_PTR(pResHeap); + + for (int i = 0; i < K_LENGTHOF(scCachedScenes); i++) { + const char* pResDir = + SceneCreator::GetInstance().GetSceneDirectory(scCachedScenes[i]); + + K_ASSERT_PTR(pResDir); + + // Not enough memory to decompress these all ahead of time + const Resource* pCommonResource = + Load(Format("Common/%scommon.carc", pResDir), pResHeap); + + K_ASSERT_PTR(pCommonResource); + + // TODO: Why only Wii Play? Are the local archives just that small? +#if defined(PACK_PLAY) + // Not enough memory to decompress these all ahead of time + const Resource* pLocalResource = + Load(Format("%s%slocal.carc", GetLocalDirectory().CStr(), pResDir), + pResHeap); + + K_ASSERT_PTR(pLocalResource); +#endif + } +} +KOKESHI_BY_PACK(KOKESHI_NOTIMPLEMENTED, // Wii Sports + KM_BRANCH_MF(0x80186D54, ResourceMgr, LoadCacheArchives), // Wii Play + KOKESHI_NOTIMPLEMENTED); // Wii Sports Resort + +/** + * @brief Loads the Kokeshi archive + */ +void ResourceMgr::LoadKokeshiArchive() { + EGG::Heap* pResHeap = RP_GET_INSTANCE(RPSysSystem)->getResourceHeap(); + K_ASSERT_PTR(pResHeap); + + const Resource* pResource = + LoadDecomp("Common/Kokeshi/common.carc", pResHeap); + + K_ASSERT_PTR(pResource); + + mpKokeshiArchive = MultiArchive::Mount(*pResource, pResHeap); + K_ASSERT_PTR(mpKokeshiArchive); +} +KOKESHI_BY_PACK(KOKESHI_NOTIMPLEMENTED, // Wii Sports + KM_BRANCH_MF(0x80186CEC, ResourceMgr, LoadKokeshiArchive), // Wii Play + KOKESHI_NOTIMPLEMENTED); // Wii Sports Resort + +/** + * @brief Attempts to load the specified resource file + * + * @param pPath Archive path + * @param pHeap Heap to use for allocations + * @param cache Whether to cache the resource file + * @return Resource file + */ +const Resource* ResourceMgr::Load(const char* pPath, EGG::Heap* pHeap, + bool cache) { + K_ASSERT_PTR(pPath); + + if (pHeap == nullptr) { + pHeap = EGG::Heap::getCurrentHeap(); + } + + K_ASSERT_PTR(pHeap); + + // May have already been loaded + const Resource* pResource = sResourceCache.Get(pPath); + if (pResource != nullptr) { + return pResource; + } + + // Need to load + FileRipperArg arg; + arg.align = 32; + arg.pHeap = pHeap; + + u32 fileSize = 0; + arg.pSize = &fileSize; + + // Base file is required + void* pBaseData = FileRipper::Rip(pPath, EStorage_DVD, arg); + K_ASSERT_PTR_EX(pBaseData, "Can't find file: %s", pPath); + + DCFlushRange(pBaseData, fileSize); + + Resource* pNewResource = new (pHeap) Resource(pPath, fileSize, pBaseData); + K_ASSERT_PTR(pNewResource); + + // Patch file is optional + String patchPath = String(pPath) + scPatchExtension; + void* pPatchData = FileRipper::Rip(patchPath, EStorage_DVD, arg); + + if (pPatchData != nullptr) { + RPSysFile* pPatchFile = + new (pHeap) RPSysFile(patchPath, fileSize, pPatchData); + + K_ASSERT_PTR(pPatchFile); + pNewResource->RegistPatch(*pPatchFile); + } + + if (cache) { + sResourceCache.Insert(pPath, pNewResource); + } + + return pNewResource; +} + +/** + * @brief Attempts to load and decompress the specified resource file + * + * @param pPath Archive path + * @param pHeap Heap to use for allocations + * @return Resource file + */ +const Resource* ResourceMgr::LoadDecomp(const char* pPath, EGG::Heap* pHeap) { + K_ASSERT_PTR(pPath); + + if (pHeap == nullptr) { + pHeap = EGG::Heap::getCurrentHeap(); + } + + K_ASSERT_PTR(pHeap); + + // May have already been decompressed + const Resource* pResource = sDecompCache.Get(pPath); + if (pResource != nullptr) { + return pResource; + } + + // May have already been loaded, but not decompressed yet + pResource = sResourceCache.Get(pPath); + + // Don't cache it because we will decompress it + if (pResource == nullptr) { + pResource = Load(pPath, pHeap, false); + } + + K_ASSERT_PTR(pResource); + + const Resource* pDecompResource = DecompResource(*pResource, pHeap); + K_ASSERT_PTR(pDecompResource); + + // Can release compressed resource + if (pDecompResource != pResource) { + delete pResource; + } + + sDecompCache.Insert(pPath, pDecompResource); + return pDecompResource; +} + +/** + * @brief Attempts to decompress the specified resource file + * + * @param rResource Resource file + * @param pHeap Heap to use for allocations + * @return Decompressed resource + */ +const Resource* ResourceMgr::DecompResource(const Resource& rResource, + EGG::Heap* pHeap) { + + if (pHeap == nullptr) { + pHeap = EGG::Heap::getCurrentHeap(); + } + + K_ASSERT_PTR(pHeap); + + RPSysFile* pBaseFile = DecompFile(rResource.GetBaseFile(), pHeap); + K_ASSERT_PTR(pBaseFile); + + Resource* pDecompResource = new (pHeap) Resource( + pBaseFile->GetPath(), pBaseFile->GetSize(), pBaseFile->GetData()); + K_ASSERT_PTR(pDecompResource); + + K_FOREACH (it, rResource.GetPatchFiles()) { + RPSysFile* pPatchFile = DecompFile(**it, pHeap); + + K_ASSERT_PTR(pPatchFile); + pDecompResource->RegistPatch(*pPatchFile); + } + + return pDecompResource; +} + +/** + * @brief Attempts to decompress the specified file + * + * @param rFile File to decompress + * @param pHeap Heap to use for allocations + * @return Decompressed file + */ +RPSysFile* ResourceMgr::DecompFile(const RPSysFile& rFile, EGG::Heap* pHeap) { + if (pHeap == nullptr) { + pHeap = EGG::Heap::getCurrentHeap(); + } + + K_ASSERT_PTR(pHeap); + + u8* pBaseData = const_cast(rFile.GetData()); + K_ASSERT_PTR(pBaseData); + + // Resource may not actually be compressed + if (EGG::Decomp::checkCompressed(pBaseData) == + EGG::Decomp::cCompress_None) { + + return const_cast(&rFile); + } + + s32 expandSize = EGG::Decomp::getExpandSize(pBaseData); + u8* pExpandData = new (32, pHeap) u8[expandSize]; + + K_ASSERT_PTR(pExpandData); + s32 decompSize = EGG::Decomp::decode(pBaseData, pExpandData); + + K_ASSERT_EX(decompSize <= expandSize, "Decomp buffer overflow!"); + DCFlushRange(pExpandData, decompSize); + + RPSysFile* pDecompFile = + new (pHeap) RPSysFile(rFile.GetPath(), decompSize, pExpandData); + K_ASSERT_PTR(pDecompFile); + + return pDecompFile; +} + +} // namespace kiwi + +#endif \ No newline at end of file diff --git a/lib/libkiwi/resource/kiwiResourceMgr.h b/lib/libkiwi/resource/kiwiResourceMgr.h new file mode 100644 index 0000000..53fa09c --- /dev/null +++ b/lib/libkiwi/resource/kiwiResourceMgr.h @@ -0,0 +1,153 @@ +// TODO(kiwi) Needs changes for WSR +#if !defined(PACK_RESORT) + +#ifndef LIBKIWI_RESOURCE_RESOURCE_MGR_H +#define LIBKIWI_RESOURCE_RESOURCE_MGR_H +#include +#include +#include +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_resource +//! @{ + +// Forward declarations +class MultiArchive; +class Resource; + +/** + * @brief Pack Project resource manager extension + */ +class ResourceMgr : public ExtSingletonPtr { +public: + /** + * @brief Attempts to get the specified file from the archive + * + * @param pArchive Archive containing the file + * @param pPath File path + * @param[out] pSize File size, in bytes + */ + static void* GetFileFromArchive(MultiArchive* pArchive, const char* pPath, + u32* pSize = nullptr); + + /** + * @brief Removes the specified resource file from the cache + * + * @param rResource Resource file + */ + static void RemoveResourceFromCache(const Resource& rResource); + + /** + * @brief Attempts to get the specified message data (BMG) + * + * @param pPath Message file path + * @return Message file data + */ + static void* GetMessageResource(const char* pPath); + + /** + * @brief Attempts to load the common archive for the specified scene + * + * @note The "common" archive must always be named `common.carc`. + * + * @param scene Scene ID + * @param pHeap Heap from which to allocate the buffer + * @return Multi-handle archive containing any patches + */ + static MultiArchive* LoadGameCommonArchive(s32 scene = -1, + EGG::Heap* pHeap = nullptr); + + /** + * @brief Attempts to load the local archive for the specified scene + * + * @note The "local" archive must always be named `local.carc`. + * + * @param scene Scene ID + * @param pHeap Heap from which to allocate the buffer + * @return Multi-handle archive containing any patches + */ + static MultiArchive* LoadGameLocalArchive(s32 scene = -1, + EGG::Heap* pHeap = nullptr); + + /** + * @brief Loads all resources with static lifetime + */ + void LoadStaticArchives(); + + /** + * @brief Loads all cached resources + */ + void LoadCacheArchives(); + + /** + * @brief Loads the Kokeshi archive + */ + void LoadKokeshiArchive(); + +private: + /** + * @brief Attempts to load the specified resource file + * + * @param pPath Archive path + * @param pHeap Heap to use for allocations + * @param cache Whether to cache the resource file + * @return Resource file + */ + static const Resource* Load(const char* pPath, EGG::Heap* pHeap = nullptr, + bool cache = false); + + /** + * @brief Attempts to load and decompress the specified resource file + * + * @param pPath Archive path + * @param pHeap Heap to use for allocations + * @return Resource file + */ + static const Resource* LoadDecomp(const char* pPath, + EGG::Heap* pHeap = nullptr); + + /** + * @brief Attempts to decompress the specified resource file + * + * @param rResource Resource file + * @param pHeap Heap to use for allocations + * @return Decompressed resource + */ + static const Resource* DecompResource(const Resource& rResource, + EGG::Heap* pHeap = nullptr); + + /** + * @brief Attempts to decompress the specified file + * + * @param rFile File to decompress + * @param pHeap Heap to use for allocations + * @return Decompressed file + */ + static RPSysFile* DecompFile(const RPSysFile& rFile, + EGG::Heap* pHeap = nullptr); + +private: + //! Patch archive file extension + static const char* scPatchExtension; + + //! Static/shared directory names + static const char* scStaticDirs[kiwi::EPackID_Max]; + + //! Scenes with cached archives + static const kiwi::ESceneID scCachedScenes[]; + + //! Raw resource file cache + static THashMap sResourceCache; + //! Decompressed resource file cache + static THashMap sDecompCache; +}; + +//! @} +} // namespace kiwi + +#endif + +#endif \ No newline at end of file diff --git a/lib/libkiwi/support/kiwiLibEGG.cpp b/lib/libkiwi/support/kiwiLibEGG.cpp new file mode 100644 index 0000000..7a7504d --- /dev/null +++ b/lib/libkiwi/support/kiwiLibEGG.cpp @@ -0,0 +1,28 @@ +#include + +#include + +namespace EGG { + +/****************************************************************************** + * + * Archive + * + ******************************************************************************/ +Archive::Archive() { + mRefCount = 1; + mMountType = MOUNT_TYPE_NONE; + std::memset(&mHandle, 0, sizeof(ARCHandle)); + appendList(this); +} + +void Archive::appendList(Archive* pArchive) { + if (!sIsArchiveListInitialized) { + NW4R_UT_LIST_INIT(sArchiveList, Archive); + sIsArchiveListInitialized = true; + } + + nw4r::ut::List_Append(&sArchiveList, pArchive); +} + +} // namespace EGG diff --git a/lib/libkiwi/support/kiwiLibGX.cpp b/lib/libkiwi/support/kiwiLibGX.cpp index 4dd2724..b20db17 100644 --- a/lib/libkiwi/support/kiwiLibGX.cpp +++ b/lib/libkiwi/support/kiwiLibGX.cpp @@ -1,4 +1,5 @@ #include + #include namespace kiwi { @@ -8,11 +9,26 @@ namespace kiwi { */ const GXRenderModeObj* LibGX::GetDefaultRenderMode() { switch (VIGetTvFormat()) { - case VI_TV_FMT_NTSC: return &GXNtsc480IntDf; - case VI_TV_FMT_PAL: return &GXPal528IntDf; - case VI_TV_FMT_EURGB60: return &GXEurgb60Hz480IntDf; - case VI_TV_FMT_MPAL: return &GXMpal480IntDf; - default: return nullptr; + case VI_TVFORMAT_NTSC: { + return &GXNtsc480IntDf; + } + + case VI_TVFORMAT_PAL: { + return &GXPal528IntDf; + } + + case VI_TVFORMAT_EURGB60: { + return &GXEurgb60Hz480IntDf; + } + + case VI_TVFORMAT_MPAL: { + return &GXMpal480IntDf; + } + + default: { + K_UNREACHABLE(); + return nullptr; + } } } diff --git a/lib/libkiwi/support/kiwiLibOS.cpp b/lib/libkiwi/support/kiwiLibOS.cpp index aff9741..544a908 100644 --- a/lib/libkiwi/support/kiwiLibOS.cpp +++ b/lib/libkiwi/support/kiwiLibOS.cpp @@ -5,10 +5,10 @@ namespace kiwi { /** * @brief Saves floating-point registers to the context * - * @param ctx OS context + * @param pCtx OS context */ -void LibOS::FillFPUContext(register OSContext* ctx) { - K_ASSERT(ctx != nullptr); +void LibOS::FillFPUContext(register OSContext* pCtx) { + K_ASSERT_PTR(pCtx); // clang-format off asm volatile { @@ -17,79 +17,79 @@ void LibOS::FillFPUContext(register OSContext* ctx) { mtmsr r5 isync - stfd f0, ctx->fprs[0] - stfd f1, ctx->fprs[1] - stfd f2, ctx->fprs[2] - stfd f3, ctx->fprs[3] - stfd f4, ctx->fprs[4] - stfd f5, ctx->fprs[5] - stfd f6, ctx->fprs[6] - stfd f7, ctx->fprs[7] - stfd f8, ctx->fprs[8] - stfd f9, ctx->fprs[9] - stfd f10, ctx->fprs[10] - stfd f11, ctx->fprs[11] - stfd f12, ctx->fprs[12] - stfd f13, ctx->fprs[13] - stfd f14, ctx->fprs[14] - stfd f15, ctx->fprs[15] - stfd f16, ctx->fprs[16] - stfd f17, ctx->fprs[17] - stfd f18, ctx->fprs[18] - stfd f19, ctx->fprs[19] - stfd f20, ctx->fprs[20] - stfd f21, ctx->fprs[21] - stfd f22, ctx->fprs[22] - stfd f23, ctx->fprs[23] - stfd f24, ctx->fprs[24] - stfd f25, ctx->fprs[25] - stfd f26, ctx->fprs[26] - stfd f27, ctx->fprs[27] - stfd f28, ctx->fprs[28] - stfd f29, ctx->fprs[29] - stfd f30, ctx->fprs[30] - stfd f31, ctx->fprs[31] + stfd f0, pCtx->fprs[0] + stfd f1, pCtx->fprs[1] + stfd f2, pCtx->fprs[2] + stfd f3, pCtx->fprs[3] + stfd f4, pCtx->fprs[4] + stfd f5, pCtx->fprs[5] + stfd f6, pCtx->fprs[6] + stfd f7, pCtx->fprs[7] + stfd f8, pCtx->fprs[8] + stfd f9, pCtx->fprs[9] + stfd f10, pCtx->fprs[10] + stfd f11, pCtx->fprs[11] + stfd f12, pCtx->fprs[12] + stfd f13, pCtx->fprs[13] + stfd f14, pCtx->fprs[14] + stfd f15, pCtx->fprs[15] + stfd f16, pCtx->fprs[16] + stfd f17, pCtx->fprs[17] + stfd f18, pCtx->fprs[18] + stfd f19, pCtx->fprs[19] + stfd f20, pCtx->fprs[20] + stfd f21, pCtx->fprs[21] + stfd f22, pCtx->fprs[22] + stfd f23, pCtx->fprs[23] + stfd f24, pCtx->fprs[24] + stfd f25, pCtx->fprs[25] + stfd f26, pCtx->fprs[26] + stfd f27, pCtx->fprs[27] + stfd f28, pCtx->fprs[28] + stfd f29, pCtx->fprs[29] + stfd f30, pCtx->fprs[30] + stfd f31, pCtx->fprs[31] mffs f0 - stfd f0, ctx->fpscr_pad - lfd f0, ctx->fprs[0] + stfd f0, pCtx->fpscr_pad + lfd f0, pCtx->fprs[0] mfhid2 r5 rlwinm. r5, r5, 3, 31, 31 // HID2_PSE beq _exit - psq_st f0, OSContext.psfs[0](ctx), 0, 0 - psq_st f1, OSContext.psfs[1](ctx), 0, 0 - psq_st f2, OSContext.psfs[2](ctx), 0, 0 - psq_st f3, OSContext.psfs[3](ctx), 0, 0 - psq_st f4, OSContext.psfs[4](ctx), 0, 0 - psq_st f5, OSContext.psfs[5](ctx), 0, 0 - psq_st f6, OSContext.psfs[6](ctx), 0, 0 - psq_st f7, OSContext.psfs[7](ctx), 0, 0 - psq_st f8, OSContext.psfs[8](ctx), 0, 0 - psq_st f9, OSContext.psfs[9](ctx), 0, 0 - psq_st f10, OSContext.psfs[10](ctx), 0, 0 - psq_st f11, OSContext.psfs[11](ctx), 0, 0 - psq_st f12, OSContext.psfs[12](ctx), 0, 0 - psq_st f13, OSContext.psfs[13](ctx), 0, 0 - psq_st f14, OSContext.psfs[14](ctx), 0, 0 - psq_st f15, OSContext.psfs[15](ctx), 0, 0 - psq_st f16, OSContext.psfs[16](ctx), 0, 0 - psq_st f17, OSContext.psfs[17](ctx), 0, 0 - psq_st f18, OSContext.psfs[18](ctx), 0, 0 - psq_st f19, OSContext.psfs[19](ctx), 0, 0 - psq_st f20, OSContext.psfs[20](ctx), 0, 0 - psq_st f21, OSContext.psfs[21](ctx), 0, 0 - psq_st f22, OSContext.psfs[22](ctx), 0, 0 - psq_st f23, OSContext.psfs[23](ctx), 0, 0 - psq_st f24, OSContext.psfs[24](ctx), 0, 0 - psq_st f25, OSContext.psfs[25](ctx), 0, 0 - psq_st f26, OSContext.psfs[26](ctx), 0, 0 - psq_st f27, OSContext.psfs[27](ctx), 0, 0 - psq_st f28, OSContext.psfs[28](ctx), 0, 0 - psq_st f29, OSContext.psfs[29](ctx), 0, 0 - psq_st f30, OSContext.psfs[30](ctx), 0, 0 - psq_st f31, OSContext.psfs[31](ctx), 0, 0 + psq_st f0, OSContext.psfs[0](pCtx), 0, 0 + psq_st f1, OSContext.psfs[1](pCtx), 0, 0 + psq_st f2, OSContext.psfs[2](pCtx), 0, 0 + psq_st f3, OSContext.psfs[3](pCtx), 0, 0 + psq_st f4, OSContext.psfs[4](pCtx), 0, 0 + psq_st f5, OSContext.psfs[5](pCtx), 0, 0 + psq_st f6, OSContext.psfs[6](pCtx), 0, 0 + psq_st f7, OSContext.psfs[7](pCtx), 0, 0 + psq_st f8, OSContext.psfs[8](pCtx), 0, 0 + psq_st f9, OSContext.psfs[9](pCtx), 0, 0 + psq_st f10, OSContext.psfs[10](pCtx), 0, 0 + psq_st f11, OSContext.psfs[11](pCtx), 0, 0 + psq_st f12, OSContext.psfs[12](pCtx), 0, 0 + psq_st f13, OSContext.psfs[13](pCtx), 0, 0 + psq_st f14, OSContext.psfs[14](pCtx), 0, 0 + psq_st f15, OSContext.psfs[15](pCtx), 0, 0 + psq_st f16, OSContext.psfs[16](pCtx), 0, 0 + psq_st f17, OSContext.psfs[17](pCtx), 0, 0 + psq_st f18, OSContext.psfs[18](pCtx), 0, 0 + psq_st f19, OSContext.psfs[19](pCtx), 0, 0 + psq_st f20, OSContext.psfs[20](pCtx), 0, 0 + psq_st f21, OSContext.psfs[21](pCtx), 0, 0 + psq_st f22, OSContext.psfs[22](pCtx), 0, 0 + psq_st f23, OSContext.psfs[23](pCtx), 0, 0 + psq_st f24, OSContext.psfs[24](pCtx), 0, 0 + psq_st f25, OSContext.psfs[25](pCtx), 0, 0 + psq_st f26, OSContext.psfs[26](pCtx), 0, 0 + psq_st f27, OSContext.psfs[27](pCtx), 0, 0 + psq_st f28, OSContext.psfs[28](pCtx), 0, 0 + psq_st f29, OSContext.psfs[29](pCtx), 0, 0 + psq_st f30, OSContext.psfs[30](pCtx), 0, 0 + psq_st f31, OSContext.psfs[31](pCtx), 0, 0 _exit: } diff --git a/lib/libkiwi/support/kiwiLibSO.cpp b/lib/libkiwi/support/kiwiLibSO.cpp index 1a44ba9..ae42999 100644 --- a/lib/libkiwi/support/kiwiLibSO.cpp +++ b/lib/libkiwi/support/kiwiLibSO.cpp @@ -347,7 +347,7 @@ SOResult LibSO::GetPeerName(SOSocket socket, SockAddrAny& addr) { */ s32 LibSO::Read(SOSocket socket, void* dst, u32 len) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); - K_ASSERT(dst != nullptr); + K_ASSERT_PTR(dst); return Recv(socket, dst, len, 0); } @@ -363,7 +363,7 @@ s32 LibSO::Read(SOSocket socket, void* dst, u32 len) { */ s32 LibSO::Recv(SOSocket socket, void* dst, u32 len, u32 flags) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); - K_ASSERT(dst != nullptr); + K_ASSERT_PTR(dst); return RecvImpl(socket, dst, len, flags, nullptr); } @@ -381,7 +381,7 @@ s32 LibSO::Recv(SOSocket socket, void* dst, u32 len, u32 flags) { s32 LibSO::RecvFrom(SOSocket socket, void* dst, u32 len, u32 flags, SockAddrAny& addr) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); - K_ASSERT(dst != nullptr); + K_ASSERT_PTR(dst); K_ASSERT(addr.IsValid()); return RecvImpl(socket, dst, len, flags, &addr); @@ -397,7 +397,7 @@ s32 LibSO::RecvFrom(SOSocket socket, void* dst, u32 len, u32 flags, */ s32 LibSO::Write(SOSocket socket, const void* src, u32 len) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); - K_ASSERT(src != nullptr); + K_ASSERT_PTR(src); return Send(socket, src, len, 0); } @@ -413,7 +413,7 @@ s32 LibSO::Write(SOSocket socket, const void* src, u32 len) { */ s32 LibSO::Send(SOSocket socket, const void* src, u32 len, u32 flags) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); - K_ASSERT(src != nullptr); + K_ASSERT_PTR(src); return SendImpl(socket, src, len, flags, nullptr); } @@ -431,7 +431,7 @@ s32 LibSO::Send(SOSocket socket, const void* src, u32 len, u32 flags) { s32 LibSO::SendTo(SOSocket socket, const void* src, u32 len, u32 flags, const SockAddrAny& addr) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); - K_ASSERT(src != nullptr); + K_ASSERT_PTR(src); K_ASSERT(addr.IsValid()); return SendImpl(socket, src, len, flags, &addr); @@ -454,7 +454,7 @@ struct SORecvArgs { s32 LibSO::RecvImpl(SOSocket socket, void* dst, u32 len, u32 flags, SockAddrAny* addr) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); - K_ASSERT(dst != nullptr); + K_ASSERT_PTR(dst); K_ASSERT(addr == nullptr || addr->IsValid()); TVector input; @@ -506,7 +506,7 @@ struct SOSendArgs { s32 LibSO::SendImpl(SOSocket socket, const void* src, u32 len, u32 flags, const SockAddrAny* addr) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); - K_ASSERT(src != nullptr); + K_ASSERT_PTR(src); K_ASSERT(addr == nullptr || addr->IsValid()); TVector input; @@ -608,7 +608,7 @@ SOResult LibSO::Shutdown(SOSocket socket, SOShutdownType how) { */ s32 LibSO::Poll(SOPollFD fds[], u32 numfds, s64 timeout) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); - K_ASSERT(fds != nullptr); + K_ASSERT_PTR(fds); K_ASSERT(numfds > 0); IosObject msec(OS_TICKS_TO_MSEC(timeout)); @@ -868,7 +868,7 @@ SOResult LibSO::SetSockOpt(SOSocket socket, SOSockOptLevel level, SOSockOpt opt, const void* val, u32 len) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); K_ASSERT(socket >= 0); - K_ASSERT(val != nullptr); + K_ASSERT_PTR(val); K_ASSERT(len > 0); IosObject args; diff --git a/lib/libkiwi/support/kiwiLibSSL.cpp b/lib/libkiwi/support/kiwiLibSSL.cpp deleted file mode 100644 index d75c94d..0000000 --- a/lib/libkiwi/support/kiwiLibSSL.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include - -namespace kiwi { - -; - -} // namespace kiwi diff --git a/lib/libkiwi/support/kiwiLibSSL.h b/lib/libkiwi/support/kiwiLibSSL.h deleted file mode 100644 index 1caec31..0000000 --- a/lib/libkiwi/support/kiwiLibSSL.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef LIBKIWI_SUPPORT_LIBSSL_H -#define LIBKIWI_SUPPORT_LIBSSL_H -#include -#include -#include -#include - -#include - -namespace kiwi { -//! @addtogroup libkiwi_support -//! @{ - -/** - * @brief SSL library wrapper/extension - */ -class LibSSL { -public: - ; - -private: - //! SSL device - static IosDevice sDevNetSsl; -}; - -//! @} -} // namespace kiwi - -#endif diff --git a/lib/libkiwi/support/kiwiLibVI.cpp b/lib/libkiwi/support/kiwiLibVI.cpp new file mode 100644 index 0000000..c132825 --- /dev/null +++ b/lib/libkiwi/support/kiwiLibVI.cpp @@ -0,0 +1,25 @@ +#include + +#include + +namespace kiwi { + +/** + * @brief Gets the target framerate of the current video configuration + */ +f32 LibVI::GetTargetFrameRate() { + switch (VIGetTvFormat()) { + case VI_TVFORMAT_NTSC: + case VI_TVFORMAT_EURGB60: + default: { + return 59.94f; + } + + case VI_TVFORMAT_PAL: + case VI_TVFORMAT_MPAL: { + return 50.0f; + } + } +} + +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/support/kiwiLibVI.h b/lib/libkiwi/support/kiwiLibVI.h new file mode 100644 index 0000000..f7f0bd6 --- /dev/null +++ b/lib/libkiwi/support/kiwiLibVI.h @@ -0,0 +1,25 @@ +#ifndef LIBKIWI_SUPPORT_LIBVI_H +#define LIBKIWI_SUPPORT_LIBVI_H +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_support +//! @{ + +/** + * @brief VI library wrapper/extension + */ +class LibVI { +public: + /** + * @brief Gets the target framerate of the current video configuration + */ + static f32 GetTargetFrameRate(); +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/test/kiwiIUnitTest.h b/lib/libkiwi/test/kiwiIUnitTest.h new file mode 100644 index 0000000..b68fe32 --- /dev/null +++ b/lib/libkiwi/test/kiwiIUnitTest.h @@ -0,0 +1,157 @@ +#ifndef LIBKIWI_TEST_I_UNIT_TEST_H +#define LIBKIWI_TEST_I_UNIT_TEST_H +#include +#include + +/** + * @brief Defines a unit test and registers it with the test manager + */ +#define KT_TEST(SUITE_NAME, TEST_NAME) \ + class KT_##SUITE_NAME##_##TEST_NAME : public kiwi::detail::IUnitTest { \ + public: \ + KT_##SUITE_NAME##_##TEST_NAME() \ + : kiwi::detail::IUnitTest(#SUITE_NAME, #TEST_NAME) {} \ + \ + private: \ + virtual void Run(); \ + \ + private: \ + static kiwi::detail::UnitTestDecl \ + sTestDecl; \ + }; \ + \ + kiwi::detail::UnitTestDecl \ + KT_##SUITE_NAME##_##TEST_NAME::sTestDecl; \ + \ + void KT_##SUITE_NAME##_##TEST_NAME::Run() + +//! Asserts that the specified expression holds true +#define KT_ASSERT(EXPR) __KT_ASSERT_UNARY(EXPR) + +//! Asserts that the two expressions are equal +#define KT_ASSERT_EQ(X, Y) __KT_ASSERT_BINARY(X, ==, Y) +//! Asserts that the two expressions are not equal +#define KT_ASSERT_NE(X, Y) __KT_ASSERT_BINARY(X, !=, Y) + +//! Asserts that expression X is less-than-or-equal-to Y +#define KT_ASSERT_LE(X, Y) __KT_ASSERT_BINARY(X, <=, Y) +//! Asserts that expression X is less than Y +#define KT_ASSERT_LT(X, Y) __KT_ASSERT_BINARY(X, <, Y) + +//! Asserts that expression X is greater-than-or-equal-to Y +#define KT_ASSERT_GE(X, Y) __KT_ASSERT_BINARY(X, >=, Y) +//! Asserts that expression X is greater than Y +#define KT_ASSERT_GT(X, Y) __KT_ASSERT_BINARY(X, >, Y) + +namespace kiwi { +//! @addtogroup libkiwi_test +//! @{ + +namespace detail { +//! @addtogroup libkiwi_test +//! @{ + +/** + * @brief Unit test interface + */ +class IUnitTest { +public: + /** + * @brief Constructor + * + * @param rSuiteName Test suite name + * @param rTestName Test case name + */ + IUnitTest(const String& rSuiteName, const String& rTestName) + : mSuiteName(rSuiteName), mTestName(rTestName), mIsFailed(false) {} + + /** + * @brief Runs the unit test + */ + virtual void Run() = 0; + + /** + * @brief Gets the test suite name + */ + const String& GetSuiteName() const { + return mSuiteName; + } + /** + * @brief Gets the test case name + */ + const String& GetTestName() const { + return mTestName; + } + + /** + * @brief Tests whether the test case failed + */ + bool IsFailed() const { + return mIsFailed; + } + /** + * @brief Gets the assertion expression that caused the failure + */ + const String& GetFailedExpr() const { + return mFailedExpr; + } + +protected: + //! Test suite name + String mSuiteName; + //! Test case name + String mTestName; + + //! Whether this test failed + bool mIsFailed; + //! Expression that caused the failure + String mFailedExpr; +}; + +//! @} +} // namespace detail + +//! @} +} // namespace kiwi + +//! Internal macro for unary expressions +// clang-format off +#define __KT_ASSERT_UNARY(VAL) \ + __KT_ASSERT_INNER( \ + (VAL), \ + kiwi::Format( \ + /* "%s (%s)", */ \ + "%s", \ + #VAL \ + /* kiwi::ToString(VAL).CStr() */ \ + ) \ + ) +// clang-format on + +//! Internal macro for binary expressions +// clang-format off +#define __KT_ASSERT_BINARY(VALX, OP, VALY) \ + __KT_ASSERT_INNER( \ + ((VALX) OP (VALY)), \ + kiwi::Format( \ + /* "%s %s %s (%s %s %s)", */ \ + "%s %s %s", \ + #VALX, #OP, #VALY \ + /* kiwi::ToString(VALX).CStr(), #OP, kiwi::ToString(VALY).CStr() */\ + ) \ + ) +// clang-format on + +/** + * @brief Internal test assertion macro + */ +#define __KT_ASSERT_INNER(EXPR, STR) \ + do { \ + if (!(EXPR)) { \ + mIsFailed = true; \ + mFailedExpr = STR; \ + return; \ + } \ + } while (0); + +#endif \ No newline at end of file diff --git a/lib/libkiwi/test/kiwiUnitTestMgr.cpp b/lib/libkiwi/test/kiwiUnitTestMgr.cpp new file mode 100644 index 0000000..3766945 --- /dev/null +++ b/lib/libkiwi/test/kiwiUnitTestMgr.cpp @@ -0,0 +1,37 @@ +#include + +namespace kiwi { + +/** + * @brief Runs all registered unit tests + */ +bool UnitTestMgr::Run() { + int testNum = mUnitTests.Size(); + int passNum = 0; + + K_LOG("[UnitTestMgr]\n"); + K_LOG_EX("Running %d test cases\n", testNum); + + K_FOREACH (it, mUnitTests) { + K_ASSERT_PTR(*it); + + // Show fully-qualified test name + K_LOG_EX(">>>>> %s.%s\n", (*it)->GetSuiteName().CStr(), + (*it)->GetTestName().CStr()); + + (*it)->Run(); + passNum += !(*it)->IsFailed() ? 1 : 0; + + // Show failure information + if ((*it)->IsFailed()) { + K_LOG_EX(" FAILED: %s\n", (*it)->GetFailedExpr().CStr()); + } + } + + K_LOG("Complete!\n"); + K_LOG_EX("Passed: %d, Total: %d\n", passNum, testNum); + + return passNum == testNum; +} + +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/test/kiwiUnitTestMgr.h b/lib/libkiwi/test/kiwiUnitTestMgr.h new file mode 100644 index 0000000..8c039e4 --- /dev/null +++ b/lib/libkiwi/test/kiwiUnitTestMgr.h @@ -0,0 +1,77 @@ +#ifndef LIBKIWI_TEST_UNIT_TEST_MGR_H +#define LIBKIWI_TEST_UNIT_TEST_MGR_H +#include +#include +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_test +//! @{ + +// Forward declarations +namespace detail { +template class UnitTestDecl; +} // namespace detail + +/** + * @brief Unit test manager + */ +class UnitTestMgr : public StaticSingleton { + friend class StaticSingleton; + + //! Only UnitTestDecl is allowed to register unit tests + template friend class detail::UnitTestDecl; + +public: + /** + * @brief Runs all registered unit tests + * + * @returns Whether every test passed + */ + bool Run(); + +private: + /** + * @brief Registers a new unit test + * + * @param pTest Unit test + */ + void RegistTest(detail::IUnitTest* pTest) { + K_ASSERT_PTR(pTest); + mUnitTests.PushBack(pTest); + } + +private: + //! List of all unit tests + TList mUnitTests; +}; + +namespace detail { +//! @addtogroup libkiwi_test +//! @{ + +/** + * @brief Unit test declaration + * @details Registers an instance of the test with the test manager + * + * @tparam T Unit test class type + */ +template class UnitTestDecl { +public: + UnitTestDecl() { + IUnitTest* pTest = new T(); + K_ASSERT_PTR(pTest); + + UnitTestMgr::GetInstance().RegistTest(pTest); + } +}; + +//! @} +} // namespace detail + +//! @} +} // namespace kiwi + +#endif \ No newline at end of file diff --git a/lib/libkiwi/test/unit/test_kiwiArray.cpp b/lib/libkiwi/test/unit/test_kiwiArray.cpp new file mode 100644 index 0000000..010cd08 --- /dev/null +++ b/lib/libkiwi/test/unit/test_kiwiArray.cpp @@ -0,0 +1,227 @@ +#include + +namespace kiwi { +namespace ArrayTests { + +/****************************************************************************** + * + * TArrayImpl + * + ******************************************************************************/ + +/** + * @brief Tests that Begin provides an iterator to the first element + */ +KT_TEST(TArrayImpl, Begin) { + TArray array; + + for (int i = 0; i < array.Size(); i++) { + array[i] = i; + } + + KT_ASSERT_NE(array.Begin(), array.End()); + KT_ASSERT_EQ(*array.Begin(), 0); +} + +/** + * @brief Tests that End provides an iterator past the last element + */ +KT_TEST(TArrayImpl, End) { + TArray array; + + for (int i = 0; i < array.Size(); i++) { + array[i] = i; + } + + KT_ASSERT_NE(array.End(), array.Begin()); + KT_ASSERT_EQ(*--array.End(), array.Size() - 1); +} + +/** + * @brief Tests that the Size method accurately reports the number of elements + */ +KT_TEST(TArrayImpl, Size) { + TArray array; + KT_ASSERT_EQ(array.Size(), 10); +} + +/** + * @brief Tests that the Front method accesses the first element in the array + */ +KT_TEST(TArrayImpl, Front) { + TArray array; + + for (int i = 0; i < array.Size(); i++) { + array[i] = i; + } + + KT_ASSERT_EQ(array.Front(), 0); +} + +/** + * @brief Tests that the Back method accesses the last element in the array + */ +KT_TEST(TArrayImpl, Back) { + TArray array; + + for (int i = 0; i < array.Size(); i++) { + array[i] = i; + } + + KT_ASSERT_EQ(array.Back(), array.Size() - 1); +} + +/** + * @brief Tests that the At method accurately reports the specified element + */ +KT_TEST(TArrayImpl, At) { + TArray array; + + for (int i = 0; i < array.Size(); i++) { + // Don't use At to set the values + array.Data()[i] = i; + } + + for (int i = 0; i < array.Size(); i++) { + KT_ASSERT_EQ(array.At(i), i); + } +} + +/** + * @brief Tests that the operator[]/operator() methods accurately report the + * specified element + */ +KT_TEST(TArrayImpl, OperatorAt) { + TArray array; + + for (int i = 0; i < array.Size(); i++) { + // Don't use At to set the values + array.Data()[i] = i; + } + + for (int i = 0; i < array.Size(); i++) { + KT_ASSERT_EQ(array[i], i); + KT_ASSERT_EQ(array(i), i); + } +} + +/** + * @brief Tests that forward iteration produces the expected results + */ +KT_TEST(TArrayImpl, ForwardIterator) { + TArray array; + + for (int i = 0; i < array.Size(); i++) { + array[i] = i; + } + + TArray::Iterator it = array.Begin(); + int i = 0; + + while (i < array.Size()) { + KT_ASSERT_NE(it, array.End()); + KT_ASSERT_EQ(*it, i); + + i++; + ++it; + } +} + +/** + * @brief Tests that reverse iteration produces the expected results + */ +KT_TEST(TArrayImpl, ReverseIterator) { + TArray array; + + for (int i = 0; i < array.Size(); i++) { + array[i] = i; + } + + TArray::RevIterator it = array.RBegin(); + int i = 0; + + while (i < array.Size()) { + KT_ASSERT_NE(it, array.REnd()); + KT_ASSERT_EQ(*it, (array.Size() - 1 - i)); + + i++; + ++it; + } +} + +/****************************************************************************** + * + * TArray1D + * + ******************************************************************************/ + +/** + * @brief Tests that the Sort method correctly sorts all elements + */ +KT_TEST(TArray1D, Sort) { + TArray array; + + for (int i = 0; i < array.Size(); i++) { + // 0, -1, 2, 1, 4, 3, . . . + array[i] = i % 2 == 0 ? i : i - 2; + } + + array.Sort(); + + int prev = -999; + + K_FOREACH (it, array) { + KT_ASSERT_LE(prev, *it); + prev = *it; + } +} + +/****************************************************************************** + * + * TArray2D + * + ******************************************************************************/ + +/** + * @brief Tests that the InnerSize method accurately reports the number of + * columns + */ +KT_TEST(TArray2D, InnerSize) { + TArray2D array; + KT_ASSERT_EQ(array.InnerSize(), 4); +} + +/** + * @brief Tests that the At (element) method accurately reports the specified + * element + */ +KT_TEST(TArray2D, At) { + TArray2D array; + + for (int i = 0; i < array.Size(); i++) { + for (int j = 0; j < array.InnerSize(); j++) { + array[i][j] = array.InnerSize() * i + j; + } + } + + KT_ASSERT_EQ(array.At(1, 0), 4); +} + +/** + * @brief Tests that the operator[]/operator() (element) methods accurately + * report the specified element + */ +KT_TEST(TArray2D, OperatorAt) { + TArray2D array; + + for (int i = 0; i < array.Size(); i++) { + for (int j = 0; j < array.InnerSize(); j++) { + array[i][j] = array.InnerSize() * i + j; + } + } + + KT_ASSERT_EQ(array(1, 0), 4); +} + +} // namespace ArrayTests +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/test/unit/test_kiwiHashMap.cpp b/lib/libkiwi/test/unit/test_kiwiHashMap.cpp new file mode 100644 index 0000000..8af9531 --- /dev/null +++ b/lib/libkiwi/test/unit/test_kiwiHashMap.cpp @@ -0,0 +1,399 @@ +#include + +namespace kiwi { +namespace HashMapTests { + +/****************************************************************************** + * + * THashMap + * + ******************************************************************************/ + +/** + * @brief Tests that a hashmap after construction is empty (no elements and zero + * size) + */ +KT_TEST(THashMap, Constructor) { + THashMap map; + + KT_ASSERT(map.Empty()); + KT_ASSERT_EQ(map.Begin(), map.End()); +} + +/** + * @brief Tests that the copy constructor correctly duplicates elements + */ +KT_TEST(THashMap, CopyConstructor) { + THashMap map; + + for (int i = 0; i < 10; i++) { + map[i] = i % 2 == 0; + } + + THashMap clone(map); + KT_ASSERT_EQ(map.Size(), clone.Size()); + + THashMap::ConstIterator mapIt = map.Begin(); + THashMap::ConstIterator cloneIt = clone.Begin(); + + while (mapIt != map.End() && cloneIt != clone.End()) { + KT_ASSERT_EQ(mapIt->key, cloneIt->key); + KT_ASSERT_EQ(mapIt->value, cloneIt->value); + + // Make sure they don't point to the same memory + KT_ASSERT_NE(&*mapIt, &*cloneIt); + + ++mapIt; + ++cloneIt; + } + + KT_ASSERT_EQ(mapIt, map.End()); + KT_ASSERT_EQ(cloneIt, clone.End()); + + // One last duplication check by clearing the original + map.Clear(); + KT_ASSERT_EQ(map.Size(), 0); + KT_ASSERT_NE(clone.Size(), 0); +} + +/** + * @brief Tests that the Clear method results in an empty hashmap with no + * elements and zero size + */ +KT_TEST(THashMap, Clear) { + THashMap map; + + for (int i = 0; i < 10; i++) { + map[i] = i % 2 == 0; + } + map.Clear(); + + KT_ASSERT(map.Empty()); + KT_ASSERT_EQ(map.Begin(), map.End()); +} + +/** + * @brief Tests that the Size method accurately reports the number of elements + */ +KT_TEST(THashMap, Size) { + THashMap map; + + for (int i = 0; i < 10; i++) { + map[i] = i % 2 == 0; + } + + KT_ASSERT_EQ(map.Size(), 10); +} + +/** + * @brief Tests that the Capacity method accurately reports the maximum number + * of elements + */ +KT_TEST(THashMap, Capacity) { + THashMap map; + + for (int i = 0; i < 10; i++) { + map[i] = i % 2 == 0; + } + + KT_ASSERT_GE(map.Capacity(), map.Size()); +} + +/** + * @brief Tests that the Empty method accurately reports whether there are no + * elements + */ +KT_TEST(THashMap, Empty) { + THashMap map; + + KT_ASSERT(map.Empty()); + map.Insert(0, true); + KT_ASSERT(!map.Empty()); +} + +/** + * @brief Tests that the Insert method can create new elements + */ +KT_TEST(THashMap, InsertCreate) { + THashMap map; + + KT_ASSERT(!map.Contains(0)); + + map.Insert(0, true); + KT_ASSERT(map.Contains(0)); + KT_ASSERT_EQ(map[0], true); +} + +/** + * @brief Tests that the Insert method can update existing elements + */ +KT_TEST(THashMap, InsertUpdate) { + THashMap map; + + KT_ASSERT(!map.Contains(0)); + + // Create new element + map.Insert(0, true); + KT_ASSERT(map.Contains(0)); + KT_ASSERT_EQ(map[0], true); + + map.Insert(0, false); + KT_ASSERT_EQ(map[0], false); +} + +/** + * @brief Tests that the Remove method fails when the element does not exist + */ +KT_TEST(THashMap, RemoveFail) { + THashMap map; + + u32 oldSize = map.Size(); + + bool success = map.Remove(0); + KT_ASSERT(!success); + + KT_ASSERT_EQ(map.Size(), oldSize); +} + +/** + * @brief Tests that the Remove method can remove existing elements + */ +KT_TEST(THashMap, RemoveSuccess) { + THashMap map; + + map.Insert(0, true); + KT_ASSERT(map.Contains(0)); + + u32 oldSize = map.Size(); + + bool oldValue = false; + bool success = map.Remove(0, &oldValue); + KT_ASSERT(success); + KT_ASSERT_EQ(oldValue, true); + + KT_ASSERT(!map.Contains(0)); + + KT_ASSERT_EQ(map.Size(), oldSize - 1); +} + +namespace { + +bool RemoveIfTrue(const THashItem& rItem) { + return rItem.value == true; +} + +} // namespace + +/** + * @brief Tests that the RemoveIf method correctly removes selected elements + */ +KT_TEST(THashMap, RemoveIf) { + THashMap map; + + for (int i = 0; i < 10; i++) { + map[i] = i % 2 == 0; + } + + u32 oldSize = map.Size(); + + u32 removeNum = map.RemoveIf(RemoveIfTrue); + KT_ASSERT_EQ(removeNum, 10 / 2); + + K_FOREACH (it, map) { + KT_ASSERT(it->value == false); + } + + KT_ASSERT_EQ(map.Size(), oldSize - removeNum); +} + +/** + * @brief Tests that the Erase method erases the correct element + */ +KT_TEST(THashMap, Erase) { + THashMap map; + + for (int i = 0; i < 10; i++) { + map[i] = i % 2 == 0; + } + + u32 oldSize = map.Size(); + + THashMap::Iterator it = map.Begin(); + + // Iterator that should follow the erased one + THashMap::Iterator expected = it; + ++expected; + + THashMap::Iterator got = map.Erase(it); + KT_ASSERT_EQ(expected, got); + + KT_ASSERT_EQ(map.Size(), oldSize - 1); +} + +/** + * @brief Tests that the operator[] method can lookup existing elements + */ +KT_TEST(THashMap, OperatorGet) { + THashMap map; + + map.Insert(0, true); + KT_ASSERT_EQ(map[0], true); +} + +/** + * @brief Tests that the operator[] method can create new elements + */ +KT_TEST(THashMap, OperatorCreate) { + THashMap map; + + map[0] = true; + KT_ASSERT_EQ(map[0], true); +} + +/** + * @brief Tests that the operator[] method can update existing elements + */ +KT_TEST(THashMap, OperatorUpdate) { + THashMap map; + + map.Insert(0, true); + + map[0] = false; + KT_ASSERT_EQ(map[0], false); +} + +/** + * @brief Tests that the Find method returns NULL when no element is found + */ +KT_TEST(THashMap, FindFail) { + THashMap map; + + bool* pElement = map.Find(0); + KT_ASSERT_EQ(pElement, nullptr); +} + +/** + * @brief Tests that the Find method can find existing elements by key + */ +KT_TEST(THashMap, FindSuccess) { + THashMap map; + + map[0] = true; + + bool* pElement = map.Find(0); + KT_ASSERT_NE(pElement, nullptr); + KT_ASSERT_EQ(*pElement, true); +} + +/** + * @brief Tests that the Get method returns the default value when no element is + * found + */ +KT_TEST(THashMap, GetFail) { + THashMap map; + KT_ASSERT_EQ(map.Get(0, true), true); +} + +/** + * @brief Tests that the Get method can find existing elements by key + */ +KT_TEST(THashMap, GetSuccess) { + THashMap map; + + map[0] = true; + KT_ASSERT_EQ(map.Get(0, false), true); +} + +/** + * @brief Tests that the Contains method accurately reports whether an element + * exists + */ +KT_TEST(THashMap, Contains) { + THashMap map; + + KT_ASSERT_EQ(map.Contains(0), false); + + map[0] = true; + KT_ASSERT_EQ(map.Contains(0), true); +} + +/** + * @brief Tests that the Keys method correctly includes all keys in the map + */ +KT_TEST(THashMap, Keys) { + THashMap map; + + static const int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + bool found[LENGTHOF(expected)] = {}; + + for (u32 i = 0; i < LENGTHOF(expected); i++) { + map[expected[i]] = expected[i] % 2 == 0; + } + + TVector keys = map.Keys(); + + // Track keys from the original array that were discovered + K_FOREACH (it, keys) { + found[*it] = true; + } + + for (u32 i = 0; i < LENGTHOF(found); i++) { + KT_ASSERT_EQ(found[i], true); + } +} + +/** + * @brief Tests that the Values method correctly includes all values in the map + */ +KT_TEST(THashMap, Values) { + THashMap map; + + static const int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int numTrue = 0; + int numFalse = 0; + + for (u32 i = 0; i < LENGTHOF(expected); i++) { + map[expected[i]] = expected[i] % 2 == 0; + } + + TVector values = map.Values(); + + // Track values from the original array that were discovered + K_FOREACH (it, values) { + if (*it) { + numTrue++; + } else { + numFalse++; + } + } + + KT_ASSERT_EQ(numTrue, LENGTHOF(expected) / 2); + KT_ASSERT_EQ(numFalse, LENGTHOF(expected) / 2); +} + +/** + * @brief Tests that iteration accesses all elements in the map + */ +KT_TEST(THashMap, Iterator) { + THashMap map; + + static const int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + bool found[LENGTHOF(expected)] = {}; + + for (u32 i = 0; i < LENGTHOF(expected); i++) { + map[expected[i]] = expected[i] % 2 == 0; + } + + // Track keys from the original array that were discovered + K_FOREACH (it, map) { + found[it->key] = true; + KT_ASSERT_EQ(it->value, it->key % 2 == 0); + } + + for (u32 i = 0; i < LENGTHOF(found); i++) { + KT_ASSERT_EQ(found[i], true); + } +} + +} // namespace HashMapTests +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/test/unit/test_kiwiList.cpp b/lib/libkiwi/test/unit/test_kiwiList.cpp new file mode 100644 index 0000000..dd22589 --- /dev/null +++ b/lib/libkiwi/test/unit/test_kiwiList.cpp @@ -0,0 +1,384 @@ +#include + +namespace kiwi { +namespace ListTests { + +/** + * @brief Tests that a list after construction is empty (no elements and zero + * size) + */ +KT_TEST(TList, Constructor) { + TList list; + + KT_ASSERT(list.Empty()); + KT_ASSERT_EQ(list.Begin(), list.End()); +} + +/** + * @brief Tests that the copy constructor correctly duplicates elements + */ +KT_TEST(TList, CopyConstructor) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + + TList clone(list); + KT_ASSERT_EQ(list.Size(), clone.Size()); + + TList::ConstIterator listIt = list.Begin(); + TList::ConstIterator cloneIt = clone.Begin(); + + while (listIt != list.End() && cloneIt != clone.End()) { + KT_ASSERT_EQ(*listIt, *cloneIt); + + // Make sure they don't point to the same memory + KT_ASSERT_NE(&*listIt, &*cloneIt); + + ++listIt; + ++cloneIt; + } + + KT_ASSERT_EQ(listIt, list.End()); + KT_ASSERT_EQ(cloneIt, clone.End()); + + // One last duplication check by clearing the original + list.Clear(); + KT_ASSERT_EQ(list.Size(), 0); + KT_ASSERT_NE(clone.Size(), 0); +} + +/** + * @brief Tests that the Clear method results in an empty list with no elements + * and zero size + */ +KT_TEST(TList, Clear) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + list.Clear(); + + KT_ASSERT(list.Empty()); + KT_ASSERT_EQ(list.Begin(), list.End()); +} + +/** + * @brief Tests that Begin provides an iterator to the first element + */ +KT_TEST(TList, Begin) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + + KT_ASSERT_NE(list.Begin(), list.End()); + KT_ASSERT_EQ(*list.Begin(), 0); +} + +/** + * @brief Tests that End provides an iterator past the last element + */ +KT_TEST(TList, End) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + + KT_ASSERT_NE(list.End(), list.Begin()); + KT_ASSERT_EQ(*--list.End(), 9); +} + +/** + * @brief Tests that the Size method accurately reports the number of elements + */ +KT_TEST(TList, Size) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + + KT_ASSERT_EQ(list.Size(), 10); +} + +/** + * @brief Tests that the Empty method accurately reports whether there are no + * elements + */ +KT_TEST(TList, Empty) { + TList list; + + KT_ASSERT(list.Empty()); + list.PushBack(1); + KT_ASSERT(!list.Empty()); +} + +/** + * @brief Tests that the PopFront method erases and returns the first element + */ +KT_TEST(TList, PopFront) { + TList list; + + list.PushBack(1); + list.PushBack(2); + list.PushBack(3); + + int front = list.PopFront(); + KT_ASSERT_EQ(front, 1); + KT_ASSERT_EQ(list.Front(), 2); +} + +/** + * @brief Tests that the PopBack method erases and returns the last element + */ +KT_TEST(TList, PopBack) { + TList list; + + list.PushBack(1); + list.PushBack(2); + list.PushBack(3); + + int front = list.PopBack(); + KT_ASSERT_EQ(front, 3); + KT_ASSERT_EQ(list.Back(), 2); +} + +/** + * @brief Tests that the PushFront method prepends to the list + */ +KT_TEST(TList, PushFront) { + TList list; + + list.PushBack(1); + list.PushBack(2); + list.PushBack(3); + + list.PushFront(0); + KT_ASSERT_EQ(list.Front(), 0); +} + +/** + * @brief Tests that the PushBack method appends to the list + */ +KT_TEST(TList, PushBack) { + TList list; + + list.PushBack(1); + list.PushBack(2); + list.PushBack(3); + + list.PushBack(4); + KT_ASSERT_EQ(list.Back(), 4); +} + +/** + * @brief Tests that the Front method accesses the first element + */ +KT_TEST(TList, Front) { + TList list; + + list.PushBack(1); + list.PushBack(2); + list.PushBack(3); + + KT_ASSERT_EQ(list.Front(), 1); +} + +/** + * @brief Tests that the Back method accesses the last element + */ +KT_TEST(TList, Back) { + TList list; + + list.PushBack(1); + list.PushBack(2); + list.PushBack(3); + + KT_ASSERT_EQ(list.Back(), 3); +} + +/** + * @brief Tests that the Remove method correctly removes the first occurrence + */ +KT_TEST(TList, Remove) { + TList list; + + list.PushBack(2); + list.PushBack(3); + list.PushBack(2); + + KT_ASSERT(list.Remove(2)); + KT_ASSERT_EQ(list.Front(), 3) + KT_ASSERT_EQ(list.Back(), 2) + + KT_ASSERT(list.Remove(2)); + KT_ASSERT_EQ(list.Front(), 3) + KT_ASSERT_EQ(list.Back(), 3) +} + +namespace { + +bool RemoveIfOdd(const int& x) { + return x % 2 != 0; +} + +} // namespace + +/** + * @brief Tests that the RemoveIf method correctly removes selected elements + */ +KT_TEST(TList, RemoveIf) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + + u32 removeNum = list.RemoveIf(RemoveIfOdd); + KT_ASSERT_EQ(removeNum, 10 / 2); + + K_FOREACH (it, list) { + KT_ASSERT(*it % 2 == 0); + } +} + +/** + * @brief Tests that the Insert method correctly positions the new element + */ +KT_TEST(TList, Insert) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + + K_FOREACH (it, list) { + // Insert another 4 before the 5 + if (*it == 5) { + TList::Iterator result = list.Insert(it, 4); + KT_ASSERT_EQ(*result, 4); + + // Ensure they are sequential + KT_ASSERT_EQ(++result, it); + break; + } + } +} + +/** + * @brief Tests that the Erase method erases the correct element + */ +KT_TEST(TList, Erase) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + + K_FOREACH (it, list) { + if (*it == 5) { + TList::Iterator next = it; + ++next; + + TList::Iterator result = list.Erase(it); + KT_ASSERT_EQ(result, next); + break; + } + } +} + +/** + * @brief Tests that the Erase method erases the correct range of elements + */ +KT_TEST(TList, EraseRange) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + + K_FOREACH (it, list) { + // Erase elements from 5 onwards + if (*it >= 5) { + list.Erase(it, list.End()); + break; + } + } + + K_FOREACH (it, list) { + KT_ASSERT_LT(*it, 5); + } +} + +/** + * @brief Tests that forward iteration produces the expected results + */ +KT_TEST(TList, ForwardIterator) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + + TList::Iterator it = list.Begin(); + int i = 0; + + while (i < 10) { + KT_ASSERT_NE(it, list.End()); + KT_ASSERT_EQ(*it, i); + + i++; + ++it; + } +} + +/** + * @brief Tests that reverse iteration produces the expected results + */ +KT_TEST(TList, ReverseIterator) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + } + + TList::RevIterator it = list.RBegin(); + int i = 0; + + while (i < 10) { + KT_ASSERT_NE(it, list.REnd()); + KT_ASSERT_EQ(*it, (10 - 1 - i)); + + i++; + ++it; + } +} + +/** + * @brief Tests that the Sort method correctly sorts all elements + */ +KT_TEST(TList, Sort) { + TList list; + + for (int i = 0; i < 10; i++) { + list.PushBack(i); + list.PushBack(i - 1); + } + + list.Sort(); + + int prev = -999; + + K_FOREACH (it, list) { + KT_ASSERT_LE(prev, *it); + prev = *it; + } +} + +} // namespace ListTests +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/test/unit/test_kiwiVector.cpp b/lib/libkiwi/test/unit/test_kiwiVector.cpp new file mode 100644 index 0000000..41b0bc6 --- /dev/null +++ b/lib/libkiwi/test/unit/test_kiwiVector.cpp @@ -0,0 +1,352 @@ +#include + +namespace kiwi { +namespace VectorTests { + +/** + * @brief Tests that a vector after construction is empty (no elements and zero + * size) + */ +KT_TEST(TVector, Constructor) { + TVector vector; + + KT_ASSERT(vector.Empty()); + KT_ASSERT_EQ(vector.Begin(), vector.End()); +} + +/** + * @brief Tests that the copy constructor correctly duplicates elements + */ +KT_TEST(TVector, CopyConstructor) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + + TVector clone(vector); + KT_ASSERT_EQ(vector.Size(), clone.Size()); + + TVector::ConstIterator vectorIt = vector.Begin(); + TVector::ConstIterator cloneIt = clone.Begin(); + + while (vectorIt != vector.End() && cloneIt != clone.End()) { + KT_ASSERT_EQ(*vectorIt, *cloneIt); + + // Make sure they don't point to the same memory + KT_ASSERT_NE(&*vectorIt, &*cloneIt); + + ++vectorIt; + ++cloneIt; + } + + KT_ASSERT_EQ(vectorIt, vector.End()); + KT_ASSERT_EQ(cloneIt, clone.End()); + + // One last duplication check by clearing the original + vector.Clear(); + KT_ASSERT_EQ(vector.Size(), 0); + KT_ASSERT_NE(clone.Size(), 0); +} + +/** + * @brief Tests that the Clear method results in an empty vector with no + * elements and zero size + */ +KT_TEST(TVector, Clear) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + vector.Clear(); + + KT_ASSERT(vector.Empty()); + KT_ASSERT_EQ(vector.Begin(), vector.End()); +} + +/** + * @brief Tests that Begin provides an iterator to the first element + */ +KT_TEST(TVector, Begin) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + + KT_ASSERT_NE(vector.Begin(), vector.End()); + KT_ASSERT_EQ(*vector.Begin(), 0); +} + +/** + * @brief Tests that End provides an iterator past the last element + */ +KT_TEST(TVector, End) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + + KT_ASSERT_NE(vector.End(), vector.Begin()); + KT_ASSERT_EQ(*--vector.End(), vector.Size() - 1); +} + +/** + * @brief Tests that the Size method accurately reports the number of elements + */ +KT_TEST(TVector, Size) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + + KT_ASSERT_EQ(vector.Size(), 10); +} + +/** + * @brief Tests that the Empty method accurately reports whether there are no + * elements + */ +KT_TEST(TVector, Empty) { + TVector vector; + + KT_ASSERT(vector.Empty()); + vector.PushBack(1); + KT_ASSERT(!vector.Empty()); +} + +/** + * @brief Tests that the PopBack method erases and returns the last element + */ +KT_TEST(TVector, PopBack) { + TVector vector; + + vector.PushBack(1); + vector.PushBack(2); + vector.PushBack(3); + + int front = vector.PopBack(); + KT_ASSERT_EQ(front, 3); + KT_ASSERT_EQ(vector.Back(), 2); +} + +/** + * @brief Tests that the PushBack method appends to the vector + */ +KT_TEST(TVector, PushBack) { + TVector vector; + + vector.PushBack(1); + vector.PushBack(2); + vector.PushBack(3); + + vector.PushBack(4); + KT_ASSERT_EQ(vector.Back(), 4); +} + +/** + * @brief Tests that the Front method accesses the first element + */ +KT_TEST(TVector, Front) { + TVector vector; + + vector.PushBack(1); + vector.PushBack(2); + vector.PushBack(3); + + KT_ASSERT_EQ(vector.Front(), 1); +} + +/** + * @brief Tests that the Back method accesses the last element + */ +KT_TEST(TVector, Back) { + TVector vector; + + vector.PushBack(1); + vector.PushBack(2); + vector.PushBack(3); + + KT_ASSERT_EQ(vector.Back(), 3); +} + +/** + * @brief Tests that the Remove method correctly removes the first occurrence + */ +KT_TEST(TVector, Remove) { + TVector vector; + + vector.PushBack(2); + vector.PushBack(3); + vector.PushBack(2); + + KT_ASSERT(vector.Remove(2)); + KT_ASSERT_EQ(vector.Front(), 3) + KT_ASSERT_EQ(vector.Back(), 2) + + KT_ASSERT(vector.Remove(2)); + KT_ASSERT_EQ(vector.Front(), 3) + KT_ASSERT_EQ(vector.Back(), 3) +} + +namespace { + +bool RemoveIfOdd(const int& x) { + return x % 2 != 0; +} + +} // namespace + +/** + * @brief Tests that the RemoveIf method correctly removes selected elements + */ +KT_TEST(TVector, RemoveIf) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + + u32 removeNum = vector.RemoveIf(RemoveIfOdd); + KT_ASSERT_EQ(removeNum, 10 / 2); + + K_FOREACH (it, vector) { + KT_ASSERT(*it % 2 == 0); + } +} + +/** + * @brief Tests that the Insert method correctly positions the new element + */ +KT_TEST(TVector, Insert) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + + K_FOREACH (it, vector) { + // Insert another 4 before the 5 + if (*it == 5) { + TVector::Iterator result = vector.Insert(it, 4); + KT_ASSERT_EQ(*result, 4); + + // Ensure they are sequential + KT_ASSERT_EQ(*++result, 5); + break; + } + } +} + +/** + * @brief Tests that the Erase method erases the correct element + */ +KT_TEST(TVector, Erase) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + + K_FOREACH (it, vector) { + if (*it == 5) { + TVector::Iterator result = vector.Erase(it); + KT_ASSERT_EQ(*result, 6); + break; + } + } +} + +/** + * @brief Tests that the Erase method erases the correct range of elements + */ +KT_TEST(TVector, EraseRange) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + + K_FOREACH (it, vector) { + // Erase elements from 5 onwards + if (*it >= 5) { + vector.Erase(it, vector.End()); + break; + } + } + + K_FOREACH (it, vector) { + KT_ASSERT_LT(*it, 5); + } +} + +/** + * @brief Tests that forward iteration produces the expected results + */ +KT_TEST(TVector, ForwardIterator) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + + TVector::Iterator it = vector.Begin(); + int i = 0; + + while (i < 10) { + KT_ASSERT_NE(it, vector.End()); + KT_ASSERT_EQ(*it, i); + + i++; + ++it; + } +} + +/** + * @brief Tests that reverse iteration produces the expected results + */ +KT_TEST(TVector, ReverseIterator) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + } + + TVector::RevIterator it = vector.RBegin(); + int i = 0; + + while (i < 10) { + KT_ASSERT_NE(it, vector.REnd()); + KT_ASSERT_EQ(*it, (10 - 1 - i)); + + i++; + ++it; + } +} + +/** + * @brief Tests that the Sort method correctly sorts all elements + */ +KT_TEST(TVector, Sort) { + TVector vector; + + for (int i = 0; i < 10; i++) { + vector.PushBack(i); + vector.PushBack(i - 1); + } + + vector.Sort(); + + int prev = -999; + + K_FOREACH (it, vector) { + KT_ASSERT_LE(prev, *it); + prev = *it; + } +} + +} // namespace VectorTests +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/util/kiwiAutoLock.h b/lib/libkiwi/util/kiwiAutoLock.h deleted file mode 100644 index bbbf1b8..0000000 --- a/lib/libkiwi/util/kiwiAutoLock.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef LIBKIWI_UTIL_AUTOLOCK_H -#define LIBKIWI_UTIL_AUTOLOCK_H -#include -#include - -namespace kiwi { -//! @addtogroup libkiwi_util -//! @{ - -/** - * @brief Generic scoped lock - */ -template class AutoLock : private NonCopyable { -public: - AutoLock(T& object) : mObject(object) { - Lock(); - } - ~AutoLock() { - Unlock(); - } - - // Implement these for custom types - void Lock(); - void Unlock(); - -private: - T& mObject; // Locked object -}; - -/** - * @brief OSMutex specializations - */ -template <> K_INLINE void AutoLock::Lock() { - if (OSGetCurrentThread() != nullptr) { - OSLockMutex(&mObject); - } -} -template <> K_INLINE void AutoLock::Unlock() { - if (OSGetCurrentThread() != nullptr) { - OSUnlockMutex(&mObject); - } -} - -typedef AutoLock AutoMutexLock; - -/** - * @brief OS interrupt scoped lock - */ -class AutoInterruptLock : private NonCopyable { -public: - AutoInterruptLock(bool enable = false) - : mEnabled(enable ? OSEnableInterrupts() : OSDisableInterrupts()) {} - ~AutoInterruptLock() { - OSRestoreInterrupts(mEnabled); - } - -private: - BOOL mEnabled; // Interrupt status -}; - -//! @} -} // namespace kiwi - -#endif diff --git a/lib/libkiwi/util/kiwiChecksum.h b/lib/libkiwi/util/kiwiChecksum.h index 1d88c67..2f01485 100644 --- a/lib/libkiwi/util/kiwiChecksum.h +++ b/lib/libkiwi/util/kiwiChecksum.h @@ -24,7 +24,7 @@ class Checksum { * @param size Size of data */ void Process(const void* data, u32 size) { - K_ASSERT(data != nullptr); + K_ASSERT_PTR(data); const u8* p = static_cast(data); diff --git a/lib/libkiwi/util/kiwiDynamicSingleton.h b/lib/libkiwi/util/kiwiDynamicSingleton.h index 9f82b50..bd48e3e 100644 --- a/lib/libkiwi/util/kiwiDynamicSingleton.h +++ b/lib/libkiwi/util/kiwiDynamicSingleton.h @@ -1,13 +1,14 @@ #ifndef LIBKIWI_UTIL_DYNAMIC_SINGLETON_H #define LIBKIWI_UTIL_DYNAMIC_SINGLETON_H #include -#include +#include #include + #include #define K_DYNAMIC_SINGLETON_IMPL(T) \ T* kiwi::DynamicSingleton::sInstance = nullptr; \ - OSMutex kiwi::DynamicSingleton::sMutex; + kiwi::Mutex kiwi::DynamicSingleton::sMutex; namespace kiwi { //! @addtogroup libkiwi_util @@ -19,36 +20,49 @@ namespace kiwi { template class DynamicSingleton : private NonCopyable { public: /** - * @brief Gets reference to singleton object + * @brief Gets a reference to the singleton object */ static T& GetInstance() { - AutoLock lock(sMutex); - K_ASSERT(sInstance != nullptr); + AutoMutexLock lock(sMutex); + K_ASSERT_PTR(sInstance); return *sInstance; } /** - * @brief Initializes singleton object + * @brief Initializes the singleton object */ - static void CreateInstance() { - AutoLock lock(sMutex); + static T* CreateInstance() { + AutoMutexLock lock(sMutex); K_ASSERT_EX(sInstance == nullptr, "Created singleton twice"); + if (sInstance == nullptr) { sInstance = new T(); + K_ASSERT_PTR(sInstance); } + + return sInstance; } /** - * @brief Destroys singleton object + * @brief Destroys the singleton object */ static void DestroyInstance() { - AutoLock lock(sMutex); + AutoMutexLock lock(sMutex); delete sInstance; + sInstance = nullptr; + } + + /** + * @brief Tests whether the instance has been created + */ + static bool IsCreateInstance() { + AutoMutexLock lock(sMutex); + return sInstance != nullptr; } private: - static T* sInstance; // Static instance - static OSMutex sMutex; // Mutex lock for safe access + static T* sInstance; //! Static instance + static Mutex sMutex; //! Mutex lock for safe access }; //! @} diff --git a/lib/libkiwi/util/kiwiExtension.h b/lib/libkiwi/util/kiwiExtension.h index 088287b..e4ecfce 100644 --- a/lib/libkiwi/util/kiwiExtension.h +++ b/lib/libkiwi/util/kiwiExtension.h @@ -24,8 +24,8 @@ class ExtSingletonPtr : public TBase, private NonConstructable { * @brief Accesses singleton instance (by pointer) */ static TDerived& GetInstance() { - K_ASSERT(TBase::getInstance() != nullptr); - return static_cast(*TBase::getInstance()); + K_ASSERT_PTR(TBase::instance()); + return static_cast(*TBase::instance()); } }; @@ -39,11 +39,51 @@ class ExtSingletonRef : public TBase, private NonConstructable { * @brief Accesses singleton instance (by reference) */ static TDerived& GetInstance() { - return static_cast(TBase::getInstance()); + return static_cast(TBase::instance()); } }; //! @} } // namespace kiwi +/** + * @brief Declares function(s) necessary to override singleton + * creation/destruction. + */ +#define K_SINGLETON_REPLACE_DECL(TBASE, TDERIVED) \ +public: \ + static TBASE* Ex_CreateInstance(); \ + static void Ex_DestroyInstance(); \ + \ +private: \ + ; + +/** + * @brief Defines function(s) necessary to override singleton creation. + * @note The new/derived type must inherit from StaticSingleton. + */ +#define K_SINGLETON_REPLACE_IMPL_STATIC(TBASE, TDERIVED) \ + TBASE* TDERIVED::Ex_CreateInstance() { \ + return TBASE::spInstance = \ + &kiwi::StaticSingleton::GetInstance(); \ + } \ + KM_BRANCH(TBASE::CreateInstance, TDERIVED::Ex_CreateInstance); + +/** + * @brief Defines function(s) necessary to override singleton creation. + * @note The new/derived type must inherit from DynamicSingleton. + */ +#define K_SINGLETON_REPLACE_IMPL_DYNAMIC(TBASE, TDERIVED) \ + TBASE* TDERIVED::Ex_CreateInstance() { \ + return TBASE::spInstance = \ + kiwi::DynamicSingleton::CreateInstance(); \ + } \ + KM_BRANCH(TBASE::CreateInstance, TDERIVED::Ex_CreateInstance); \ + \ + void TDERIVED::Ex_DestroyInstance() { \ + kiwi::DynamicSingleton::DestroyInstance(); \ + TBASE::spInstance = nullptr; \ + } \ + KM_BRANCH(TBASE::DestroyInstance, TDERIVED::Ex_DestroyInstance); + #endif diff --git a/lib/libkiwi/util/kiwiGlobalInstance.h b/lib/libkiwi/util/kiwiGlobalInstance.h index 2a135f2..f67887b 100644 --- a/lib/libkiwi/util/kiwiGlobalInstance.h +++ b/lib/libkiwi/util/kiwiGlobalInstance.h @@ -1,12 +1,13 @@ #ifndef LIBKIWI_UTIL_GLOBAL_INSTANCE_H #define LIBKIWI_UTIL_GLOBAL_INSTANCE_H #include -#include +#include + #include #define K_GLOBAL_INSTANCE_IMPL(T) \ T* kiwi::GlobalInstance::sInstance = nullptr; \ - OSMutex kiwi::GlobalInstance::sMutex; + Mutex kiwi::GlobalInstance::sMutex; namespace kiwi { //! @addtogroup libkiwi_util @@ -23,7 +24,7 @@ template class GlobalInstance { * @param force Overwrite the current instance */ GlobalInstance(bool force = false) { - AutoLock lock(sMutex); + AutoMutexLock lock(sMutex); // Without 'force' we cannot re-register if (sInstance != nullptr && !force) { @@ -39,7 +40,7 @@ template class GlobalInstance { * @brief Destructor */ ~GlobalInstance() { - AutoLock lock(sMutex); + AutoMutexLock lock(sMutex); // Only unregister if this object is the global instance if (sInstance == (T*)this) { @@ -51,8 +52,8 @@ template class GlobalInstance { * @brief Gets reference to global instance */ static T& Get() { - AutoLock lock(sMutex); - K_ASSERT(sInstance != nullptr); + AutoMutexLock lock(sMutex); + K_ASSERT_PTR(sInstance); return *sInstance; } @@ -62,7 +63,7 @@ template class GlobalInstance { * @param instance New instance */ static void Set(T& instance) { - AutoLock lock(sMutex); + AutoMutexLock lock(sMutex); sInstance = &instance; } @@ -70,13 +71,13 @@ template class GlobalInstance { * @brief Tests whether a global instance is registered */ static bool Exists() { - AutoLock lock(sMutex); + AutoMutexLock lock(sMutex); return sInstance != nullptr; } private: - static T* sInstance; // Global instance - static OSMutex sMutex; // Mutex lock for safe access + static T* sInstance; // Global instance + static Mutex sMutex; // Mutex lock for safe access }; //! @} diff --git a/lib/libkiwi/util/kiwiIosDevice.cpp b/lib/libkiwi/util/kiwiIosDevice.cpp index 856953b..90f5ce4 100644 --- a/lib/libkiwi/util/kiwiIosDevice.cpp +++ b/lib/libkiwi/util/kiwiIosDevice.cpp @@ -85,7 +85,7 @@ s32 IosDevice::IoctlV(s32 id, const TVector& in, // Vectors need to be contiguous and usually(?) in MEM2 IPCIOVector* vectors = new (32, EMemory_MEM2) IPCIOVector[in.Size() + out.Size()]; - K_ASSERT(vectors != nullptr); + K_ASSERT_PTR(vectors); // Copy in user vectors int i = 0; diff --git a/lib/libkiwi/util/kiwiIosObject.h b/lib/libkiwi/util/kiwiIosObject.h index 12a2be2..426e825 100644 --- a/lib/libkiwi/util/kiwiIosObject.h +++ b/lib/libkiwi/util/kiwiIosObject.h @@ -26,7 +26,7 @@ template class IosBuffer : public IosVector { K_ASSERT(size > 0); u8* buffer = new (32, EMemory_MEM2) u8[size * sizeof(T)]; - K_ASSERT(buffer != nullptr); + K_ASSERT_PTR(buffer); Set(buffer, size); } @@ -100,7 +100,7 @@ template class IosObject : public IosBuffer { * @brief Access underlying object (pointer) */ T* Ptr() const { - K_ASSERT(Base() != nullptr); + K_ASSERT_PTR(Base()); return reinterpret_cast(Base()); } diff --git a/lib/libkiwi/util/kiwiModelUtil.cpp b/lib/libkiwi/util/kiwiModelUtil.cpp new file mode 100644 index 0000000..f6c1010 --- /dev/null +++ b/lib/libkiwi/util/kiwiModelUtil.cpp @@ -0,0 +1,36 @@ +#include + +#include + +#include + +namespace kiwi { + +/** + * @brief Gets a model's material by name + * + * @param pModel Model + * @param rName G3D material name + * @return RP engine material, or nullptr if not found + */ +RPGrpModelMaterial* ModelUtil::GetModelMaterial(RPGrpModel* pModel, + const String& rName) { + + ASSERT_PTR(pModel); + + EGG::ModelEx* pModelEx = pModel->GetModelEx(); + ASSERT_PTR(pModelEx); + + nw4r::g3d::ScnMdlSimple* pScnMdlSimple = pModelEx->getScnMdlSimple(); + ASSERT_PTR_EX(pScnMdlSimple, "This model is not a ScnMdl"); + + nw4r::g3d::ResMdl resMdl = pScnMdlSimple->GetResMdl(); + ASSERT(resMdl.IsValid()); + + nw4r::g3d::ResMat resMat = resMdl.GetResMat(rName); + ASSERT_EX(resMat.IsValid(), "Cannot find material: %s", rName.CStr()); + + return pModel->GetMaterial(resMat.GetID()); +} + +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/util/kiwiModelUtil.h b/lib/libkiwi/util/kiwiModelUtil.h new file mode 100644 index 0000000..d3acc3c --- /dev/null +++ b/lib/libkiwi/util/kiwiModelUtil.h @@ -0,0 +1,30 @@ +#ifndef LIBKIWI_UTIL_MODEL_UTIL_H +#define LIBKIWI_UTIL_MODEL_UTIL_H +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_util +//! @{ + +/** + * @brief Model utilities + */ +class ModelUtil { +public: + /** + * @brief Gets a model's material by name + * + * @param pModel Model + * @param rName G3D material name + * @return RP engine material, or nullptr if not found + */ + static RPGrpModelMaterial* GetModelMaterial(RPGrpModel* pModel, + const String& rName); +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/util/kiwiNonConstructable.h b/lib/libkiwi/util/kiwiNonConstructable.h index 1bcffa8..c6b429d 100644 --- a/lib/libkiwi/util/kiwiNonConstructable.h +++ b/lib/libkiwi/util/kiwiNonConstructable.h @@ -13,16 +13,16 @@ namespace kiwi { class NonConstructable { private: NonConstructable() { - K_ASSERT(false); + K_UNREACHABLE(); } ~NonConstructable() { - K_ASSERT(false); + K_UNREACHABLE(); } NonConstructable(const NonConstructable& /* rOther */) { - K_ASSERT(false); + K_UNREACHABLE(); } NonConstructable& operator=(const NonConstructable& /* rOther */) { - K_ASSERT(false); + K_UNREACHABLE(); return *this; } }; diff --git a/lib/libkiwi/util/kiwiNonCopyable.h b/lib/libkiwi/util/kiwiNonCopyable.h index e074281..9d50d63 100644 --- a/lib/libkiwi/util/kiwiNonCopyable.h +++ b/lib/libkiwi/util/kiwiNonCopyable.h @@ -17,10 +17,10 @@ class NonCopyable { private: NonCopyable(const NonCopyable& /* rOther */) { - K_ASSERT(false); + K_UNREACHABLE(); } NonCopyable& operator=(const NonCopyable& /* rOther */) { - K_ASSERT(false); + K_UNREACHABLE(); return *this; } }; diff --git a/lib/libkiwi/util/kiwiProductInfo.cpp b/lib/libkiwi/util/kiwiProductInfo.cpp index 4c78097..89e6f77 100644 --- a/lib/libkiwi/util/kiwiProductInfo.cpp +++ b/lib/libkiwi/util/kiwiProductInfo.cpp @@ -24,11 +24,22 @@ const char* GetBuildPack() { * @brief Gets the target for which the module was built */ const char* GetBuildTarget() { -#ifdef NDEBUG +#if defined(NDEBUG) return "Release"; #else return "Debug"; #endif } +/** + * @brief Gets the hash (shortened) of the latest Git commit + */ +const char* GetGitCommitHash() { +#if defined(GIT_COMMIT_HASH) + return K_STRINGITIZE(GIT_COMMIT_HASH); +#else + return ""; +#endif +} + } // namespace kiwi diff --git a/lib/libkiwi/util/kiwiProductInfo.h b/lib/libkiwi/util/kiwiProductInfo.h index aa637e4..65a3374 100644 --- a/lib/libkiwi/util/kiwiProductInfo.h +++ b/lib/libkiwi/util/kiwiProductInfo.h @@ -10,6 +10,7 @@ namespace kiwi { const char* GetBuildDate(); const char* GetBuildPack(); const char* GetBuildTarget(); +const char* GetGitCommitHash(); //! @} } // namespace kiwi diff --git a/lib/libkiwi/util/kiwiRandom.h b/lib/libkiwi/util/kiwiRandom.h index f0f09a5..b416e93 100644 --- a/lib/libkiwi/util/kiwiRandom.h +++ b/lib/libkiwi/util/kiwiRandom.h @@ -164,24 +164,6 @@ class Random { */ extern Random RNG; -/** - * @brief Performs the Fisher-Yates shuffle algorithm to generate a random - * permutation - * - * @tparam T Element type - * @param pArray Input array - * @param size Array size - */ -template K_INLINE void Shuffle(T pArray, int size) { - K_ASSERT(pArray != nullptr); - - Random r; - for (int i = size - 1; i >= 1; i--) { - int j = r.NextS32(i + 1); - std::swap(pArray[j], pArray[i]); - } -} - //! @} } // namespace kiwi diff --git a/lib/libkiwi/util/kiwiSceneUtil.cpp b/lib/libkiwi/util/kiwiSceneUtil.cpp new file mode 100644 index 0000000..6799f94 --- /dev/null +++ b/lib/libkiwi/util/kiwiSceneUtil.cpp @@ -0,0 +1,36 @@ +#include + +namespace kiwi { + +/** + * @brief Gets the current scene as the EGG type + */ +EGG::Scene* SceneUtil::GetCurrentScene() { + EGG::Scene* pScene = RP_GET_INSTANCE(RPSysSceneMgr)->getCurrentScene(); + K_ASSERT_PTR(pScene); + + return pScene; +} + +/** + * @brief Tests whether a given scene has a user-defined scene ID + * @details Call without arguments to check the current scene + * + * @param pScene Current scene + */ +bool SceneUtil::IsSceneUser(const EGG::Scene* pScene) { + K_ASSERT_PTR(pScene); + + return pScene->getSceneID() >= ESceneID_Max; +} + +/** + * @brief Tests whether the current scene permits NAND access + * + * @return Whether NAND access is permitted + */ +bool SceneUtil::IsNANDAccessEnable() { + return GetCurrentSceneRP()->isNandAccessEnable(); +} + +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/util/kiwiSceneUtil.h b/lib/libkiwi/util/kiwiSceneUtil.h new file mode 100644 index 0000000..32cf5f0 --- /dev/null +++ b/lib/libkiwi/util/kiwiSceneUtil.h @@ -0,0 +1,63 @@ +#ifndef LIBKIWI_UTIL_SCENE_UTIL_H +#define LIBKIWI_UTIL_SCENE_UTIL_H +#include +#include +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_util +//! @{ + +/** + * @brief Scene utilities + */ +class SceneUtil { +public: + /** + * @brief Gets the current scene as the EGG type + */ + static EGG::Scene* GetCurrentScene(); + /** + * @brief Gets the current scene as the RP type + */ + static RPSysScene* GetCurrentSceneRP() { + return static_cast(GetCurrentScene()); + } + /** + * @brief Gets the current scene as the libkiwi type + */ + static IScene* GetCurrentSceneKiwi() { + return static_cast(GetCurrentScene()); + } + + /** + * @brief Tests whether a given scene has a Pack Project scene ID + * @details Call without arguments to check the current scene + * + * @param pScene Current scene + */ + static bool IsScenePack(const EGG::Scene* pScene = nullptr) { + return !IsSceneUser(pScene); + } + /** + * @brief Tests whether a given scene has a user-defined scene ID + * @details Call without arguments to check the current scene + * + * @param pScene Current scene + */ + static bool IsSceneUser(const EGG::Scene* pScene = nullptr); + + /** + * @brief Tests whether the current scene permits NAND access + * + * @return Whether NAND access is permitted + */ + static bool IsNANDAccessEnable(); +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/util/kiwiWorkBuffer.h b/lib/libkiwi/util/kiwiWorkBuffer.h index 251487e..f041ca5 100644 --- a/lib/libkiwi/util/kiwiWorkBuffer.h +++ b/lib/libkiwi/util/kiwiWorkBuffer.h @@ -45,7 +45,7 @@ class WorkBuffer { mBufferAlignSize = RoundUp(mBufferSize, mSizeAlign); mpBuffer = new (mMemAlign, mMemRegion) u8[mBufferAlignSize]; - K_ASSERT(mpBuffer != nullptr); + K_ASSERT_PTR(mpBuffer); } /** diff --git a/loader/kamek/kamekHooks.hpp b/loader/kamek/kamekHooks.hpp index f19e754..07c43e4 100644 --- a/loader/kamek/kamekHooks.hpp +++ b/loader/kamek/kamekHooks.hpp @@ -103,7 +103,7 @@ // Create dummy function to call a member function. #define _KM_INJECT_MF(cls, func) \ UNKWORD CONCAT(KM_TRAMP_##cls##_##func, __LINE__)(void* arg, ...) { \ - typedef UNKWORD (cls::*cls##_fun_t)(...); \ + typedef UNKWORD (cls::* cls##_fun_t)(...); \ const cls##_fun_t mem_fun = (cls##_fun_t)(&cls::func); \ cls* self = reinterpret_cast(arg); \ return (self->*mem_fun)(); \ diff --git a/loader/kokeshi.cpp b/loader/kokeshi.cpp index 2d320c6..897b9f7 100644 --- a/loader/kokeshi.cpp +++ b/loader/kokeshi.cpp @@ -6,8 +6,10 @@ // #include -#include + #include + +#include #include namespace kokeshi { diff --git a/loader/kokeshi.hpp b/loader/kokeshi.hpp index 9dec8e4..3d28d7b 100644 --- a/loader/kokeshi.hpp +++ b/loader/kokeshi.hpp @@ -30,9 +30,9 @@ // clang-format off //! Name of the module-related files #define KOKESHI_MODULE_PATH \ - KOKESHI_BY_PACK("/modules/m_sports", /* Wii Sports */ \ - "/modules/m_play", /* Wii Play */ \ - "/modules/m_resort") /* Wii Sports Resort */ + KOKESHI_BY_PACK("/modules/ModuleSports", /* Wii Sports */ \ + "/modules/ModulePlay", /* Wii Play */ \ + "/modules/ModuleResort") /* Wii Sports Resort */ // clang-format on //! @} diff --git a/src/core/CheckMgr.cpp b/src/core/CheckMgr.cpp index 1f8c850..fd64460 100644 --- a/src/core/CheckMgr.cpp +++ b/src/core/CheckMgr.cpp @@ -244,42 +244,76 @@ const char* CheckMgr::GetCheckName(CheckMgr::CheckID id) const { case SWORDPLAY_DUEL_FIRST_WIN: return "Swordplay Duel - First Win!"; - case GOLF_COMPLTE_HOLE_1: return "Golf - Complete Hole 1!"; - case GOLF_COMPLTE_HOLE_2: return "Golf - Complete Hole 2!"; - case GOLF_COMPLTE_HOLE_3: return "Golf - Complete Hole 3!"; - case GOLF_COMPLTE_HOLE_4: return "Golf - Complete Hole 4!"; - case GOLF_COMPLTE_HOLE_5: return "Golf - Complete Hole 5!"; - case GOLF_COMPLTE_HOLE_6: return "Golf - Complete Hole 6!"; - case GOLF_COMPLTE_HOLE_7: return "Golf - Complete Hole 7!"; - case GOLF_COMPLTE_HOLE_8: return "Golf - Complete Hole 8!"; - case GOLF_COMPLTE_HOLE_9: return "Golf - Complete Hole 9!"; - case GOLF_COMPLTE_HOLE_10: return "Golf - Complete Hole 10!"; - case GOLF_COMPLTE_HOLE_11: return "Golf - Complete Hole 11!"; - case GOLF_COMPLTE_HOLE_12: return "Golf - Complete Hole 12!"; - case GOLF_COMPLTE_HOLE_13: return "Golf - Complete Hole 13!"; - case GOLF_COMPLTE_HOLE_14: return "Golf - Complete Hole 14!"; - case GOLF_COMPLTE_HOLE_15: return "Golf - Complete Hole 15!"; - case GOLF_COMPLTE_HOLE_16: return "Golf - Complete Hole 16!"; - case GOLF_COMPLTE_HOLE_17: return "Golf - Complete Hole 17!"; - case GOLF_COMPLTE_HOLE_18: return "Golf - Complete Hole 18!"; - case GOLF_COMPLTE_HOLE_19: return "Golf - Complete Hole 19!"; - case GOLF_COMPLTE_HOLE_20: return "Golf - Complete Hole 20!"; - case GOLF_COMPLTE_HOLE_21: return "Golf - Complete Hole 21!"; + case GOLF_COMPLTE_HOLE_1: + return "Golf - Complete Hole 1!"; + case GOLF_COMPLTE_HOLE_2: + return "Golf - Complete Hole 2!"; + case GOLF_COMPLTE_HOLE_3: + return "Golf - Complete Hole 3!"; + case GOLF_COMPLTE_HOLE_4: + return "Golf - Complete Hole 4!"; + case GOLF_COMPLTE_HOLE_5: + return "Golf - Complete Hole 5!"; + case GOLF_COMPLTE_HOLE_6: + return "Golf - Complete Hole 6!"; + case GOLF_COMPLTE_HOLE_7: + return "Golf - Complete Hole 7!"; + case GOLF_COMPLTE_HOLE_8: + return "Golf - Complete Hole 8!"; + case GOLF_COMPLTE_HOLE_9: + return "Golf - Complete Hole 9!"; + case GOLF_COMPLTE_HOLE_10: + return "Golf - Complete Hole 10!"; + case GOLF_COMPLTE_HOLE_11: + return "Golf - Complete Hole 11!"; + case GOLF_COMPLTE_HOLE_12: + return "Golf - Complete Hole 12!"; + case GOLF_COMPLTE_HOLE_13: + return "Golf - Complete Hole 13!"; + case GOLF_COMPLTE_HOLE_14: + return "Golf - Complete Hole 14!"; + case GOLF_COMPLTE_HOLE_15: + return "Golf - Complete Hole 15!"; + case GOLF_COMPLTE_HOLE_16: + return "Golf - Complete Hole 16!"; + case GOLF_COMPLTE_HOLE_17: + return "Golf - Complete Hole 17!"; + case GOLF_COMPLTE_HOLE_18: + return "Golf - Complete Hole 18!"; + case GOLF_COMPLTE_HOLE_19: + return "Golf - Complete Hole 19!"; + case GOLF_COMPLTE_HOLE_20: + return "Golf - Complete Hole 20!"; + case GOLF_COMPLTE_HOLE_21: + return "Golf - Complete Hole 21!"; - case BOWLING_STANDARD_FIRST_STRIKE: return "Bowling Standard Game - First Strike!"; + case BOWLING_STANDARD_FIRST_STRIKE: + return "Bowling Standard Game - First Strike!"; - case ISLAND_FLYOVER_IPOINT_GROUP_1: return "Progressive Island Flyover I Point Group 1"; - case ISLAND_FLYOVER_IPOINT_GROUP_2: return "Progressive Island Flyover I Point Group 2"; - case ISLAND_FLYOVER_IPOINT_GROUP_3: return "Progressive Island Flyover I Point Group 3"; - case ISLAND_FLYOVER_IPOINT_GROUP_4: return "Progressive Island Flyover I Point Group 4"; - case ISLAND_FLYOVER_IPOINT_GROUP_5: return "Progressive Island Flyover I Point Group 5"; - case ISLAND_FLYOVER_IPOINT_GROUP_6: return "Progressive Island Flyover I Point Group 6"; - case ISLAND_FLYOVER_IPOINT_GROUP_7: return "Progressive Island Flyover I Point Group 7"; - case ISLAND_FLYOVER_IPOINT_GROUP_8: return "Progressive Island Flyover I Point Group 8"; - case ISLAND_FLYOVER_IPOINT_GROUP_9: return "Progressive Island Flyover I Point Group 9"; - case ISLAND_FLYOVER_IPOINT_GROUP_10: return "Progressive Island Flyover I Point Group 10"; - case ISLAND_FLYOVER_IPOINT_GROUP_11: return "Progressive Island Flyover I Point Group 11"; - case ISLAND_FLYOVER_IPOINT_GROUP_12: return "Progressive Island Flyover I Point Group 12"; + case ISLAND_FLYOVER_IPOINT_GROUP_1: + return "Progressive Island Flyover I Point Group 1"; + case ISLAND_FLYOVER_IPOINT_GROUP_2: + return "Progressive Island Flyover I Point Group 2"; + case ISLAND_FLYOVER_IPOINT_GROUP_3: + return "Progressive Island Flyover I Point Group 3"; + case ISLAND_FLYOVER_IPOINT_GROUP_4: + return "Progressive Island Flyover I Point Group 4"; + case ISLAND_FLYOVER_IPOINT_GROUP_5: + return "Progressive Island Flyover I Point Group 5"; + case ISLAND_FLYOVER_IPOINT_GROUP_6: + return "Progressive Island Flyover I Point Group 6"; + case ISLAND_FLYOVER_IPOINT_GROUP_7: + return "Progressive Island Flyover I Point Group 7"; + case ISLAND_FLYOVER_IPOINT_GROUP_8: + return "Progressive Island Flyover I Point Group 8"; + case ISLAND_FLYOVER_IPOINT_GROUP_9: + return "Progressive Island Flyover I Point Group 9"; + case ISLAND_FLYOVER_IPOINT_GROUP_10: + return "Progressive Island Flyover I Point Group 10"; + case ISLAND_FLYOVER_IPOINT_GROUP_11: + return "Progressive Island Flyover I Point Group 11"; + case ISLAND_FLYOVER_IPOINT_GROUP_12: + return "Progressive Island Flyover I Point Group 12"; default: kiwi::cout << "Bad ID: " << id << kiwi::endl; @@ -293,7 +327,7 @@ const char* CheckMgr::GetCheckName(CheckMgr::CheckID id) const { void CheckMgr::Clear() { GenerateCheckIDArray(); - for (int i = 0; i < checkIDArr.Length(); i++) { + for (int i = 0; i < checkIDArr.Size(); i++) { CheckID currCheckID = checkIDArr[i]; SetCheckState(currCheckID, false); } diff --git a/src/core/CheckMgr.h b/src/core/CheckMgr.h index eacf90d..309c1e5 100644 --- a/src/core/CheckMgr.h +++ b/src/core/CheckMgr.h @@ -3,7 +3,6 @@ #include #include "core/const.h" - #include #include @@ -288,8 +287,8 @@ class CheckMgr : public kiwi::DynamicSingleton, kiwi::TArray checkIDArr; private: - kiwi::TMap mCheckState; //!< Check state - kiwi::TMap mCheckToItemID; //!< Check to item mapping + kiwi::THashMap mCheckState; //!< Check state + kiwi::THashMap mCheckToItemID; //!< Check to item mapping }; } // namespace AP diff --git a/src/core/CosmeticMgr.cpp b/src/core/CosmeticMgr.cpp index 29458f3..8f82c71 100644 --- a/src/core/CosmeticMgr.cpp +++ b/src/core/CosmeticMgr.cpp @@ -63,7 +63,7 @@ void CosmeticMgr::Debug() { for (int i = 0; i < K_LENGTHOF(mRandomBgmMapping); i++) { mRandomBgmMapping[i] = i; } - kiwi::Shuffle(mRandomBgmMapping, K_LENGTHOF(mRandomBgmMapping)); + kiwi::Shuffle(mRandomBgmMapping); mRandomFavoriteColor = true; diff --git a/src/core/ItemMgr.cpp b/src/core/ItemMgr.cpp index be6ce0f..6a2b8d7 100644 --- a/src/core/ItemMgr.cpp +++ b/src/core/ItemMgr.cpp @@ -349,6 +349,7 @@ const char* ItemMgr::GetItemName(ItemMgr::ItemID id) { default: kiwi::cout << "Unknown ID" << kiwi::endl; + return "Unknown ID"; } } @@ -518,7 +519,7 @@ void ItemMgr::Debug() { mBwlWalSpinFlag = r.CoinFlip(); // Power Cruising - //mJskBoostFlag = r.CoinFlip(); + // mJskBoostFlag = r.CoinFlip(); mJskRingTimerFlag.Randomize(); mJsk2xRingFlag = r.CoinFlip(); mJskFreeTimerFlag.Randomize(); @@ -540,12 +541,12 @@ void ItemMgr::Debug() { // Air Sports mPlnTimerFlag.Randomize(); mPlnStageFlag.Randomize(); - //mPlnDoubleBlastersFlag = r.CoinFlip(); - //mPlnNightLightsFlag = r.CoinFlip(); - //mPlnBalloonsFlag = r.CoinFlip(); - //mPlnTwoSeaterPlaneFlag = r.CoinFlip(); - //mPlnBoostFlag = r.CoinFlip(); - //mPlnBrakeFlag = r.CoinFlip(); + // mPlnDoubleBlastersFlag = r.CoinFlip(); + // mPlnNightLightsFlag = r.CoinFlip(); + // mPlnBalloonsFlag = r.CoinFlip(); + // mPlnTwoSeaterPlaneFlag = r.CoinFlip(); + // mPlnBoostFlag = r.CoinFlip(); + // mPlnBrakeFlag = r.CoinFlip(); } } // namespace AP diff --git a/src/hooks/Arc/items_Arc.cpp b/src/hooks/Arc/items_Arc.cpp index a7b96c4..841bbc4 100644 --- a/src/hooks/Arc/items_Arc.cpp +++ b/src/hooks/Arc/items_Arc.cpp @@ -1,6 +1,5 @@ #include "core/ItemMgr.h" #include "hooks/trampoline.h" - #include #include @@ -18,9 +17,12 @@ namespace Arc { * @brief Sets the aim flag in Archery */ bool ArcSetAimFlag(bool hold2) { - if (!ItemMgr::GetInstance().IsArcAim()) return false; - else if (!hold2) return false; - else return true; + if (!ItemMgr::GetInstance().IsArcAim()) + return false; + else if (!hold2) + return false; + else + return true; } /** @@ -45,36 +47,36 @@ TRAMPOLINE_DEF(0x80548828, 0x8054882c) { */ bool ArcSetFruitFlag(int stageID) { - int difficulty; - - switch(stageID) { - case 11: - case 24: - case 12: - case 3: - difficulty = 0; - break; - - case 31: - case 9: - case 32: - case 13: - difficulty = 1; - break; - - case 17: - case 22: - case 35: - case 4: - difficulty = 2; - break; - - default: - K_LOG_EX("stageID: %d\n", stageID); - K_LOG_EX("difficulty: %d\n", difficulty); - K_ASSERT(false); + int difficulty = 0; + + switch (stageID) { + case 11: + case 24: + case 12: + case 3: + difficulty = 0; + break; + + case 31: + case 9: + case 32: + case 13: + difficulty = 1; + break; + + case 17: + case 22: + case 35: + case 4: + difficulty = 2; + break; + + default: + K_LOG_EX("stageID: %d\n", stageID); + K_LOG_EX("difficulty: %d\n", difficulty); + K_ASSERT(false); } - + return ItemMgr::GetInstance().IsArcFruitUnlock(difficulty) == 1; } @@ -82,8 +84,7 @@ bool ArcSetFruitFlag(int stageID) { * @brief ArcSetFruitFlag trampoline */ - -TRAMPOLINE_DEF(0x8057cbe0, 0x8057cbe4) { +TRAMPOLINE_DEF(0x8057cbe0, 0x8057cbe4){ // clang-format off TRAMPOLINE_BEGIN diff --git a/src/hooks/Bic/items_Bic.cpp b/src/hooks/Bic/items_Bic.cpp index ca96d99..6a9ab1f 100644 --- a/src/hooks/Bic/items_Bic.cpp +++ b/src/hooks/Bic/items_Bic.cpp @@ -1,6 +1,5 @@ #include "core/ItemMgr.h" #include "hooks/trampoline.h" - #include #include @@ -65,6 +64,7 @@ f32 BicCalcEnergy(Sp2::Bic::Cyclist* pCyclist, f32 energy) { energy = kiwi::Min(energy, energyLimit); pCyclist->setEnergy(energy); + return energy; } /** diff --git a/src/hooks/Cmn/items_Cmn.cpp b/src/hooks/Cmn/items_Cmn.cpp index 05a2d5b..3eb5895 100644 --- a/src/hooks/Cmn/items_Cmn.cpp +++ b/src/hooks/Cmn/items_Cmn.cpp @@ -4,7 +4,6 @@ #include "core/ItemMgr.h" #include "hooks/Swf/items_Swf.h" #include "hooks/trampoline.h" - #include #include #include @@ -52,7 +51,7 @@ bool TryHomeButton() { // Home menu is disabled in Speed Slice while objects are falling if (isSwfPrc && !ItemMgr::GetInstance().IsSwfPrcPause() && Swf::PrcIsObjFalling()) { - return; + return false; } return true; diff --git a/src/hooks/Swf/items_Swf.cpp b/src/hooks/Swf/items_Swf.cpp index 408204c..58fbca3 100644 --- a/src/hooks/Swf/items_Swf.cpp +++ b/src/hooks/Swf/items_Swf.cpp @@ -1,6 +1,5 @@ #include "core/ItemMgr.h" #include "hooks/trampoline.h" - #include #include #include @@ -23,12 +22,12 @@ namespace Swf { * @param pController Remote controller */ void TryBlock(Sp2::Swf::UserCtrl* pUserCtrl, - const Sp2::Cmn::Controller* pController) { + Sp2::Cmn::Controller* pController) { ASSERT(pUserCtrl != nullptr); ASSERT(pController != nullptr); - bool pressed = pController->getCoreStatus()->trig & EGG::cCORE_FSSTICK_B; - bool held = pController->getCoreStatus()->hold & EGG::cCORE_FSSTICK_B; + bool pressed = pController->getCoreStatus()->trig & EGG::cCORE_BUTTON_B; + bool held = pController->getCoreStatus()->hold & EGG::cCORE_BUTTON_B; // Blocking is controlled by the B Button if (!held) { diff --git a/src/scene/DebugRootScene/SceneSelectPage.cpp b/src/scene/DebugRootScene/SceneSelectPage.cpp index e119dd2..8bbc3bc 100644 --- a/src/scene/DebugRootScene/SceneSelectPage.cpp +++ b/src/scene/DebugRootScene/SceneSelectPage.cpp @@ -42,10 +42,12 @@ SceneSelectPage::~SceneSelectPage() { /** * @brief Option select callback * + * @param pInvoker Callback invoker * @param pArg Callback user argument * @return Result of action */ -kiwi::EDebugMenuResult SceneSelectPage::SelectProc(void* pArg) { +kiwi::EDebugMenuResult +SceneSelectPage::SelectProc(kiwi::DebugOptionBase* pInvoker, void* pArg) { ASSERT_PTR(pArg); SceneSelectPage* p = static_cast(pArg); diff --git a/src/scene/DebugRootScene/SceneSelectPage.h b/src/scene/DebugRootScene/SceneSelectPage.h index fa5563b..136ec78 100644 --- a/src/scene/DebugRootScene/SceneSelectPage.h +++ b/src/scene/DebugRootScene/SceneSelectPage.h @@ -34,10 +34,12 @@ class SceneSelectPage : public kiwi::DebugPage { /** * @brief Option select callback * + * @param pInvoker Callback invoker * @param pArg Callback user argument * @return Result of action */ - static kiwi::EDebugMenuResult SelectProc(void* pArg); + static kiwi::EDebugMenuResult SelectProc(kiwi::DebugOptionBase* pInvoker, + void* pArg); private: //! Number of menu options diff --git a/tools/asset.py b/tools/asset.py deleted file mode 100644 index 9cc4497..0000000 --- a/tools/asset.py +++ /dev/null @@ -1,95 +0,0 @@ -# -# Kokeshi asset build script -# -# Don't modify this unless you know what you're doing! -# - -from shutil import copytree -from compile import ROMFS_DIR -from argparse import ArgumentParser -from os.path import exists - -# -# Directories -# - -ASSETS_DIR = "assets" - - -def main() -> None: - """Main function - """ - parser = ArgumentParser(prog="Kokeshi") - - parser.add_argument("--game", type=str, required=True, - choices=["sports", "play", "resort"], help="Game name") - - parser.add_argument("--ci", type=int, required=False, default=0, - help="Use for GitHub CI to avoid the ROM.") - - args = parser.parse_args() - - if not build(args): - exit(1) - - print("[INFO] Success!") - - -def build(args) -> bool: - """Attempt to build the mod - - Args: - args: Parsed command-line arguments - """ - - if not args.ci: - print("[INFO] Installing assets...") - if not install_assets(args): - return False - - return True - - -def install_assets(args) -> bool: - """Move assets into the appropriate romfs location - - Args: - args: Parsed command-line arguments - - Returns: - bool: Success - """ - # Assume Dolphin format (DATA -> disc,files,sys) - disc_root = f"{ROMFS_DIR}/{args.game}" # Extracted disc - partition_root = f"{disc_root}/DATA" # DATA partition (RomFS) - - # Folders that must exist in this disc dump - must_exist = [ - disc_root, - partition_root, - f"{partition_root}/sys", # DOL goes here - f"{partition_root}/files", # Module goes here (well, files/modules...) - ] - - # Check RomFS structure - for path in must_exist: - if not exists(path): - print(f"""[FATAL] RomFS is not setup correctly. Missing the following directory: {partition_root} - Please use Dolphin Emulator's \"Extract Game Disc...\" option, and extract the contents into the following folder: - {disc_root}""") - return False - - try: - # Install assets - copytree(f"{ASSETS_DIR}/{args.game}", - f"{partition_root}/files", dirs_exist_ok=True) - except Exception as err: - print("[FATAL] An error occurred while copying assets:") - print(err) - return False - - return True - - -if __name__ == "__main__": - main() diff --git a/tools/clean.py b/tools/clean.py deleted file mode 100644 index 4a5e0a2..0000000 --- a/tools/clean.py +++ /dev/null @@ -1,33 +0,0 @@ -# -# Kokeshi clean script -# -# Don't modify this unless you know what you're doing! -# - -from shutil import rmtree - -# -# Directories -# - -ASSETS_DIR = "assets" -BUILD_DIR = "build" - - -def main(): - # Remove build artifacts - try: - rmtree(BUILD_DIR) - except FileNotFoundError: - # OK if the directory is already gone - pass - except Exception: - # Something else happened :( - print("[WARN] Could not delete the build directory.") - - # Remove built assets (TODO) - pass - - -if __name__ == "__main__": - main() diff --git a/tools/codewarrior/.gitkeep b/tools/codewarrior/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tools/compile.py b/tools/compile.py deleted file mode 100644 index b8aeed0..0000000 --- a/tools/compile.py +++ /dev/null @@ -1,534 +0,0 @@ -# -# Kokeshi code build script -# -# Don't modify this unless you know what you're doing! -# - -from argparse import ArgumentParser -from os import walk, makedirs -from os.path import join, exists, split -from shutil import copyfile, copytree -from subprocess import run, PIPE -from hashlib import sha1 -from threading import Thread - -# -# Configuration -# - -# DOL address where the Kamek loader will be statitcally linked. -# Change it if you need this memory area for whatever reason. -LOADER_ADDR = 0x80001900 - -# -# Compiler flags -# - -# Flags applied to all source files -CFLAGS_COMMON = " ".join([ - # For Kokeshi-specific code (separate from decomp) - "-D__KOKESHI__", - - "-proc gekko", # Gekko processor - "-I-", - "-Cpp_exceptions off", # Disable C++ exceptions - "-enum int", # Force 4-byte enumerations - "-O4,s", # Max optimization level, focus on small code size - "-use_lmw_stmw on", # Use lmw/stmw for stack frames to save code size - "-fp fmadd", # Use compact floating-point instructions to save code size - "-rostr", # Place strings in rodata - "-RTTI off", # Disable RTTI to save module size - "-sdata 0", # We can't use small data sections in relocatable code - "-sdata2 0", # We can't use small data sections in relocatable code - "-pragma \"cpp1x on\"", # Enable C++11 features - "-DREVOLUTION", # For BTE library -]) - -# Flags applied only to the module -CFLAGS_MODULE = " ".join([ -]) - -# Flags applied for debug target -CFLAGS_DEBUG = " ".join([ -]) - -# Flags applied for release target -CFLAGS_RELEASE = " ".join([ - "-DNDEBUG" -]) - -# -# Directories -# - -BUILD_DIR = "build" -BASE_DIR = "base" -ROMFS_DIR = "romfs" -MODULES_DIR = "modules" -INCLUDE_DIR = "include" -LIBRARY_DIR = "lib" -LOADER_DIR = "loader" -SRC_DIR = "src" -TOOLS_DIR = "tools" - -# -# Tools -# - -CC = f"{TOOLS_DIR}\\mwcceppc.exe" -KAMEK = f"{TOOLS_DIR}\\Kamek.exe" - -# -# File extensions -# - -SRC_EXTENSIONS = [".c", ".cpp", ".cc", ".cxx"] -INCLUDE_EXTENSIONS = [".h", ".hpp", ".hh", ".hxx"] - -# -# Known good file hashes -# - -GOOD_HASHES = { - "sports": [ - "8bb422971b88b5551a37de98db69557df7b46637" # Wii Sports (US, Rev 1) - ], - "play": [ - "0da5e7e51135219f580ad011d1b635bc83569bb9" # Wii Play (US, Rev 1) - ], - "resort": [ - "e3e22a9de62f6e11ded52e9a7e6933892963b219" # Wii Sports Resort (US) - ] -} - -# -# Functions -# - - -def main() -> None: - """Main function - """ - - parser = ArgumentParser(prog="Kokeshi") - - parser.add_argument("--game", type=str, required=True, - choices=["sports", "play", "resort"], help="Game name") - - parser.add_argument("--target", type=str, required=False, - default="debug", choices=["debug", "release"], help="Build target") - - parser.add_argument("--cflags", type=str, required=False, - help="Register a custom set of compiler flags") - - parser.add_argument("--define", action='append', - required=False, help="Register a custom preprocessor definition of the form \"KEY,VALUE\"") - - parser.add_argument("--ci", type=int, required=False, default=0, - help="Use for GitHub CI to only compile code and avoid the ROM.") - - args = parser.parse_args() - success = build(args) - - if not success: - exit(1) - - print(f"[INFO] Success!") - - -def build(args) -> bool: - """Attempt to build the mod - - Args: - args: Parsed command-line arguments - """ - - if not args.ci: - print("[INFO] Checking baserom...") - if not baserom_ok(args): - return False - - print("[INFO] Building Kamek loader...") - if not build_loader(args): - return False - - print(f"[INFO] Building module...") - if not build_module(args): - return False - - if not args.ci: - print(f"[INFO] Installing to romfs...") - if not install_romfs(args): - return False - - return True - - -def search_files(root: str, extensions: list[str]) -> list[str]: - """Search directory recursively for files with the specified extensions - - Args: - root (str): Root directory - extensions (list[str]): Allowed file extensions - - Returns: - list[str]: Search results - """ - - found = [] - - for dirpath, _, filenames in walk(root): - for name in filenames: - # Isolate file extension - ext = name[name.rfind("."):] - - # Check whitelist - if ext in extensions: - # Absolute path - found.append(join(dirpath, name)) - - return found - - -def search_dirs(root: str, recursive: bool) -> list[str]: - """Search directory recursively for subdirectories - - Args: - root (str): Root directory - - Returns: - list[str]: Search results - """ - found = [root] - - for dirpath, dirnames, _ in walk(root): - # Absolute path - found += [join(dirpath, x) for x in dirnames] - - if not recursive: - break - - return found - - -def src_to_obj(path: str) -> str: - """Convert source file path to object file path - - Args: - path (str): Source file path - - Returns: - str: Object file path - """ - - # Sort extensions by length to ensure greedy matching - for ext in sorted(SRC_EXTENSIONS, key=lambda x: len(x)): - # Replace with object extension, and also put it in the build directory - if ext in path: - return f"{BUILD_DIR}/{path.removesuffix(ext)}.o" - - return path - - -def compile(path: str, flags: str) -> bool: - """Attempt to compile source file - - Args: - path (str): Source file path - flags (str): Compiler flags - - Returns: - bool: Success - """ - - # Object file that will be created - obj = src_to_obj(path) - # Make directories if we need to for this object - makedirs(split(obj)[0], exist_ok=True) - - # Shell command - cmd = f"{CC} {flags} -c -o {obj} {path}" - - # Run CW compiler - result = run(cmd, shell=True, stdout=PIPE, - stderr=PIPE, universal_newlines=True) - - # Check for compiler error - if result.returncode != 0: - print(result.returncode, result.stdout, result.stderr) - - return result.returncode == 0 - - -def compile_thread_func(path: str, flags: str, results: list): - """Thread function helper for compile() - - Args: - path (str): Source file path - flags (str): Compiler flags - results (list): Output list - """ - results.append(compile(path, flags)) - - -def link(files: list[str], flags: str) -> bool: - """Attempt to link object files - - Args: - files (list[str]): Object files - ldflags (str): Linker flags - - Returns: - bool: Success - """ - - # Shell command - cmd = f"{KAMEK} {' '.join(files)} {flags}" - - # Run Kamek linker - result = run(cmd, shell=True, stdout=PIPE, - stderr=PIPE, universal_newlines=True) - - # Check for linker error - if result.returncode != 0: - print(result.returncode, result.stdout, result.stderr) - - return result.returncode == 0 - - -def baserom_ok(args) -> bool: - """Check for the existence & correctness of the base game executable - - Args: - args: Parsed command-line arguments - - Returns: - bool: Success - """ - - # Where the base DOL should be - rom_path = f"{BASE_DIR}/baserom_{args.game}.dol" - - # Read executable contents - try: - f = open(rom_path, "rb") - dol = f.read() - except OSError: - print(f"[FATAL] Baserom is missing or could not be opened: {rom_path}") - return False - - # Verify hash - ctx = sha1() - ctx.update(dol) - if ctx.hexdigest() not in GOOD_HASHES[args.game]: - print(f"[FATAL] Baserom does not have the correct hash: {rom_path}") - return False - - return True - - -def build_loader(args) -> bool: - """Compile & link Kamek loader program - - Args: - args: Parsed command-line arguments - - Returns: - bool: Success - """ - - # - # Compilation step - # - - # Identify loader files - srcs = search_files(LOADER_DIR, SRC_EXTENSIONS) - objs = [src_to_obj(f) for f in srcs] - - inc_dirs = ["include/MSL"] + \ - search_dirs(SRC_DIR, recursive=False) + \ - search_dirs(INCLUDE_DIR, recursive=False) + \ - search_dirs(LIBRARY_DIR, recursive=False) + \ - [LOADER_DIR] - - # Loader compiler flags - cflags = ' '.join([ - # Common flags - CFLAGS_COMMON, - # Pack definition - f"-DPACK_{args.game.upper()}", - # Build target flags (release/debug) - ' '.join(CFLAGS_DEBUG if args.target == "debug" else CFLAGS_RELEASE), - # User flags - args.cflags, - # Include flags - ' '.join([f"-ir {x}" for x in inc_dirs]) - ]) - - # Compile source files - threads = [] - success = [] - for f in srcs: - t = Thread(target=compile_thread_func, args=(f, cflags, success)) - threads.append(t) - t.start() - - # Join threads - for t in threads: - t.join() - - # Validate return codes - if False in success: - print("[FATAL] Error while compiling Kamek loader.") - return False - - # - # Link step - # - - if not args.ci: - # Kamek loader flags - ldflags = " ".join([ - f"-static={hex(LOADER_ADDR)}", - f"-input-dol={BASE_DIR}/baserom_{args.game}.dol", - f"-output-dol={BUILD_DIR}/main_{args.game}.dol", - f"-output-kamek={BUILD_DIR}/{LOADER_DIR}/Loader_{args.game}.bin", - f"-output-map={BUILD_DIR}/{LOADER_DIR}/Loader_{args.game}.map", - f"-externals={BASE_DIR}/symbols_{args.game}.txt" - ]) - - if not link(objs, ldflags): - print("[FATAL] Error while linking Kamek loader.") - return False - - return True - - -def build_module(args) -> bool: - """Compile & link module program - - Args: - args: Parsed command-line arguments - - Returns: - bool: Success - """ - - # - # Compilation step - # - - # Identify module files - # NOTE: Make sure library files are linked BEFORE module files - srcs = search_files(LIBRARY_DIR, SRC_EXTENSIONS) + \ - search_files(SRC_DIR, SRC_EXTENSIONS) - objs = [src_to_obj(f) for f in srcs] - - inc_dirs = ["include/MSL"] + \ - search_dirs(SRC_DIR, recursive=False) + \ - search_dirs(INCLUDE_DIR, recursive=False) + \ - search_dirs(LIBRARY_DIR, recursive=False) + \ - [LOADER_DIR] - - # Module compiler flags - cflags = ' '.join([ - # Common flags - CFLAGS_COMMON, - # Module flags - CFLAGS_MODULE, - # Pack definition - f"-DPACK_{args.game.upper()}", - # Build target flags (release/debug) - ' '.join(CFLAGS_DEBUG if args.target == "debug" else CFLAGS_RELEASE), - # User flags - args.cflags, - # Include flags - ' '.join([f"-ir {x}" for x in inc_dirs]) - ]) - - # Compile source files - threads = [] - success = [] - for f in srcs: - t = Thread(target=compile_thread_func, args=(f, cflags, success)) - threads.append(t) - t.start() - - # Join threads - for t in threads: - t.join() - - # Validate return codes - if False in success: - print("[FATAL] Error while compiling your module.") - return False - - # - # Link step - # - - # Make modules directory if we need to - makedirs(f"{BUILD_DIR}/{MODULES_DIR}", exist_ok=True) - - # Kamek module flags - ldflags = " ".join([ - f"-output-kamek={BUILD_DIR}/{MODULES_DIR}/m_{args.game}.bin", - f"-output-map={BUILD_DIR}/{MODULES_DIR}/m_{args.game}.map", - f"-externals={BASE_DIR}/symbols_{args.game}.txt" - ]) - - if not link(objs, ldflags): - print("[FATAL] Error while linking your module.") - return False - - return True - - -def install_romfs(args) -> bool: - """Move everything into its appropriate romfs location - - Args: - args: Parsed command-line arguments - - Returns: - bool: Success - """ - # Assume Dolphin format (DATA -> disc,files,sys) - disc_root = f"{ROMFS_DIR}/{args.game}" # Extracted disc - partition_root = f"{disc_root}/DATA" # DATA partition (RomFS) - - # Folders that must exist in this disc dump - must_exist = [ - disc_root, - partition_root, - f"{partition_root}/sys", # DOL goes here - f"{partition_root}/files", # Module goes here (well, files/modules...) - ] - - # Check RomFS structure - for path in must_exist: - if not exists(path): - print(f"""[FATAL] RomFS is not setup correctly. Missing the following directory: {partition_root} - Please use Dolphin Emulator's \"Extract Game Disc...\" option, and extract the contents into the following folder: - {disc_root}""") - return False - - try: - # Install loader (sys/main.dol patch) - copyfile(f"{BUILD_DIR}/main_{args.game}.dol", - f"{partition_root}/sys/main.dol") - - # Install module & mapfile - copytree(f"{BUILD_DIR}/{MODULES_DIR}", - f"{partition_root}/files/{MODULES_DIR}", dirs_exist_ok=True) - except Exception: - return False - - return True - - -# -# Top-level code -# -if __name__ == "__main__": - main() diff --git a/tools/kamek/.gitkeep b/tools/kamek/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tools/libkiwi_py/binary/block/block_base.py b/tools/libkiwi_py/binary/block/block_base.py deleted file mode 100644 index a90970d..0000000 --- a/tools/libkiwi_py/binary/block/block_base.py +++ /dev/null @@ -1,87 +0,0 @@ -from libkiwi_py.stream.block_builder import BlockBuilder -from libkiwi_py.stream.stream_base import Endian, StreamBase -from libkiwi_py.binary.types.member import Member - - -class BlockBase: - """Base block class""" - - # All blocks are aligned to 32 bytes - BLOCK_ALIGN = 32 - - # Block magic/kind is limited to 4 bytes - KIND_MAX_LEN = 4 - - def __init__(self, kind: str): - self.kind = kind - self.builder = BlockBuilder(Endian.Big) - self.__members = dict() - - def before_build_callback(self): - """Override to implement custom serialization before the block contents are built""" - pass - - def after_build_callback(self): - """Override to implement custom serialization after the block contents are built""" - pass - - def __getitem__(self, key: str) -> Member: - """Access block member""" - assert key in self.__members, f"Member does not exist: {key}" - return self.__members[key] - - def add_member(self, member: Member): - """Add member to block""" - assert member.name not in self.__members, f"Duplicate member declaration: {member.name}" - self.__members[member.name] = member - - def offset_of(self, key: str): - """Offset of member in block""" - # Add up offsets until we hit the desired member - offset = 0 - offset += 4 # u32 kind - offset += 4 # u32 size - - for item in self.__members.items(): - # Target member found - if item[0] == key: - return offset - # Keep going - offset += item[1].byte_size() - - # Member is not in block - return -1 - - def byte_size(self) -> int: - """Size of block in bytes""" - bsize = 0 - bsize += 4 # u32 kind - bsize += 4 # u32 size - bsize += self.builder.buffer_size() # Block data - return bsize - - def aligned_size(self) -> int: - """Size of block in bytes, aligned to BLOCK_ALIGN""" - bsize = self.byte_size() - align = self.BLOCK_ALIGN - (bsize % self.BLOCK_ALIGN) - return bsize + align - - def write(self, strm: StreamBase): - """Write block builder to stream""" - - self.before_build_callback() - - # Serialize to block builder - for m in self.__members.values(): - m.write(self.builder) - - self.after_build_callback() - - # Block kind - strm.write_string(self.kind, maxlen=self.KIND_MAX_LEN, terminate=False) - # Block size - strm.write_u32(self.aligned_size()) - # Block data - strm.write(self.builder.buffer_data()) - # Block padding - strm.write_padding(self.aligned_size() - self.byte_size()) diff --git a/tools/libkiwi_py/binary/block/header_block_base.py b/tools/libkiwi_py/binary/block/header_block_base.py deleted file mode 100644 index fbba142..0000000 --- a/tools/libkiwi_py/binary/block/header_block_base.py +++ /dev/null @@ -1,29 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase -from libkiwi_py.stream.stream_base import StreamBase -from libkiwi_py.binary.types.primitive import Primitive - - -class HeaderBlockBase(BlockBase): - """Base header block""" - - def __init__(self, kind: str, version: int, blocks: list[BlockBase]): - super().__init__(kind) - self.version = version - self.children = blocks - - self.add_member(Primitive("u16", "version", value=self.VERSION)) - self.add_member(Primitive("u16", "numBlocks", - value=len(self.children))) - - def append_child(self, block: BlockBase): - """Append child block""" - self.children.append(block) - self["numBlocks"].value += 1 - - def write(self, strm: StreamBase): - """Write block buffer to stream""" - BlockBase.write(self, strm) - - # Children blocks - for block in self.children: - block.write(strm) diff --git a/tools/libkiwi_py/binary/types/bitfield.py b/tools/libkiwi_py/binary/types/bitfield.py deleted file mode 100644 index 33cd749..0000000 --- a/tools/libkiwi_py/binary/types/bitfield.py +++ /dev/null @@ -1,121 +0,0 @@ -from libkiwi_py.binary.types.member import Member -from libkiwi_py.binary.types.primitive import Primitive -from libkiwi_py.stream.stream_base import StreamBase -from copy import deepcopy - - -class BitMember: - """Member of bitfield""" - - def __init__(self, name: str, size: int, value=0, enum_cls=None): - self.name = name - self.size = size - self.value = value - - # Hacky, but we sometimes the bitfield member should take on an enum value. - # We don't want inheritance, because these enums should already exist. - self.__enum = enum_cls.VALUES if enum_cls != None else dict() - - self.set_value(value) - - def set_value(self, value): - """Set member value, potentially using an enum value""" - # Enum value - if type(value) == str: - assert value in self.__enum, f"Invalid enum value for {self.name}: {value}" - self.value = self.__enum[value] - - # Raw value - else: - assert type( - value) == int, "Specify either an enum value or a raw integer value." - self.value = value - - -class BitField(Member): - """Bit field member""" - - def __init__(self, underlying_type: str, name: str, values: dict[str, int] = {}): - super().__init__(self.__class__.__name__, name) - self.__type = underlying_type - - # Convert member list into dictionary - self.value = {m.name: m for m in deepcopy(self.MEMBERS)} - - # User initialization - for item in values.items(): - k, v = item[0], item[1] - if k in self.members: - self.members[k].set_value(v) - - assert self.__type in Primitive.PRIM_2_WRITE_FUNC, f"Invalid bitfield type: {self.__type}" - - self.__validate() - - def __getitem__(self, key: str): - """Access member of bitfield by name""" - assert key in self.__members, f"Member {key} not in bitfield {self.__class__.__name__}" - return self.__members[key] - - def __iter__(self): - """Iterator support""" - return self.value.values().__iter__() - - def byte_size(self): - """Size of bitfield in bytes""" - assert self.__type in Primitive.PRIM_2_BYTE_SIZE, f"Invalid bitfield type: {self.__type}" - return Primitive.PRIM_2_BYTE_SIZE[self.__type] - - def write(self, strm: StreamBase): - """Write bitfield to file""" - assert self.__type in Primitive.PRIM_2_WRITE_FUNC, f"Invalid bitfield type: {self.__type}" - f = Primitive.PRIM_2_WRITE_FUNC[self.__type] - - f(strm, self.__raw_value()) - - def set_value(self, data): - """Set bitfield values""" - # Everything is nullable - if data == None: - return - - # User initialization - for item in data.items(): - k, v = item[0], item[1] - - if k in self.value: - self.value[k].set_value(v) - else: - print( - f"[WARN] Cannot access undeclared member: {self.__class__.__name__}::{k}. Value will be ignored") - - def __validate(self): - """Validate members of bitfield""" - max_bytes = self.byte_size() - my_bits = sum(member.size for member in self) - - # Get byte count - my_bytes = my_bits // 8 - - # Roll over into next byte - if my_bits % 8 != 0: - my_bytes += 1 - - assert my_bytes <= max_bytes - - def __raw_value(self): - """Get raw (integer) value of bitfield""" - raw = 0 - pos = 0 - - # Compose value - for member in self: - assert pos < self.byte_size() * 8, "Bitfield overflow!!" - - mask = (~(1 << member.size)) - value = member.value & mask - raw |= (value << pos) - - pos += member.size - - return raw diff --git a/tools/libkiwi_py/binary/types/common.py b/tools/libkiwi_py/binary/types/common.py deleted file mode 100644 index d2eda9a..0000000 --- a/tools/libkiwi_py/binary/types/common.py +++ /dev/null @@ -1,30 +0,0 @@ -from libkiwi_py.binary.types.structure import Structure -from libkiwi_py.binary.types.primitive import Primitive - - -class Size(Structure): - """2D vector representing size""" - - MEMBERS = [ - Primitive("f32", "width"), - Primitive("f32", "height") - ] - - -class VEC2(Structure): - """2D vector""" - - MEMBERS = [ - Primitive("f32", "x"), - Primitive("f32", "y") - ] - - -class VEC3(Structure): - """3D vector""" - - MEMBERS = [ - Primitive("f32", "x"), - Primitive("f32", "y"), - Primitive("f32", "z") - ] diff --git a/tools/libkiwi_py/binary/types/enum.py b/tools/libkiwi_py/binary/types/enum.py deleted file mode 100644 index 940f957..0000000 --- a/tools/libkiwi_py/binary/types/enum.py +++ /dev/null @@ -1,30 +0,0 @@ -from libkiwi_py.binary.types.primitive import Primitive - - -class Enum(Primitive): - """Primitive member associated with an enum""" - - def __init__(self, underlying_type: str, name: str, arr: str = None, value=None): - super().__init__(underlying_type, name, arr, value) - self.__enum = self.VALUES - - def __getitem__(self, key: str): - """Access enum values like a dictionary""" - assert key in self.__enum, f"Invalid enum value: {key} not in {self.__class__.__name__}" - return self.__enum[key] - - def set_value(self, data): - """Set member value""" - if data == None: - data = self._get_default_value() - - # Enum value - if type(data) == str: - assert data in self.__enum, f"Invalid enum value: {data} not in {self.__class__.__name__}" - Primitive.set_value(self, self.__enum[data]) - - # Raw value (sure, I guess..) - else: - assert type( - data) == int, "Specify either an enum value or a raw integer value." - Primitive.set_value(self, data) diff --git a/tools/libkiwi_py/binary/types/gx.py b/tools/libkiwi_py/binary/types/gx.py deleted file mode 100644 index b4f25e8..0000000 --- a/tools/libkiwi_py/binary/types/gx.py +++ /dev/null @@ -1,109 +0,0 @@ -from libkiwi_py.binary.types.enum import Enum -from libkiwi_py.binary.types.primitive import Primitive -from libkiwi_py.binary.types.structure import Structure - - -class GXAlphaOp(Enum): - """GX alpha operation""" - - VALUES = { - "GX_AOP_AND": 0, - "GX_AOP_OR": 1, - "GX_AOP_XOR": 2, - "GX_AOP_XNOR": 3, - } - - -class GXCompare(Enum): - """GX comparison""" - - VALUES = { - "GX_NEVER": 0, - "GX_LESS": 1, - "GX_EQUAL": 2, - "GX_LEQUAL": 3, - "GX_GREATER": 4, - "GX_NEQUAL": 5, - "GX_GEQUAL": 6, - "GX_ALWAYS": 7 - } - - -class GXColorSrc(Enum): - """GX color source""" - - VALUES = { - "GX_SRC_REG": 0, - "GX_SRC_VTX": 1 - } - - -class GXTexCoordID(Enum): - """GX texture coordinate ID""" - - VALUES = { - "GX_TEXCOORD0": 0, - "GX_TEXCOORD1": 1, - "GX_TEXCOORD2": 2, - "GX_TEXCOORD3": 3, - "GX_TEXCOORD4": 4, - "GX_TEXCOORD5": 5, - "GX_TEXCOORD6": 6, - "GX_TEXCOORD7": 7, - "GX_TEXCOORD_NULL": 255 - } - - -class GXTexMapID(Enum): - """GX texture map ID""" - - VALUES = { - "GX_TEXMAP0": 0, - "GX_TEXMAP1": 1, - "GX_TEXMAP2": 2, - "GX_TEXMAP3": 3, - "GX_TEXMAP4": 4, - "GX_TEXMAP5": 5, - "GX_TEXMAP6": 6, - "GX_TEXMAP7": 7, - "GX_TEXMAP_NULL": 255, - "GX_TEX_DISABLE": 256 - } - - -class GXIndTexScale(Enum): - """GX indirect texture scale""" - - VALUES = { - "GX_ITS_1": 0, - "GX_ITS_2": 1, - "GX_ITS_4": 2, - "GX_ITS_8": 3, - "GX_ITS_16": 4, - "GX_ITS_32": 5, - "GX_ITS_64": 6, - "GX_ITS_128": 7, - "GX_ITS_256": 8 - } - - -class GXColor(Structure): - """GX 32-bit color""" - - MEMBERS = [ - Primitive("u8", "r"), - Primitive("u8", "g"), - Primitive("u8", "b"), - Primitive("u8", "a") - ] - - -class GXColorS10(Structure): - """GX 64-bit color""" - - MEMBERS = [ - Primitive("s16", "r"), - Primitive("s16", "g"), - Primitive("s16", "b"), - Primitive("s16", "a") - ] diff --git a/tools/libkiwi_py/binary/types/member.py b/tools/libkiwi_py/binary/types/member.py deleted file mode 100644 index 738c0ea..0000000 --- a/tools/libkiwi_py/binary/types/member.py +++ /dev/null @@ -1,116 +0,0 @@ -from libkiwi_py.stream.stream_base import StreamBase -from libkiwi_py.utility.util import Util -from re import search - - -class Member: - """Representation of a structure field/member""" - - ARRAY_REGEX = r"\[\s*(?P[0-9]*)\s*\]" - - def __init__(self, _type: str, name: str, arr: str = None, value=None): - # Type name - self.type = _type - # Member name - self.name = name - - # Array declaration - if arr != None: - match_obj = search(self.ARRAY_REGEX, arr) - assert match_obj != None and match_obj.group( - "Size") != None, f"Invalid array declaration: {arr}" - - self.__length = match_obj.group("Size") - - # Variadic-length array - if self.__length == "": - self.__length = -1 - # Explicit length - else: - # Limit array length to 1 - self.__length = max(1, int(self.__length)) - - # Single element - else: - self.__length = 1 - - # Member value - self.set_value(value) - - def __repr__(self): - """Convert object to string (for debugging)""" - text = f"{self.type} {self.name}" - - # Format array type - if self.is_array(): - # Variable-length array - if self.is_vl_array(): - text += "[]" - # Explicit length - else: - text += f"[{self.__length}]" - - return f"{text} = {self.value}" - - def __iter__(self): - """Iterator support""" - if self.is_array(): - return self.value.__iter__() - return [self.value].__iter__() - - def set_value(self, data): - """Set member value""" - # Everything is nullable - if data == None: - if self.is_vl_array(): - self.value = list() - else: - self.value = data - return - - # Is an array - if self.is_array(): - assert Util.is_iterable( - data), "Cannot set non-array value to array member" - - # Explicit array length - if not self.is_vl_array(): - assert len( - data) == self.__length, f"Array length mismatch: got {len(data)}, expected {self.__length}" - - # Convert all iterable types to list - self.value = list(data) - - # Not an array - else: - assert not Util.is_list( - data) or len(data) == 1, "Cannot set list value to non-array member" - self.value = data - - def array_size(self): - """Member array length""" - if self.is_vl_array(): - # VLA is not yet initialized - if self.value == None: - return 1 - # VLA has been initialized - return len(self.value) - if self.is_array(): - return self.__length - return 1 - - def byte_size(self): - """Size of member in bytes""" - pass - - def write(self, strm: StreamBase): - """Write member to stream""" - pass - - def is_array(self): - """Check whether the member is an array""" - return self.__length == -1 or self.__length > 1 - - def is_vl_array(self): - """Check whether the member is a variable-length array""" - return self.__length == -1 diff --git a/tools/libkiwi_py/binary/types/primitive.py b/tools/libkiwi_py/binary/types/primitive.py deleted file mode 100644 index 5781738..0000000 --- a/tools/libkiwi_py/binary/types/primitive.py +++ /dev/null @@ -1,117 +0,0 @@ -from libkiwi_py.binary.types.member import Member -from libkiwi_py.stream.stream_base import StreamBase - - -class Primitive(Member): - """Primitive-type member""" - - PRIM_2_WRITE_FUNC = { - "u8": StreamBase.write_u8, - "unsigned char": StreamBase.write_u8, - "bool": StreamBase.write_u8, - - "s8": StreamBase.write_s8, - "char": StreamBase.write_s8, - "signed char": StreamBase.write_s8, - - "u16": StreamBase.write_u16, - "unsigned short": StreamBase.write_u16, - "wchar_t": StreamBase.write_u16, - - "s16": StreamBase.write_s16, - "short": StreamBase.write_s16, - "signed short": StreamBase.write_s16, - - "u32": StreamBase.write_u32, - "unsigned long": StreamBase.write_u32, - - "s32": StreamBase.write_s32, - "long": StreamBase.write_s32, - "signed long": StreamBase.write_s32, - "int": StreamBase.write_s32, - "signed int": StreamBase.write_s32, - - "f32": StreamBase.write_f32, - "float": StreamBase.write_f32, - - "f64": StreamBase.write_f64, - "double": StreamBase.write_f64, - } - - PRIM_2_BYTE_SIZE = { - "u8": 1, - "unsigned char": 1, - "bool": 1, - - "s8": 1, - "char": 1, - "signed char": 1, - - "u16": 2, - "unsigned short": 2, - "wchar_t": 2, - - "s16": 2, - "short": 2, - "signed short": 2, - - "u32": 4, - "unsigned long": 4, - - "s32": 4, - "long": 4, - "signed long": 4, - "int": 4, - "signed int": 4, - - "f32": 4, - "float": 4, - - "f64": 8, - "double": 8, - } - - def __init__(self, _type: str, name: str, arr: str = None, value=None): - super().__init__(_type, name, arr, value) - - # Attempt to use default primitive value if nothing was specified - if self.value == None: - self.value = self._get_default_value() - - def byte_size(self): - """Size of primitive member in bytes""" - assert self.type in self.PRIM_2_BYTE_SIZE, "Not a primitive type!" - size_one = self.PRIM_2_BYTE_SIZE[self.type] - return size_one * self.array_size() - - def write(self, strm: StreamBase): - """Write primitive member to stream""" - assert self.type in self.PRIM_2_BYTE_SIZE, "Not a primitive type!" - f = self.PRIM_2_WRITE_FUNC[self.type] - - for elem in self: - f(strm, elem) - - def _get_default_value(self): - """Get default value for primitive member""" - # Variable-length array - if self.is_vl_array(): - # Cannot safely initialize, user doesn't know length - return [] - - default = None - - if self.type in self.PRIM_2_WRITE_FUNC: - default = 0 - # Unsupported type, or is a Structure - else: - print( - f"[WARN] Primitive type has no known default value: {self.type}") - return None - - # Scale for arrays - if self.is_array(): - return [default] * self.array_size() - - # Single element - return default diff --git a/tools/libkiwi_py/binary/types/string.py b/tools/libkiwi_py/binary/types/string.py deleted file mode 100644 index a90fbe6..0000000 --- a/tools/libkiwi_py/binary/types/string.py +++ /dev/null @@ -1,78 +0,0 @@ -from libkiwi_py.binary.types.member import Member -from libkiwi_py.stream.stream_base import StreamBase -from libkiwi_py.utility.util import Util - - -class String(Member): - """ANSI string member""" - - STRING_TYPES = ("cstr", "str") - - def __init__(self, name: str, arr: str = None, value=None, c_style: bool = True, maxlen: int = -1, pad: bool = False): - super().__init__(self.__class__.__name__, name, arr, value) - self.c_style = c_style - self.maxlen = maxlen - self.pad = pad - - def byte_size(self): - """Size of string member in bytes""" - # Recurse if array - if self.is_array(): - return sum(s.byte_size() for s in self) - - # Single string (PADDED) - if self.pad: - return self.maxlen - - # Single string (UNPADDED) - return Util.str_len(self.value, self.c_style) - - def write(self, strm: StreamBase): - """Write string member to stream""" - for string in self: - # String length - length = Util.str_len(string, terminator=self.c_style) - - # Truncate to specified max length - if self.maxlen > 0: - if length > self.maxlen: - print( - f"[WARN] String {string} will be truncated to {self.maxlen} characters.") - - # Write data - strm.write_string(string, self.maxlen, self.c_style) - - # Optional padding - if self.pad and length < self.maxlen: - strm.write_padding(self.maxlen - length) - - -class WString(String): - """Widechar (UTF-16) string member""" - - def __init__(self, name: str, arr: str = None, value=None, c_style: bool = True, maxlen: int = -1, pad: bool = True): - super().__init__(name, arr, value, c_style, maxlen, pad) - - def byte_size(self): - """Size of string member in bytes""" - return String.byte_size() * 2 # wchar_t - - def write(self, strm: StreamBase): - """Write string member to stream""" - for string in self: - # String length - length = Util.str_len(string, terminator=self.c_style) - - # Truncate to specified max length - if self.maxlen > 0: - # NOT A BUG! Max length counts characters, not bytes - if length > self.maxlen: - print( - f"[WARN] String {string} will be truncated to {self.maxlen} characters.") - - # Write data - strm.write_wstring(string, self.maxlen, self.c_style) - - # Optional padding - if self.pad and length < self.maxlen: - strm.write_padding(self.maxlen - length) diff --git a/tools/libkiwi_py/binary/types/structure.py b/tools/libkiwi_py/binary/types/structure.py deleted file mode 100644 index b0eeefb..0000000 --- a/tools/libkiwi_py/binary/types/structure.py +++ /dev/null @@ -1,103 +0,0 @@ -from libkiwi_py.binary.types.member import Member -from libkiwi_py.stream.stream_base import StreamBase -from copy import deepcopy -from libkiwi_py.utility.util import Util - - -class Structure(Member): - """Structure containing members""" - - def __init__(self, name: str, arr: str = None, values=None): - super().__init__(self.__class__.__name__, name, arr) - - # Convert member list into dictionary - members = {m.name: m for m in deepcopy(self.MEMBERS)} - - if self.is_array(): - # Cannot initialize variable length array - if self.is_vl_array(): - self.value = list() - else: - # In an array, all indices will be initialized the same way - self.value = [members] * self.array_size() - # Single element - else: - self.value = members - - # User initialization - if values != None: - self.set_value(values) - - def __getitem__(self, key): - """Access member of structure""" - return self.value[key] - - def __repr__(self): - """Convert object to string (for debugging)""" - return f"{self.type} {self.name} = {{{','.join(self.value)}}}" - - def byte_size(self): - """Size of structure in bytes""" - # Size of one instance - size = sum(m.byte_size() for m in self.MEMBERS) - # Scale for array - return size * self.array_size() - - def write(self, strm: StreamBase): - """Write structure to stream""" - for inst in self: - for m in inst.values(): - m.write(strm) - - def append(self, member: Member): - """Append to structure's array""" - assert self.is_array(), "Not an array!" - self.value.append(member.value) - - def offset_of(self, key: str): - """Offset of member in structure""" - # First set of members - member_dict = self.value if not self.is_array( - ) else self.value[0] - - # Add up offsets until we hit the desired member - offset = 0 - for item in member_dict.items(): - # Target member found - if item[0].name == key: - return offset - # Keep going - offset += item[1].byte_size() - - # Member is not in structure - return -1 - - def set_value(self, members): - """Set structure values (members)""" - if members == None: - return - - # Convert to length 1 list - if not Util.is_list(members): - members = [members] - - # Structure members as list - my_members = [self.value] if not self.is_array() else self.value - - # Length should be the same - assert len(members) == len( - my_members), f"Invalid array initialization: Expected {len(my_members)} entries, got {len(members)}" - - # User initialization - for i, m in enumerate(members): - # Array element (i'th instance of structure) - inst = my_members[i] - - # Apply values - for item in m.items(): - k, v = item[0], item[1] - if k in inst: - inst[k].set_value(v) - else: - print( - f"[WARN] Cannot access undeclared member: {self.__class__.__name__}::{k}. Value will be ignored") diff --git a/tools/libkiwi_py/layout/clyt_block.py b/tools/libkiwi_py/layout/clyt_block.py deleted file mode 100644 index 7dd5489..0000000 --- a/tools/libkiwi_py/layout/clyt_block.py +++ /dev/null @@ -1,13 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase -from libkiwi_py.binary.block.header_block_base import HeaderBlockBase - - -class KLYTBlock(HeaderBlockBase): - """Layout header block""" - - # Update as format is revised - SIGNATURE = "KLYT" - VERSION = 0x0100 # 1.0 - - def __init__(self, blocks: list[BlockBase] = []): - super().__init__(self.SIGNATURE, self.VERSION, blocks) diff --git a/tools/libkiwi_py/layout/fnl1_block.py b/tools/libkiwi_py/layout/fnl1_block.py deleted file mode 100644 index a368cec..0000000 --- a/tools/libkiwi_py/layout/fnl1_block.py +++ /dev/null @@ -1,56 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase -from libkiwi_py.binary.types.structure import Structure -from libkiwi_py.binary.types.string import String -from libkiwi_py.binary.types.primitive import Primitive -from libkiwi_py.stream.stream_base import StreamBase -from libkiwi_py.utility.util import Util - - -class FontDesc(Structure): - """Font descriptor structure""" - - MEMBERS = [ - Primitive("u32", "offset"), - Primitive("u8", "padding0", arr="[4]") - ] - - -class FNL1Block(BlockBase): - """Font name list block""" - - SIGNATURE = "fnl1" - - def __init__(self, fonts: list[str] = []): - super().__init__(self.SIGNATURE) - self.__pool_size = 0 - - self.add_member(Primitive("u16", "numEntries", value=len(fonts))) - self.add_member(Primitive("u8", "padding0", arr="[2]")) - self.add_member(FontDesc("fontDescs", arr="[]")) - self.add_member(String("fontNames", arr="[]")) - - # Add fonts to pool - for f in fonts: - self.add_font(f) - - def add_font(self, font: str): - """Add font to name list""" - # Add font name to pool - self["fontNames"].value.append(font) - - # Add new font descriptor - desc = FontDesc("dummy", values={"offset": self.__pool_size}) - self["fontDescs"].append(desc) - - # Increase font count - self["numEntries"].value += 1 - - # Update pool size - self.__pool_size += Util.str_len(font, terminator=True) - - def before_build_callback(self): - """Custom block behavior before block contents are serialized""" - # Finalize string pool offsets - for desc in self["fontDescs"]: - # Convert pool-relative offset to section-relative offset - desc["offset"].value += self.offset_of("fontNames") diff --git a/tools/libkiwi_py/layout/lyt1_block.py b/tools/libkiwi_py/layout/lyt1_block.py deleted file mode 100644 index 6988161..0000000 --- a/tools/libkiwi_py/layout/lyt1_block.py +++ /dev/null @@ -1,18 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase -from libkiwi_py.binary.types.primitive import Primitive -from libkiwi_py.binary.types.common import Size - - -class LYT1Block(BlockBase): - """Layout block""" - - SIGNATURE = "lyt1" - - def __init__(self, res): - super().__init__(self.SIGNATURE) - - # Extract from JSON - self.add_member(Primitive("bool", "centered", - value=res.get("centered"))) - self.add_member(Primitive("u8", "padding0", arr="[3]")) - self.add_member(Size("size", values=res.get("size"))) diff --git a/tools/libkiwi_py/layout/mat1_block.py b/tools/libkiwi_py/layout/mat1_block.py deleted file mode 100644 index 928e173..0000000 --- a/tools/libkiwi_py/layout/mat1_block.py +++ /dev/null @@ -1,134 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase -from libkiwi_py.binary.types.structure import Structure -from libkiwi_py.binary.types.primitive import Primitive -from libkiwi_py.binary.types.bitfield import BitField, BitMember -from libkiwi_py.binary.types.string import String -from libkiwi_py.binary.types.common import VEC2 -from libkiwi_py.binary.types.gx import * - - -class AlphaCompare(Structure): - """Material alpha comparison structure""" - - MEMBERS = [ - GXCompare("u8", "comp"), - GXAlphaOp("u8", "op"), - Primitive("u8", "ref0"), - Primitive("u8", "ref1") - ] - - -class ChanCtrl(Structure): - """Material channel control structure""" - - MEMBERS = [ - GXColorSrc("u8", "color_src"), - GXColorSrc("u8", "alpha_src"), - Primitive("u8", "padding0", arr="[2]") - ] - - -class TexSRT(Structure): - """Texture S/R/T (Scale/Rotate/Translate)""" - - MEMBERS = [ - VEC2("translate"), - Primitive("f32", "rotate"), - VEC2("scale") - ] - - -class IndirectStage(Structure): - """Material indirect stage structure""" - - MEMBERS = [ - GXTexCoordID("u8", "tex_coord_gen"), - GXTexMapID("u8", "tex_map"), - GXIndTexScale("u8", "scale_s"), - GXIndTexScale("u8", "scale_t") - ] - - -class BitGXNums(BitField): - """GX "nums" bitfield""" - - MEMBERS = [ - BitMember("num_tex_map", 4), - BitMember("num_tex_srt", 4), - BitMember("num_tex_coord_gen", 4), - BitMember("num_ind_srt", 2), - BitMember("num_ind_stage", 3), - BitMember("has_tev_swap", 1), - BitMember("num_tev_stage", 5), - BitMember("has_chan_ctrl", 1), - BitMember("has_mat_color", 1), - BitMember("has_alpha_comp", 1), - BitMember("has_blend_mode", 1) - ] - - -class MaterialRes(Structure): - """Material structure""" - - MAX_NAME_LEN = 20 - TEV_REG_MAX = 3 - KCOLOR_MAX = 4 - - # TODO: Add optional members somehow (toggled by BitGXNums) - MEMBERS = [ - String("name", c_style=False, maxlen=MAX_NAME_LEN, pad=True), - GXColorS10("tev_colors", arr=f"[{TEV_REG_MAX}]"), - GXColor("tev_k_colors", arr=f"[{KCOLOR_MAX}]"), - BitGXNums("u32", "bit_gx_nums") - ] - - -class MaterialDesc(Structure): - """Material descriptor structure""" - - MEMBERS = [ - Primitive("u32", "offset"), - Primitive("u8", "padding0", arr="[4]") - ] - - -class MAT1Block(BlockBase): - """Material block""" - - SIGNATURE = "mat1" - - def __init__(self, materials=[]): - super().__init__(self.SIGNATURE) - self.__pool_size = 0 - - self.add_member(Primitive("u16", "numEntries")) - self.add_member(Primitive("u8", "padding0", arr="[2]")) - self.add_member(MaterialDesc("matDescs", arr="[]")) - self.add_member(MaterialRes("materials", arr="[]")) - - for res in materials: - self.add_material(res) - - def add_material(self, res): - """Add material to list""" - # Add material - mat = MaterialRes("dummy", values=res) - self["materials"].append(mat) - - # Add new material descriptor - desc = MaterialDesc("dummy", values={"offset": self.__pool_size}) - self["matDescs"].append(desc) - - # Increase material count - self["numEntries"].value += 1 - - # Update pool size - self.__pool_size += mat.byte_size() - pass - - def before_build_callback(self): - """Custom block behavior before block contents are serialized""" - # Finalize material offsets - for desc in self["matDescs"]: - # Convert pool-relative offset to section-relative offset - desc["offset"].value += self.offset_of("materials") diff --git a/tools/libkiwi_py/layout/pae1_block.py b/tools/libkiwi_py/layout/pae1_block.py deleted file mode 100644 index 4d771cf..0000000 --- a/tools/libkiwi_py/layout/pae1_block.py +++ /dev/null @@ -1,10 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase - - -class PAE1Block(BlockBase): - """Pane children (END) block""" - - SIGNATURE = "pae1" - - def __init__(self, children=[]): - super().__init__(self.SIGNATURE) diff --git a/tools/libkiwi_py/layout/pan1_block.py b/tools/libkiwi_py/layout/pan1_block.py deleted file mode 100644 index 5621254..0000000 --- a/tools/libkiwi_py/layout/pan1_block.py +++ /dev/null @@ -1,38 +0,0 @@ -from libkiwi_py.binary.types.primitive import Primitive -from libkiwi_py.binary.types.structure import Structure -from libkiwi_py.binary.types.common import VEC3, VEC2, Size -from libkiwi_py.binary.types.string import String -from libkiwi_py.binary.block.block_base import BlockBase - - -class PaneRes(Structure): - """Pane structure""" - - MAX_NAME_LEN = 16 - MAX_USERDATA_LEN = 8 - - MEMBERS = [ - Primitive("u8", "flags"), - Primitive("u8", "base_position"), - Primitive("u8", "alpha"), - Primitive("u8", "padding0"), - String("name", c_style=False, maxlen=MAX_NAME_LEN, pad=True), - String("user_data", c_style=False, maxlen=MAX_USERDATA_LEN, pad=True), - VEC3("translate"), - VEC3("rotate"), - VEC2("scale"), - Size("size") - ] - - -class PAN1Block(BlockBase): - """Pane block""" - - SIGNATURE = "pan1" - - def __init__(self, res): - super().__init__(self.SIGNATURE) - self.children = [] - - assert "name" in res, "Pane is missing name" - self.add_member(PaneRes("pane", values=res)) diff --git a/tools/libkiwi_py/layout/pas1_block.py b/tools/libkiwi_py/layout/pas1_block.py deleted file mode 100644 index d65316c..0000000 --- a/tools/libkiwi_py/layout/pas1_block.py +++ /dev/null @@ -1,20 +0,0 @@ -from libkiwi_py.layout.pan1_block import PaneRes -from libkiwi_py.binary.block.block_base import BlockBase - - -class PAS1Block(BlockBase): - """Pane children (START) block""" - - SIGNATURE = "pas1" - - def __init__(self, children=[]): - super().__init__(self.SIGNATURE) - self.add_member(PaneRes("panes", arr="[]")) - - for child in children: - self.append_pane(child) - - def append_pane(self, res): - """Append child pane""" - pane = PaneRes("dummy", values=res) - self["panes"].append(pane) diff --git a/tools/libkiwi_py/layout/txl1_block.py b/tools/libkiwi_py/layout/txl1_block.py deleted file mode 100644 index fed0ea7..0000000 --- a/tools/libkiwi_py/layout/txl1_block.py +++ /dev/null @@ -1,56 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase -from libkiwi_py.binary.types.structure import Structure -from libkiwi_py.binary.types.string import String -from libkiwi_py.binary.types.primitive import Primitive -from libkiwi_py.stream.stream_base import StreamBase -from libkiwi_py.utility.util import Util - - -class TextureDesc(Structure): - """Texture descriptor structure""" - - MEMBERS = [ - Primitive("u32", "offset"), - Primitive("u8", "padding0", arr="[4]") - ] - - -class TXL1Block(BlockBase): - """Texture list block""" - - SIGNATURE = "txl1" - - def __init__(self, textures: list[str] = []): - super().__init__(self.SIGNATURE) - self.__pool_size = 0 - - self.add_member(Primitive("u16", "numEntries", value=len(textures))) - self.add_member(Primitive("u8", "padding0", arr="[2]")) - self.add_member(TextureDesc("texDescs", arr="[]")) - self.add_member(String("texNames", arr="[]")) - - # Add textures to pool - for t in textures: - self.add_texture(t) - - def add_texture(self, texture: str): - """Add texture to pool""" - # Add texture name to pool - self["texNames"].value.append(texture) - - # Add new texture descriptor - desc = TextureDesc("dummy", values={"offset": self.__pool_size}) - self["texDescs"].append(desc) - - # Increase texture count - self["numEntries"].value += 1 - - # Update pool size - self.__pool_size += Util.str_len(texture, terminator=True) - - def before_build_callback(self): - """Custom block behavior before block contents are serialized""" - # Finalize string pool offsets - for desc in self["texDescs"]: - # Convert pool-relative offset to section-relative offset - desc["offset"].value += self.offset_of("texNames") diff --git a/tools/libkiwi_py/layout/txt1_block.py b/tools/libkiwi_py/layout/txt1_block.py deleted file mode 100644 index 635e0eb..0000000 --- a/tools/libkiwi_py/layout/txt1_block.py +++ /dev/null @@ -1,41 +0,0 @@ -from libkiwi_py.binary.types.primitive import Primitive -from libkiwi_py.binary.types.common import Size -from libkiwi_py.binary.types.string import WString -from libkiwi_py.binary.types.gx import GXColor -from libkiwi_py.layout.pan1_block import PAN1Block -from libkiwi_py.layout.mat1_block import MAT1Block -from libkiwi_py.layout.fnl1_block import FNL1Block - - -class TXT1Block(PAN1Block): - """Pane block""" - - SIGNATURE = "txt1" - - def __init__(self, res, mats: MAT1Block, fonts: FNL1Block): - super().__init__(res) - self.kind = self.SIGNATURE - - assert "name" in res, "Text box is missing name" - - self.add_member(Primitive("u16", "text_buf_size")) - self.add_member(Primitive("u16", "text_str_size")) - # TODO: Read name from JSON, convert to index using MAT1 - self.add_member(Primitive("u16", "material_index")) - # TODO: Read name from JSON, convert to index using FNL1 - self.add_member(Primitive("u16", "font_index")) - # TODO: This is an enum - self.add_member(Primitive("u8", "text_position")) - # TODO: This is an enum - self.add_member(Primitive("u8", "text_alignment")) - self.add_member(Primitive("u8[2]", "padding0")) - self.add_member(Primitive("u16", "text_str_offset")) - - self.add_member(GXColor("top_color", values=res.get("top_color"))) - self.add_member(GXColor("bot_color", values=res.get("bot_color"))) - - self.add_member(Size("font_size"), res.get("font_size")) - self.add_member(Primitive("f32", "char_space"), res.get("char_space")) - self.add_member(Primitive("f32", "line_space"), res.get("line_space")) - - self.add_member(WString("text", value=res.get("text"), c_style=True)) diff --git a/tools/libkiwi_py/message/cmsg_block.py b/tools/libkiwi_py/message/cmsg_block.py deleted file mode 100644 index 4e1d5cb..0000000 --- a/tools/libkiwi_py/message/cmsg_block.py +++ /dev/null @@ -1,12 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase -from libkiwi_py.binary.block.header_block_base import HeaderBlockBase - - -class CMSGBlock(HeaderBlockBase): - """Message header block""" - - SIGNATURE = "CMSG" - VERSION = 0x0100 # 1.0 - - def __init__(self, blocks: list[BlockBase] = []): - super().__init__(self.SIGNATURE, self.VERSION, blocks) diff --git a/tools/libkiwi_py/message/data_block.py b/tools/libkiwi_py/message/data_block.py deleted file mode 100644 index 4bc712f..0000000 --- a/tools/libkiwi_py/message/data_block.py +++ /dev/null @@ -1,17 +0,0 @@ -from libkiwi_py.binary.types.string import WString -from libkiwi_py.binary.block.block_base import BlockBase - - -class DATABlock(BlockBase): - """Message data (pool) block""" - - SIGNATURE = "DATA" - - def __init__(self, messages: list[str] = []): - super().__init__(self.SIGNATURE) - - self.add_member(WString("pool", arr="[]", value=messages)) - - def add_message(self, message: str): - """Add message to pool""" - self["pool"].value.append(message) diff --git a/tools/libkiwi_py/message/desc_block.py b/tools/libkiwi_py/message/desc_block.py deleted file mode 100644 index 64a830e..0000000 --- a/tools/libkiwi_py/message/desc_block.py +++ /dev/null @@ -1,34 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase -from libkiwi_py.binary.types.primitive import Primitive -from libkiwi_py.message.data_block import DATABlock -from libkiwi_py.utility.util import Util - - -class DESCBlock(BlockBase): - """Message descriptor block""" - - SIGNATURE = "DESC" - - def __init__(self, offsets: list[int] = []): - super().__init__(self.SIGNATURE) - - self.add_member(Primitive("u32", "numMsg", value=len(offsets))) - self.add_member( - Primitive("u32", "msgOffsets", arr="[]", value=offsets)) - - def add_offset(self, offset: int): - """Add message offset to block""" - self["numMsg"].value += 1 - self["msgOffsets"].value.append(offset) - - @staticmethod - def from_data_block(block: DATABlock): - """Generate DESC block from message data""" - offsets = [] - offset_now = 0 - - for msg in block["pool"]: - offsets.append(offset_now) - offset_now += Util.wstr_len(msg, terminator=True) - - return DESCBlock(offsets) diff --git a/tools/libkiwi_py/message/kmsg_block.py b/tools/libkiwi_py/message/kmsg_block.py deleted file mode 100644 index 486080a..0000000 --- a/tools/libkiwi_py/message/kmsg_block.py +++ /dev/null @@ -1,12 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase -from libkiwi_py.binary.block.header_block_base import HeaderBlockBase - - -class KMSGBlock(HeaderBlockBase): - """Message header block""" - - SIGNATURE = "KMSG" - VERSION = 0x0100 # 1.0 - - def __init__(self, blocks: list[BlockBase] = []): - super().__init__(self.SIGNATURE, self.VERSION, blocks) diff --git a/tools/libkiwi_py/params/kprm_block.py b/tools/libkiwi_py/params/kprm_block.py deleted file mode 100644 index e3ddc35..0000000 --- a/tools/libkiwi_py/params/kprm_block.py +++ /dev/null @@ -1,12 +0,0 @@ -from libkiwi_py.binary.block.block_base import BlockBase -from libkiwi_py.binary.block.header_block_base import HeaderBlockBase - - -class KPRMBlock(HeaderBlockBase): - """Param header block""" - - SIGNATURE = "KPRM" - VERSION = 0x0100 # 1.0 - - def __init__(self, blocks: list[BlockBase] = []): - super().__init__(self.SIGNATURE, self.VERSION, blocks) diff --git a/tools/libkiwi_py/stream/block_builder.py b/tools/libkiwi_py/stream/block_builder.py deleted file mode 100644 index a4fc729..0000000 --- a/tools/libkiwi_py/stream/block_builder.py +++ /dev/null @@ -1,37 +0,0 @@ -from libkiwi_py.stream.stream_base import StreamBase - - -class BlockBuilder(StreamBase): - """Block buffer builder""" - - def __init__(self, endian: int): - super().__init__(endian) - self.__data = bytearray() - - def read(self, size: int) -> bytearray: - """Read bytes from stream""" - raise NotImplementedError("BlockBuilder does not support reading") - - def write(self, data: bytearray): - """Write bytes to stream""" - self.__data += data - - def eof(self) -> bool: - """Check whether the stream has hit the end-of-file""" - return False - - def seek(self, origin: int, offset: int): - """Seek the stream position""" - raise NotImplementedError("BlockBuilder does not support seeking") - - def open(self, data: bytearray = bytearray()): - """Open stream (no buffer specified = create one)""" - self.__data = data - - def buffer_data(self) -> bytearray: - """Access buffer data""" - return self.__data - - def buffer_size(self) -> int: - """Access buffer size""" - return len(self.__data) diff --git a/tools/libkiwi_py/stream/file_stream.py b/tools/libkiwi_py/stream/file_stream.py deleted file mode 100644 index 523fd60..0000000 --- a/tools/libkiwi_py/stream/file_stream.py +++ /dev/null @@ -1,100 +0,0 @@ -from libkiwi_py.stream.stream_base import StreamBase, SeekOrigin - - -class OpenMode: - Read, Write, Max = range(3) - - -class DataMode: - Text, Binary, Max = range(3) - - -class FileStream(StreamBase): - """File stream""" - - def __init__(self, endian: int): - super().__init__(endian) - self._path = None - self._open_mode = None - self._data_mode = None - self._file = None - - def read(self, size: int) -> bytes: - """Read bytes from stream""" - assert not self.eof(), "End-of-file while reading" - assert self._open_mode == OpenMode.Read, "Not for this openmode" - - # No file open - if self._file == None: - return bytes() - - result = self._file.read(size) - assert len(result) == size, "End-of-file while reading" - - return result - - def write(self, data: bytes): - """Write bytes to stream""" - assert self._open_mode == OpenMode.Write, "Not for this openmode" - - # No file open - if self._file == None: - return - - self._file.write(data) - - def eof(self) -> bool: - """Check whether the stream has hit the end-of-file""" - if self._open_mode == OpenMode.Write: - return False - - # Try to peek one byte - dummy = self._file.read(1) - if len(dummy) == 0: - return True - - # Undo read operation - self._file.seek(-1, 1) - return False - - def seek(self, origin: int, offset: int): - """Seek the stream position""" - assert origin >= 0 and origin < SeekOrigin.Max - - # No file open - if self._file == None: - return - - self._file.seek(offset, origin) - - def open(self, path: str, open_mode: int, data_mode: int): - """Open stream to file""" - assert open_mode >= 0 and open_mode < OpenMode.Max - assert data_mode >= 0 and data_mode < DataMode.Max - - # Close existing file - if self._file != None: - self.close() - - self._path = path - self._open_mode = open_mode - self._data_mode = data_mode - - self._file = open(self._path, self.__get_py_open_mode()) - - def close(self): - """Close stream""" - if self._file != None: - self._file.close() - self._file = None - - def __get_py_open_mode(self) -> str: - """Get openmode string based on stream setup""" - # Read/write mode - mode = ("r", "w")[self._open_mode] - - # Binary data - if self._data_mode == DataMode.Binary: - mode += "b" - - return mode diff --git a/tools/libkiwi_py/stream/stream_base.py b/tools/libkiwi_py/stream/stream_base.py deleted file mode 100644 index 868ec63..0000000 --- a/tools/libkiwi_py/stream/stream_base.py +++ /dev/null @@ -1,214 +0,0 @@ -from abc import ABC -from struct import pack, unpack - - -class SeekOrigin: - Begin, Current, End, Max = range(4) - - -class Endian: - Little, Big, Max = range(3) - - -class StreamBase(ABC): - """Base stream class - - Only read/write/eof/seek are required for derived class implementations. - However, specialization of other methods is possible if necessary. - """ - - def __init__(self, endian: int): - assert endian >= 0 and endian < Endian.Max - self._endian = endian - - def read(self, size: int) -> bytes: - """Read bytes from stream""" - pass - - def write(self, data: bytes): - """Write bytes to stream""" - pass - - def eof(self) -> bool: - """Check whether the stream has hit the end-of-file""" - pass - - def seek(self, origin: int, offset: int): - """Seek the stream position""" - pass - - def close(self): - """Close stream""" - pass - - def read_s8(self) -> int: - """Read a signed 8-bit integer from the stream.""" - return self.__bytes2int(self.read(1), signed=True) - - def write_s8(self, data: int): - """Write a signed 8-bit integer to the stream.""" - return self.write(self.__int2bytes(data, size=1, signed=True)) - - def read_u8(self) -> int: - """Read a unsigned 8-bit integer from the stream.""" - return self.__bytes2int(self.read(1), signed=False) - - def write_u8(self, data: int): - """Write a unsigned 8-bit integer to the stream.""" - return self.write(self.__int2bytes(data, size=1, signed=False)) - - def read_s16(self) -> int: - """Read a signed 16-bit integer from the stream.""" - return self.__bytes2int(self.read(2), signed=True) - - def write_s16(self, data: int): - """Write a signed 16-bit integer to the stream.""" - return self.write(self.__int2bytes(data, size=2, signed=True)) - - def read_u16(self) -> int: - """Read a unsigned 16-bit integer from the stream.""" - return self.__bytes2int(self.read(2), signed=False) - - def write_u16(self, data: int): - """Write a unsigned 16-bit integer to the stream.""" - return self.write(self.__int2bytes(data, size=2, signed=False)) - - def read_s32(self) -> int: - """Read a signed 32-bit integer from the stream.""" - return self.__bytes2int(self.read(4), signed=True) - - def write_s32(self, data: int): - """Write a signed 32-bit integer to the stream.""" - return self.write(self.__int2bytes(data, size=4, signed=True)) - - def read_u32(self) -> int: - """Read a unsigned 32-bit integer from the stream.""" - return self.__bytes2int(self.read(4), signed=False) - - def write_u32(self, data: int): - """Write a unsigned 32-bit integer to the stream.""" - return self.write(self.__int2bytes(data, size=4, signed=False)) - - def read_f32(self) -> int: - """Read a single-precision floating-point value from the stream.""" - return self.__bytes2dec(self.read(4)) - - def write_f32(self, data: int): - """Write a single-precision floating-point value to the stream.""" - return self.write(self.__dec2bytes(data, size=4)) - - def read_f64(self) -> int: - """Read a double-precision floating-point value from the stream.""" - return self.__bytes2dec(self.read(8)) - - def write_f64(self, data: int): - """Write a double-precision floating-point value to the stream.""" - return self.write(self.__dec2bytes(data, size=8)) - - def read_string(self, maxlen: int = -1) -> str: - """Read a string (ANSI) from the stream.""" - string = "" - i = 0 - - while maxlen < 0 or i < maxlen: - data = self.read(1) - - # Null terminator - if data[0] == 0x00: - break - - # Append new character - try: - string += data.decode("utf-8") - except UnicodeDecodeError: - break - - i += 1 - - return string - - def write_string(self, string: str, maxlen: int = -1, terminate: bool = True): - """Write a string (ANSI) to the stream.""" - if maxlen >= 0: - # Reserve last space for null terminator - term_size = 1 if terminate else 0 - # Truncate if string is too long - string = string[:maxlen - term_size] - - # Write data - try: - self.write(string.encode("utf-8")) - except UnicodeEncodeError: - return - - # Null terminator - if terminate: - self.write_s8(0x00) - - def read_wstring(self, maxlen: int) -> str: - """Read a widechar string (UTF-16) from the stream.""" - string = "" - i = 0 - - while maxlen > 0 and i < maxlen: - data = self.read(2) - - # Null terminator - if data[0] == 0x00 and data[1] == 0x00: - break - - # Append new character - try: - string += data.decode("utf-16") - except UnicodeDecodeError: - break - - i += 1 - - return string - - def write_wstring(self, string: str, maxlen: int = -1, terminate: bool = True): - """Write a widechar string (UTF-16) to the stream.""" - # Truncate if string is too long - if maxlen >= 0: - # Reserve last space for null terminator - term_size = 1 if terminate else 0 - # Truncate if string is too long - string = string[:maxlen - term_size] - - # Write data - try: - self.write(string.encode("utf-16-be")) - except UnicodeEncodeError: - return - - # Null terminator - self.write_u16(0x0000) - - def write_padding(self, size: int): - """Write padding to the stream""" - self.write(bytes([0x00] * size)) - - def __int2bytes(self, data: int, size: int, signed: bool) -> bytes: - """Convert integer value into bytes""" - endian = ("little", "big")[self._endian] - return int.to_bytes(data, length=size, byteorder=endian, signed=signed) - - def __bytes2int(self, data: bytes, signed: bool) -> int: - """Convert bytes into integer value""" - endian = ("little", "big")[self._endian] - return int.from_bytes(data, byteorder=endian, signed=signed) - - def __dec2bytes(self, data: float, size: int) -> bytes: - """Convert decimal value into bytes""" - endian = ("<", ">")[self._endian] - t = "d" if size == 8 else "f" - arr = pack(f"{endian}{t}", data) - return bytes(arr) - - def __bytes2dec(self, data: bytes) -> float: - """Convert bytes into decimal value""" - endian = ("<", ">")[self._endian] - t = "d" if len(data) == 8 else "f" - arr = unpack(f"{endian}{t}", data) - return arr[0] diff --git a/tools/libkiwi_py/utility/util.py b/tools/libkiwi_py/utility/util.py deleted file mode 100644 index 744c0a4..0000000 --- a/tools/libkiwi_py/utility/util.py +++ /dev/null @@ -1,27 +0,0 @@ -class Util: - """General utility functions""" - - @staticmethod - def is_iterable(object) -> bool: - """Determine whether the object is iterable""" - try: - iter(object) - return True - except TypeError: - return False - - @staticmethod - def is_list(object) -> bool: - """Determine whether the object a list""" - return isinstance(object, list) - - @staticmethod - def str_len(string: str, terminator: bool = False): - """String length""" - _len = len(string) - return _len + 1 if terminator else _len - - @staticmethod - def wstr_len(string: str, terminator: bool = False): - """Widechar (UTF-16) string length""" - return Util.str_len(string, terminator) * 2 # wchar_t diff --git a/tools/make_message.py b/tools/make_message.py deleted file mode 100644 index 7646218..0000000 --- a/tools/make_message.py +++ /dev/null @@ -1,138 +0,0 @@ -from argparse import ArgumentParser -from sys import argv -from json import loads -from datetime import datetime -from os import makedirs - -from libkiwi_py.stream.file_stream import FileStream, OpenMode, DataMode -from libkiwi_py.stream.stream_base import Endian -from libkiwi_py.message.desc_block import DESCBlock -from libkiwi_py.message.data_block import DATABlock -from libkiwi_py.message.kmsg_block import KMSGBlock - - -def write_binary(messages: list[str], args): - """Write specified messages to BKMSG binary""" - - try: - strm = FileStream(Endian.Big) - strm.open(args.outfile, OpenMode.Write, DataMode.Binary) - except OSError: - print(f"[FATAL] Could not open BKMSG file for writing: {args.outfile}") - return - - # Header - header_blk = KMSGBlock() - - # Create blocks - data_blk = DATABlock(messages) - desc_blk = DESCBlock.from_data_block(data_blk) - - # Append blocks - header_blk.append_child(desc_blk) - header_blk.append_child(data_blk) - - # Write to file - header_blk.write(strm) - - strm.close() - - -def write_header(message_keys: list[str], args): - """Write C++ header file for use with the BKMSG binary""" - - header_path = args.header - - # Autogenerate header path if not specified - if header_path == None: - # Split up JSON path - last_dir_idx = max(args.infile.rfind("/"), args.infile.rfind("\\")) - file_ext_idx = args.infile.rfind(".") - - file_name = args.infile[last_dir_idx+1:file_ext_idx] - file_dir = args.infile[:last_dir_idx+1] - - # Ideally, "assets/*" maps to "src/*", so for autogenerating this path, - # we rely on the KMSG being somewhere inside the assets folder. - if "assets" not in file_dir: - print("[FATAL] KMSG file not in assets folder! I do not know where to put the header file, please specify using --header.") - return - - # Path to header file - header_dir = file_dir.replace("assets", "src") - header_path = f"{header_dir}BKMSG_{file_name}.h" - - # Create header directory if it doesn't exist - makedirs(header_dir, exist_ok=True) - - with open(header_path, "w+") as f: - # Comment from tool - now = datetime.now() - f.write("/**\n") - f.write( - f" * Auto-generated by make_message.py on {now.strftime('%m/%d/%Y (%H:%M:%S)')}\n") - f.write(" * Don't edit this unless you know what you are doing,\n") - f.write(" * as manual changes will be overwritten on the next build.\n") - f.write(" */\n") - - f.write("\n") - - # Begin header guard - f.write(f"#ifndef BKMSG_{file_name.upper()}_H\n") - f.write(f"#define BKMSG_{file_name.upper()}_H\n") - - f.write("\n") - - f.write(f"enum BKMSG_{file_name} {{\n") - for msg_key in message_keys: - f.write(f" {msg_key},\n") - f.write("};\n") - - f.write("\n") - - # End header guard - f.write(f"#endif\n") - - -def convert_json(args): - """Parse and validate JSON message file, before converting it to binary form""" - - # Attempt to decode JSON data - try: - with open(args.infile, "rb") as f: - json_data = loads(f.read()) - except FileNotFoundError: - print(f"[FATAL] JSON file could not be opened: {args.infile}") - return - except UnicodeDecodeError: - print(f"[FATAL] JSON data could not be decoded: {args.infile}") - return - - # Message data - msg_messages = json_data.get("messages", []) - if len(msg_messages) == 0: - print("[FATAL] No messages exist in the JSON file") - return - - # BKMSG binary - write_binary(msg_messages.values(), args) - # Generate C++ header - write_header(msg_messages.keys(), args) - - -def main(): - # Parse command-line arguments - parser = ArgumentParser() - parser.add_argument("--infile", type=str, required=True, - help="KMSG (JSON) file from which to create message binary") - parser.add_argument("--outfile", type=str, required=True, - help="(BKMSG) Path to output message binary") - parser.add_argument("--header", type=str, required=False, - help="Path to C++ header file") - args = parser.parse_args(argv[1:]) - - convert_json(args) - - -if __name__ == "__main__": - main() diff --git a/tools/ninja_kokeshi.py b/tools/ninja_kokeshi.py new file mode 100644 index 0000000..82aa713 --- /dev/null +++ b/tools/ninja_kokeshi.py @@ -0,0 +1,948 @@ +#!/usr/bin/env python3 + +# =============================================================================# +# # +# Kokeshi Ninja utilities # +# # +# =============================================================================# + +import subprocess +import sys +from glob import glob +from io import StringIO +from os import walk +from os.path import abspath, isdir +from os.path import join as joinpath +from os.path import split, splitext + +from .ninja_syntax import Writer + +# =============================================================================# +# Configuration # +# =============================================================================# + +NINJA_REQUIRED_VERSION = "1.11" +WINDOWS_EXECUTABLE_EXTENSION = ".exe" +CONFIGURE_SCRIPT = "configure.py" +CHECKROM_SCRIPT = "checkrom.py" + +# =============================================================================# +# Utilities # +# =============================================================================# + + +class PathObj: + """Represents a file in the project. + """ + + def __init__(self, parent: "KokeshiProject", path: str): + """Constructor + + Args: + parent (KokeshiProject): Parent project + path (str): File path + """ + + self._parent = parent + self._path = path + self._base_path = splitext(self._path)[0] + self._dir_path = split(self._path)[0] + + def path(self) -> str: + """Gets the path to this file + """ + + return self._path + + def directory(self) -> str: + """Gets the path to the directory containing this file + """ + + return self._dir_path + + def with_extension(self, extension: str) -> str: + """Applies the specified file extension to this file path. + `Ex: "source.cpp" -> "source.o"` + + Args: + extension (str): File extension + """ + + return f"{self._base_path}{extension}" + + +class CompileUnit(PathObj): + """Represents a translation/compilation unit in the project. + """ + + def __init__(self, parent: "KokeshiProject", src_path: str): + """Constructor + + Args: + parent (KokeshiProject): Parent project + src_path (str): Source file path + """ + + super().__init__(parent, src_path) + + def object_path(self) -> str: + """Gets the path to the object file generated by this translation unit + """ + + return joinpath( + self._parent.build_dir, + self.with_extension(".o")) + + def dependency_path(self) -> str: + """Gets the path to the dependency file generated for this translation unit + """ + + return joinpath( + self._parent.build_dir, + self.with_extension(".d")) + + def output_directory(self) -> str: + """Gets the path to the directory containing the object file generated by this translation unit + """ + + return joinpath( + self._parent.build_dir, + self.directory()) + + +class KamekBinary(PathObj): + """Represents a Kamek binary in the project. + """ + + def __init__(self, parent: "KokeshiProject", pack: str, name: str, + static_addr: int = 0): + """Constructor + + Args: + parent (KokeshiProject): Parent project + pack (str): Pack Project target + name (str): Binary name + static_addr (int): Static code destination memory address + """ + + pack_case = pack.capitalize() + + self._rel_path = joinpath(parent.build_dir, f"{name}{pack_case}.bin") + super().__init__(parent, self._rel_path) + + self._pack = pack + self._name = name + self._static_addr = static_addr + + def pack(self) -> str: + """Gets the target Pack Project game of this module + """ + + return self._pack + + def name(self) -> str: + """Gets the name of this module + """ + + return self._name + + def static_addr(self) -> int: + """Gets the virtual address at which the static code should be loaded + """ + + return self._static_addr + + # =============================================================================# + # Build artifacts # + # =============================================================================# + + def static_build_path(self) -> str: + """Gets the path to the static code module generated for this binary + """ + + # Not all Kamek binaries require DOL patches + if self._static_addr == 0: + return None + + return joinpath(self._parent.build_dir, + f"{self._name}{self._pack.capitalize()}Static.dol") + + def rel_build_path(self) -> str: + """Gets the path to the relocatable code module generated for this binary + """ + + return self._rel_path + + def map_build_path(self) -> str: + """Gets the path to the symbol map generated for this binary + """ + + return PathObj(self._parent, self._rel_path).with_extension(".map") + + # =============================================================================# + # Installation artifacts # + # =============================================================================# + + def static_install_path(self) -> str: + """Gets the path to the static code module installed for this binary + """ + + # Not all Kamek binaries require DOL patches + if self._static_addr == 0: + return None + + return joinpath(self._parent.romfs_dir, self._pack, + "DATA", "sys", "main.dol") + + def rel_install_path(self) -> str: + """Gets the path to the relocatable code module installed for this binary + """ + + return joinpath(self._parent.romfs_dir, self._pack, + "DATA", "files", self._parent.modules_dir, + f"{self._name}{self._pack.capitalize()}.bin") + + def map_install_path(self) -> str: + """Gets the path to the symbol map installed for this binary + """ + + return PathObj(self._parent, self.rel_install_path()).with_extension(".map") + + # =============================================================================# + # Misc. attributes # + # =============================================================================# + + def symbols_path(self) -> str: + """Gets the pack to the base DOL symbols required by this binary + """ + + return joinpath(self._parent.base_dir, + f"Symbols{self._pack.capitalize()}.txt") + + def baserom_path(self) -> str: + """Gets the path to the base DOL file patched for this binary + """ + + return joinpath(self._parent.base_dir, + f"Static{self._pack.capitalize()}.dol") + + def linker_flags(self): + """Gets a set of flags for the Kamek linker + """ + + flags = " ".join([ + f"-output-kamek={self._rel_path}", + f"-output-map={self.map_build_path()}", + f"-externals={self.symbols_path()}" + ]) + + if self._static_addr != 0: + flags = " ".join([ + f"-static={hex(self._static_addr)}", + f"-input-dol={self.baserom_path()}", + f"-output-dol={self.static_build_path()}", + flags + ]) + + return flags + + +class KamekLoader(KamekBinary): + """Represents a loader (statically-linked) Kamek binary. + """ + + def __init__(self, parent: "KokeshiProject", pack: str): + """Constructor + + Args: + parent (KokeshiProject): Parent project + pack (str): Pack Project target + """ + + super().__init__( + parent=parent, + pack=pack, + name="Loader", + static_addr=parent.static, + ) + + +class KamekModule(KamekBinary): + """Represents a user module (dynamically-linked) Kamek binary. + """ + + def __init__(self, parent: "KokeshiProject", pack: str, + name: str = None): + """Constructor + + Args: + parent (KokeshiProject): Parent project + pack (str): Pack Project target + name (str): Module name (defaults to "Module") + """ + + super().__init__( + parent=parent, + pack=pack, + name=name or "Module", + ) + + +class Asset(PathObj): + """Represents an asset resource file. + """ + + def __init__(self, parent: "KokeshiProject", pack: str, + path: str): + """Constructor + + Args: + parent (KokeshiProject): Parent project + pack (str): Pack Project target + path (str): Asset file path + """ + + super().__init__(parent, path) + + self._pack = pack + + def pack(self) -> str: + """Gets the target Pack Project game of this asset + """ + + return self._pack + + def install_path(self): + """Gets the ROM path where this asset should be installed + """ + + asset_dir = joinpath(self._parent.assets_dir, self._pack) + + install_dir = joinpath(self._parent.romfs_dir, + self._pack, self._parent.romfs_asset_dir) + + # Asset paths map 1:1 from asset directory to romfs + return self.path().replace(asset_dir, install_dir) + + +def find_files(root_path: str, extensions: list[str] = None) -> list[str]: + """Searches recursively from the root path for all files matching any of the specified file extensions. + If no extensions are specified, all files are allowed. + + Args: + root_path (str): Root search path + extensions (list[str]): File extensions + + Returns: + list[str]: All files matching the specified conditions + """ + + found = [] + + for dirpath, _, filenames in walk(root_path): + for name in filenames: + # Ignore hidden files + if name.startswith("."): + continue + + _, ext = splitext(name) + + if not extensions or ext in extensions: + found.append(joinpath(dirpath, name)) + + # Alphabetical order + found.sort() + return found + + +def find_directories(root_path: str, recursive: bool) -> list[str]: + """Searches from the root path for all subdirectories. + The `recursive` argument controls whether the search recurses into subdirectories. + The root path (`root_path`) is included in the list of results. + + Args: + root (str): Root search path + recursive (bool): Whether to recurse into subdirectories + + Returns: + list[str]: All subdirectories + """ + + found = [root_path] + + for dirpath, dirnames, _ in walk(root_path): + found += [joinpath(dirpath, x) for x in dirnames] + + if not recursive: + break + + return found + + +def emit_compile_unit(writer: Writer, unit: CompileUnit, + cflags_var: str, precompile: list[str] = []): + """Emits a Ninja build target for a translation unit in the project. + + Args: + writer (Writer): Ninja writer + unit (CompileUnit): Source file translation unit + cflags_var (str): Compiler flags to use as the `$cflags` variable + precompile (list[str]): List of precompiled headers this translation unit depends on + """ + + if precompile: + raise ValueError("Precompiled headers not supported yet :(") + + writer.build( + outputs=unit.object_path(), + rule="CC", + inputs=unit.path(), + variables={ + "depfile": unit.dependency_path(), + "cflags": cflags_var, + "outdir": unit.output_directory(), + }, + implicit=precompile + ) + + +def emit_link_binary(writer: Writer, binary: KamekBinary, + units: list[CompileUnit]): + """Emits a Ninja build target for linking a Kamek binary in the project. + + Args: + writer (Writer): Ninja writer + binary (KamekBinary): Kamek binary + units (list[CompileUnit]): Translation/compilation units to include in the binary + """ + + inputs = [unit.object_path() for unit in units] + outputs = [binary.rel_build_path(), binary.map_build_path()] + + # Some Kamek binaries (like the loader) require DOL patches + if binary.static_build_path(): + outputs.append(binary.static_build_path()) + + writer.build( + outputs=outputs, + rule="LD", + inputs=inputs, + variables={ + "ldflags": binary.linker_flags(), + "name": binary.name(), + "pack": binary.pack(), + }, + implicit=binary.symbols_path() + ) + + +def emit_install_binary(writer: Writer, binary: KamekBinary): + """Emits a Ninja build target for installing a Kamek binary in the project. + + Args: + writer (Writer): Ninja writer + binary (KamekBinary): Kamek binary + """ + + # Some Kamek binaries (like the loader) require DOL patches + if binary.static_addr() != 0: + input_bin = binary.static_build_path() + output_bin = binary.static_install_path() + else: + input_bin = binary.rel_build_path() + output_bin = binary.rel_install_path() + + input_map = binary.map_build_path() + output_map = binary.map_install_path() + + writer.build( + outputs=[output_bin, output_map], + rule="install_binary", + inputs=[input_bin, input_map], + variables={ + "bin_in": input_bin, + "bin_out": output_bin, + "map_in": input_map, + "map_out": output_map, + "name": binary.name(), + "pack": binary.pack(), + }, + ) + + +def emit_install_asset(writer: Writer, asset: Asset): + """Emits a Ninja build target for installing an asset in the project. + + Args: + writer (Writer): Ninja writer + asset (Asset): Project asset + """ + + writer.build( + outputs=asset.install_path(), + rule="install_asset", + inputs=asset.path(), + variables={ + "pack": asset.pack(), + }, + ) + +# =============================================================================# +# # +# Project interface # +# # +# =============================================================================# + + +class KokeshiProject: + """Represents the Kokeshi build configuration. + Edit any public members before committing the Ninja build script with `emit()`. + """ + + def __init__(self): + """Constructor + """ + + self.static = 0x80001900 + self.packs = [] + + self.cflags_common = [] + self.cflags_module = [] + self.cflags_debug = [] + self.cflags_release = [] + + self.use_git_commit_hash = False + self._git_commit_hash = "" + + self.assets_dir = "assets" + self.base_dir = "base" + self.docs_dir = "docs" + self.build_dir = "build" + self.romfs_dir = "romfs" + self.romfs_asset_dir = "DATA\\files" + self.modules_dir = "modules" + self.include_dir = "include" + self.library_dir = "lib" + self.loader_dir = "loader" + self.src_dir = "src" + self.tools_dir = "tools" + + self.compiler = "codewarrior\\mwcceppc.exe" + self.linker = "kamek\\Kamek" + + self.source_extensions = [".c", ".cpp", ".cc", ".cxx", ".c++"] + + self._cflags_common_internal = [ + # For Kokeshi-specific code (separate from decomp) + "-D__KOKESHI__", + + "-I-", + "-inline auto", # Auto-inline small functions + "-proc gekko", # Gekko processor + "-Cpp_exceptions off", # Disable C++ exceptions + "-enum int", # Force 4-byte enumerations + "-O4,s", # Max optimization level, focus on small code size + "-use_lmw_stmw on", # Use lmw/stmw for stack frames to save code size + "-fp fmadd", # Use compact floating-point instructions to save code size + "-rostr", # Place strings in rodata + "-RTTI off", # Disable RTTI to save module size + "-sdata 0", # We can't use small data sections in relocatable code + "-sdata2 0", # We can't use small data sections in relocatable code + "-pragma \"cpp1x on\"", # Enable C++11 features + "-DREVOLUTION", # For BTE library + ] + self._cflags_module_internal = [] + self._cflags_debug_internal = [] + self._cflags_release_internal = [ + "-DNDEBUG", + ] + + self._cflags_include_internal = [] + + def emit(self) -> None: + """Emits the Ninja build script (`build.ninja`) + """ + + # Prepare fields that may change from user configuration + self._proc_before_emit() + + output = StringIO() + writer = Writer(output) + + # Variables + self._emit_vars(writer) + + # Rules + self._emit_rules(writer) + + # Build targets + self._emit_targets(writer) + + # Create ninja script + with open("build.ninja", "w+") as f: + f.write(output.getvalue()) + + writer.close() + + def _proc_before_emit(self) -> None: + """Evaluates any variables after user configuration, but before emitting the Ninja build script + """ + + # Create flags for the defined pack(s) + self._cflags_common_internal.extend( + [f"-DPACK_{pack.upper()}" for pack in self.packs]) + + # Include directory priority + include_dir_order = [ + joinpath(self.include_dir, "MSL"), + self.src_dir, + self.include_dir, + self.library_dir, + self.loader_dir, + ] + + # Create compiler flags for includes + for dir in include_dir_order: + for sub_dir in find_directories(dir, recursive=False): + self._cflags_include_internal.append(f"-ir {sub_dir}") + + # Create compiler flag for Git commit hash + if self.use_git_commit_hash: + result = subprocess.run( + ["git", "rev-parse", "--short", "HEAD"], + capture_output=True, + check=True + ) + + short_hash = result.stdout.decode("utf-8").replace("\n", "") + self.cflags_module.append(f"-DGIT_COMMIT_HASH={short_hash}") + + def _emit_vars(self, writer: Writer) -> None: + """Emits the variables section of the Ninja build script + + Args: + writer (Writer): Ninja writer + """ + + writer.comment("==================================================") + writer.comment("Variables") + writer.comment("==================================================") + + # Ninja requirements + writer.comment("Ninja requirements") + writer.variable("ninja_required_version", NINJA_REQUIRED_VERSION) + writer.newline() + + # Directories + writer.comment("Directories") + writer.variable("assets_dir", self.assets_dir) + writer.variable("build_dir", self.build_dir) + writer.variable("base_dir", self.base_dir) + writer.variable("romfs_dir", self.romfs_dir) + writer.variable("romfs_asset_dir", self.romfs_asset_dir) + writer.variable("modules_dir", self.modules_dir) + writer.variable("include_dir", self.include_dir) + writer.variable("library_dir", self.library_dir) + writer.variable("loader_dir", self.loader_dir) + writer.variable("src_dir", self.src_dir) + writer.variable("tools_dir", self.tools_dir) + writer.newline() + + # Tools + writer.comment("Tools") + writer.variable("cc", self._win_tool_cmd(self.compiler)) + writer.variable("ld", self._tool_path(self.linker)) + writer.variable("configure", abspath(CONFIGURE_SCRIPT)) + writer.variable("python", sys.executable) + writer.newline() + + # Flags + writer.comment("Flags") + writer.variable("cflags_common", " ".join([ + *self._cflags_common_internal, + *self.cflags_common, + *self._cflags_include_internal, + ])) + writer.newline() + + writer.variable("cflags_module", " ".join([ + *self._cflags_module_internal, + *self.cflags_module, + ])) + writer.newline() + + writer.variable("cflags_debug", " ".join([ + *self._cflags_debug_internal, + *self.cflags_debug + ])) + writer.newline() + + writer.variable("cflags_release", " ".join([ + *self._cflags_release_internal, + *self.cflags_release + ])) + writer.newline() + + writer.variable("cflags_include", " ".join([ + *self._cflags_include_internal + ])) + writer.newline() + + def _emit_rules(self, writer: Writer) -> None: + """Emits the build rules section of the Ninja build script + + Args: + writer (Writer): Ninja writer + """ + + writer.comment("==================================================") + writer.comment("Rules") + writer.comment("==================================================") + + # # Precompile header file + # writer.comment("Precompile header file") + # writer.rule( + # name="PCH", + # command="$wrapper $cc $cflags -c $in -precompile $out", + # depfile="$depfile", + # deps="gcc", + # description="PRECOMPILE $in", + # ) + # writer.newline() + + # Compile source file + writer.comment("Compile source file") + writer.rule( + name="CC", + command="$cc $cflags -MD -c $in -o $outdir", + depfile="$depfile", + deps="gcc", + description="COMPILE $in", + ) + writer.newline() + + # Link binary + writer.comment("Link binary") + writer.rule( + name="LD", + command="$ld $in $ldflags", + description="LINK $name ($pack)", + ) + writer.newline() + + # Re-run generator script + writer.comment("Re-run generator script") + writer.rule( + name="configure", + command=f"{sys.executable} {abspath(CONFIGURE_SCRIPT)}", + description=f"RUN {CONFIGURE_SCRIPT}", + generator=True, + ) + writer.newline() + + # Check baserom + writer.comment("Check baserom") + writer.rule( + name="checkrom", + command=f"{sys.executable} {abspath(CHECKROM_SCRIPT)} --pack=$pack", + description=f"RUN {CHECKROM_SCRIPT} ($pack)", + ) + writer.newline() + + # Install Kamek binary + writer.comment("Install Kamek binary") + writer.rule( + name="install_binary", + command=self._chain_commands([ + "cp -f $bin_in $bin_out", + "cp -f $map_in $map_out", + ]), + description="INSTALL $name ($pack)", + ) + writer.newline() + + # Install Kamek binary + writer.comment("Install asset") + writer.rule( + name="install_asset", + command=f"cp -f $in $out", + description="INSTALL $in ($pack)", + ) + writer.newline() + + # # Remove all build artifacts + # writer.comment("Install build artifacts") + # writer.rule( + # name="install", + # command=f"cp ", + # description=f"INSTALL $pack" + # ) + # writer.newline() + + # # Safety check!!! rm -rf is very scary :( + # if (not self.build_dir or isabs(self.build_dir) + # or any([c in self.build_dir for c in ('$', '*', '\"')])): + # raise ValueError("Build directory path is certainly unsafe for rm") + + def _emit_targets(self, writer: Writer) -> None: + """Emits the build targets section of the Ninja build script + + Args: + writer (Writer): Ninja writer + """ + + writer.comment("==================================================") + writer.comment("Targets") + writer.comment("==================================================") + + # Re-run generator script + writer.comment("Re-run generator script") + writer.build( + outputs="build.ninja", + rule="configure", + implicit=[ + "$configure", + joinpath("$tools_dir", "ninja_syntax.py"), + joinpath("$tools_dir", "ninja_kokeshi.py") + ] + ) + writer.newline() + + # # Remove all build artifacts + # writer.comment("Remove all build artifacts") + # writer.build( + # outputs="clean", + # rule="phony", + # ) + # writer.newline() + + # =============================================================================# + # Loader source code + loader_units = [CompileUnit(self, file) for file in + find_files(self.loader_dir, self.source_extensions)] + + writer.comment("Loader (static) source code") + for unit in loader_units: + emit_compile_unit(writer, unit, + cflags_var="$cflags_common") + writer.newline() + + # =============================================================================# + # Module source code + library_units = [CompileUnit(self, file) for file in + find_files(self.library_dir, self.source_extensions)] + + src_units = [CompileUnit(self, file) for file in + find_files(self.src_dir, self.source_extensions)] + + module_units = library_units + src_units + + writer.comment("Module source code") + for unit in module_units: + emit_compile_unit(writer, unit, + cflags_var="$cflags_common $cflags_module") + writer.newline() + + # =============================================================================# + # Linking and installation + for pack in self.packs: + # Check baserom + writer.comment(f"Check baserom ({pack})") + # writer.build() + writer.newline() + + # Link Kokeshi loader + writer.comment(f"Link Kokeshi loader ({pack})") + loader_obj = KamekLoader(self, pack) + emit_link_binary(writer, loader_obj, loader_units) + writer.newline() + + # Link user module + writer.comment(f"Link user module ({pack})") + module_obj = KamekModule(self, pack) + emit_link_binary(writer, module_obj, module_units) + writer.newline() + + # Install binaries + writer.comment(f"Install binaries ({pack})") + emit_install_binary(writer, loader_obj) + emit_install_binary(writer, module_obj) + writer.newline() + + # =============================================================================# + # Project assets + for pack in self.packs: + assets = [Asset(self, pack, file) + for file in find_files(joinpath(self.assets_dir, pack))] + + # Install assets + writer.comment(f"Install assets ({pack})") + for asset in assets: + emit_install_asset(writer, asset) + writer.newline() + + def _tool_path(self, name: str) -> str: + """Creates a relative, platform-agnostic path to an executable in the tools directory + + Args: + name (str): Tool name (no file extension) + + Returns: + str: Tool path for the current platform + """ + + path = joinpath(self.tools_dir, name) + is_windows = sys.platform.startswith("win32") + + if is_windows: + path = f"{path}{WINDOWS_EXECUTABLE_EXTENSION}" + + return path + + def _win_tool_cmd(self, name: str) -> str: + """Creates a command to run a Windows executable in the tools directory + + Args: + name (str): Tool name + + Returns: + str: Wrapper path + """ + + path = joinpath(self.tools_dir, name) + is_windows = path.endswith(WINDOWS_EXECUTABLE_EXTENSION) + + if not is_windows: + return path + + # Windows can run tools natively + if sys.platform.startswith("win32"): + return path + + # Mac systems use wine-crossover + if sys.platform.startswith("darwin"): + return f"wine {path}" + + # Linux systems use wibo + if sys.platform.startswith("linux"): + return f"wibo {path}" + + assert False, f"Unknown platform: {sys.platform}" + + def _chain_commands(self, commands: list[str]) -> str: + """Creates a single Ninja `command` from multiple shell commands + + Args: + commands (list[str]): Shell commands to execute + + Returns: + str: Single command + """ + + command = " && ".join(commands) + + # Windows requires a subshell + if sys.platform.startswith("win32"): + command = f"cmd /c {command}" + + return command diff --git a/tools/ninja_syntax.py b/tools/ninja_syntax.py new file mode 100644 index 0000000..2aa8456 --- /dev/null +++ b/tools/ninja_syntax.py @@ -0,0 +1,231 @@ +#!/usr/bin/python + +# Copyright 2011 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Python module for generating .ninja files. + +Note that this is emphatically not a required piece of Ninja; it's +just a helpful utility for build-file-generation systems that already +use Python. +""" + +import re +import textwrap +from io import TextIOWrapper +from typing import Dict, List, Match, Optional, Tuple, Union + +def escape_path(word: str) -> str: + return word.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:') + +class Writer(object): + def __init__(self, output: TextIOWrapper, width: int = 78) -> None: + self.output = output + self.width = width + + def newline(self) -> None: + self.output.write('\n') + + def comment(self, text: str) -> None: + for line in textwrap.wrap(text, self.width - 2, break_long_words=False, + break_on_hyphens=False): + self.output.write('# ' + line + '\n') + + def variable( + self, + key: str, + value: Optional[Union[bool, int, float, str, List[str]]], + indent: int = 0, + ) -> None: + if value is None: + return + if isinstance(value, list): + value = ' '.join(filter(None, value)) # Filter out empty strings. + self._line('%s = %s' % (key, value), indent) + + def pool(self, name: str, depth: int) -> None: + self._line('pool %s' % name) + self.variable('depth', depth, indent=1) + + def rule( + self, + name: str, + command: str, + description: Optional[str] = None, + depfile: Optional[str] = None, + generator: bool = False, + pool: Optional[str] = None, + restat: bool = False, + rspfile: Optional[str] = None, + rspfile_content: Optional[str] = None, + deps: Optional[Union[str, List[str]]] = None, + ) -> None: + self._line('rule %s' % name) + self.variable('command', command, indent=1) + if description: + self.variable('description', description, indent=1) + if depfile: + self.variable('depfile', depfile, indent=1) + if generator: + self.variable('generator', '1', indent=1) + if pool: + self.variable('pool', pool, indent=1) + if restat: + self.variable('restat', '1', indent=1) + if rspfile: + self.variable('rspfile', rspfile, indent=1) + if rspfile_content: + self.variable('rspfile_content', rspfile_content, indent=1) + if deps: + self.variable('deps', deps, indent=1) + + def build( + self, + outputs: Union[str, List[str]], + rule: str, + inputs: Optional[Union[str, List[str]]] = None, + implicit: Optional[Union[str, List[str]]] = None, + order_only: Optional[Union[str, List[str]]] = None, + variables: Optional[ + Union[ + List[Tuple[str, Optional[Union[str, List[str]]]]], + Dict[str, Optional[Union[str, List[str]]]], + ] + ] = None, + implicit_outputs: Optional[Union[str, List[str]]] = None, + pool: Optional[str] = None, + dyndep: Optional[str] = None, + ) -> List[str]: + outputs = as_list(outputs) + out_outputs = [escape_path(x) for x in outputs] + all_inputs = [escape_path(x) for x in as_list(inputs)] + + if implicit: + implicit = [escape_path(x) for x in as_list(implicit)] + all_inputs.append('|') + all_inputs.extend(implicit) + if order_only: + order_only = [escape_path(x) for x in as_list(order_only)] + all_inputs.append('||') + all_inputs.extend(order_only) + if implicit_outputs: + implicit_outputs = [escape_path(x) + for x in as_list(implicit_outputs)] + out_outputs.append('|') + out_outputs.extend(implicit_outputs) + + self._line('build %s: %s' % (' '.join(out_outputs), + ' '.join([rule] + all_inputs))) + if pool is not None: + self._line(' pool = %s' % pool) + if dyndep is not None: + self._line(' dyndep = %s' % dyndep) + + if variables: + if isinstance(variables, dict): + iterator = iter(variables.items()) + else: + iterator = iter(variables) + + for key, val in iterator: + self.variable(key, val, indent=1) + + return outputs + + def include(self, path: str) -> None: + self._line('include %s' % path) + + def subninja(self, path: str) -> None: + self._line('subninja %s' % path) + + def default(self, paths: Union[str, List[str]]) -> None: + self._line('default %s' % ' '.join(as_list(paths))) + + def _count_dollars_before_index(self, s: str, i: int) -> int: + """Returns the number of '$' characters right in front of s[i].""" + dollar_count = 0 + dollar_index = i - 1 + while dollar_index > 0 and s[dollar_index] == '$': + dollar_count += 1 + dollar_index -= 1 + return dollar_count + + def _line(self, text: str, indent: int = 0) -> None: + """Write 'text' word-wrapped at self.width characters.""" + leading_space = ' ' * indent + while len(leading_space) + len(text) > self.width: + # The text is too wide; wrap if possible. + + # Find the rightmost space that would obey our width constraint and + # that's not an escaped space. + available_space = self.width - len(leading_space) - len(' $') + space = available_space + while True: + space = text.rfind(' ', 0, space) + if (space < 0 or + self._count_dollars_before_index(text, space) % 2 == 0): + break + + if space < 0: + # No such space; just use the first unescaped space we can find. + space = available_space - 1 + while True: + space = text.find(' ', space + 1) + if (space < 0 or + self._count_dollars_before_index(text, space) % 2 == 0): + break + if space < 0: + # Give up on breaking. + break + + self.output.write(leading_space + text[0:space] + ' $\n') + text = text[space+1:] + + # Subsequent lines are continuations, so indent them. + leading_space = ' ' * (indent+2) + + self.output.write(leading_space + text + '\n') + + def close(self) -> None: + self.output.close() + + +def as_list(input: Optional[Union[str, List[str]]]) -> List[str]: + if input is None: + return [] + if isinstance(input, list): + return input + return [input] + + +def escape(string: str) -> str: + """Escape a string such that it can be embedded into a Ninja file without + further interpretation.""" + assert '\n' not in string, 'Ninja syntax does not allow newlines' + # We only have one special metacharacter: '$'. + return string.replace('$', '$$') + + +def expand(string: str, vars: Dict[str, str], local_vars: Dict[str, str] = {}) -> str: + """Expand a string containing $vars as Ninja would. + + Note: doesn't handle the full Ninja variable syntax, but it's enough + to make configure.py's use of it work. + """ + def exp(m: Match[str]) -> str: + var = m.group(1) + if var == '$': + return '$' + return local_vars.get(var, vars.get(var, '')) + return re.sub(r'\$(\$|\w*)', exp, string) diff --git a/tools/workbench/.gitignore b/tools/workbench/.gitignore new file mode 100644 index 0000000..ba7a514 --- /dev/null +++ b/tools/workbench/.gitignore @@ -0,0 +1,428 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates +*.env + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ + +[Dd]ebug/x64/ +[Dd]ebugPublic/x64/ +[Rr]elease/x64/ +[Rr]eleases/x64/ +bin/x64/ +obj/x64/ + +[Dd]ebug/x86/ +[Dd]ebugPublic/x86/ +[Rr]elease/x86/ +[Rr]eleases/x86/ +bin/x86/ +obj/x86/ + +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +[Aa][Rr][Mm]64[Ee][Cc]/ +bld/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Build results on 'Bin' directories +**/[Bb]in/* +# Uncomment if you have tasks that rely on *.refresh files to move binaries +# (https://github.com/github/gitignore/pull/3736) +#!**/[Bb]in/*.refresh + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* +*.trx + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Approval Tests result files +*.received.* + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.idb +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +# but not Directory.Build.rsp, as it configures directory-level build defaults +!Directory.Build.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +**/.paket/paket.exe +paket-files/ + +# FAKE - F# Make +**/.fake/ + +# CodeRush personal settings +**/.cr/personal + +# Python Tools for Visual Studio (PTVS) +**/__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +#tools/** +#!tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog +MSBuild_Logs/ + +# AWS SAM Build and Temporary Artifacts folder +.aws-sam + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +**/.mfractor/ + +# Local History for Visual Studio +**/.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +**/.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp \ No newline at end of file diff --git a/tools/workbench/LibWorkBench/API/JSystem/JMessage/MsgResFile.cs b/tools/workbench/LibWorkBench/API/JSystem/JMessage/MsgResFile.cs new file mode 100644 index 0000000..46b3598 --- /dev/null +++ b/tools/workbench/LibWorkBench/API/JSystem/JMessage/MsgResFile.cs @@ -0,0 +1,63 @@ +using LibWorkBench.API.Pack; +using LibWorkBench.Attributes; +using LibWorkBench.Formats.JSystem; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Data; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types; +using LibWorkBench.Formats.JSystem.JMessage.Tag; + +namespace LibWorkBench.API.JSystem.JMessage +{ + /// + /// Message resource (BMG) + /// + [ResourceProfile(name: "msgres", extension: "bmg")] + public sealed class MsgResFile : TJSystemResource + { + /// + /// Tag processor to use for special character sequences in messages + /// + public TagProcessorBase TagProcessor { get; set; } = new RPSysTagProcessor(); + + /// + /// Text encoding format + /// + public TextEncoding Encoding + { + get => DataModel.Encoding; + set { DataModel.Encoding = value; } + } + + /// + /// Message info group ID + /// + public ushort GroupID + { + get => DataModel.GroupID; + set { DataModel.GroupID = value; } + } + + /// + /// Message ID format + /// + public Form Form + { + get => DataModel.Form; + set { DataModel.Form = value; } + } + + /// + /// Message ID supplemental format + /// + public FormSupplement FormSupplement + { + get => DataModel.FormSupplement; + set { DataModel.FormSupplement = value; } + } + + /// + /// Messages contained within this resource + /// + public List Messages => DataModel.Messages; + } +} diff --git a/tools/workbench/LibWorkBench/API/NW4R/LayoutLib/AnimationFile.cs b/tools/workbench/LibWorkBench/API/NW4R/LayoutLib/AnimationFile.cs new file mode 100644 index 0000000..5475ba7 --- /dev/null +++ b/tools/workbench/LibWorkBench/API/NW4R/LayoutLib/AnimationFile.cs @@ -0,0 +1,15 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Data; + +namespace LibWorkBench.API.NW4R.LayoutLib +{ + /// + /// Layout animation file (BRLAN) + /// + [ResourceProfile(name: "lytanim", extension: "brlan")] + public sealed class AnimationFile : TNW4RResource + { + } +} diff --git a/tools/workbench/LibWorkBench/API/NW4R/LayoutLib/LayoutFile.cs b/tools/workbench/LibWorkBench/API/NW4R/LayoutLib/LayoutFile.cs new file mode 100644 index 0000000..6ef356e --- /dev/null +++ b/tools/workbench/LibWorkBench/API/NW4R/LayoutLib/LayoutFile.cs @@ -0,0 +1,59 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; + +namespace LibWorkBench.API.NW4R.LayoutLib +{ + /// + /// UI layout file (BRLYT) + /// + [ResourceProfile(name: "layout", extension: "brlyt")] + public sealed class LayoutFile : TNW4RResource + { + /// + /// Position origin type + /// + public OriginType OriginType + { + get => DataModel.OriginType; + set { DataModel.OriginType = value; } + } + + /// + /// Size of this layout + /// + public Size Size + { + get => DataModel.Size; + set { DataModel.Size = value; } + } + + /// + /// Root of the pane hierarchy + /// + public Pane RootPane + { + get => DataModel.RootPane; + set { DataModel.RootPane = value; } + } + + /// + /// Root of the group hierarchy + /// + public Group RootGroup + { + get => DataModel.RootGroup; + set { DataModel.RootGroup = value; } + } + + /// + /// Pane materials + /// + public List Materials + { + get => DataModel.Materials; + } + } +} diff --git a/tools/workbench/LibWorkBench/API/Pack/Common/MapDataFile.cs b/tools/workbench/LibWorkBench/API/Pack/Common/MapDataFile.cs new file mode 100644 index 0000000..cda8eac --- /dev/null +++ b/tools/workbench/LibWorkBench/API/Pack/Common/MapDataFile.cs @@ -0,0 +1,15 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Core.Models; +using LibWorkBench.Formats.Pack.Common.MapData.Binary; +using LibWorkBench.Formats.Pack.Common.MapData.Data; + +namespace LibWorkBench.API.Pack.Common +{ + /// + /// Pack Mapdata (PMP) file + /// + [ResourceProfile(name: "mapdata", extension: "pmp")] + public sealed class MapDataFile : TResource + { + } +} diff --git a/tools/workbench/LibWorkBench/API/Pack/Party/Pnp/LevelTableFile.cs b/tools/workbench/LibWorkBench/API/Pack/Party/Pnp/LevelTableFile.cs new file mode 100644 index 0000000..661b95f --- /dev/null +++ b/tools/workbench/LibWorkBench/API/Pack/Party/Pnp/LevelTableFile.cs @@ -0,0 +1,23 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Core.Models; +using LibWorkBench.Formats.Pack.Party.Pnp.LevelTable; +using LibWorkBench.Formats.Pack.Party.Pnp.LevelTable.Types; + +namespace LibWorkBench.API.Pack.Party.Pnp +{ + /// + /// Table Tennis level table file + /// + [ResourceProfile(name: "pnplevel", extension: "bin")] + public sealed class LevelTableFile : TResource + { + /// + /// Level table entries + /// + public List Levels + { + get => DataModel.Levels; + set { DataModel.Levels = value; } + } + } +} diff --git a/tools/workbench/LibWorkBench/API/Pack/Party/Pnp/RallyLevelUpTableFile.cs b/tools/workbench/LibWorkBench/API/Pack/Party/Pnp/RallyLevelUpTableFile.cs new file mode 100644 index 0000000..4348a2c --- /dev/null +++ b/tools/workbench/LibWorkBench/API/Pack/Party/Pnp/RallyLevelUpTableFile.cs @@ -0,0 +1,23 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Core.Models; +using LibWorkBench.Formats.Pack.Party.Pnp.RallyLevelUpTable; +using LibWorkBench.Formats.Pack.Party.Pnp.RallyLevelUpTable.Types; + +namespace LibWorkBench.API.Pack.Party.Pnp +{ + /// + /// Table Tennis rally level-up table file + /// + [ResourceProfile(name: "pnprally", extension: "bin")] + public sealed class RallyLevelUpTableFile : TResource + { + /// + /// Level-up table entries + /// + public List Levels + { + get => DataModel.Levels; + set { DataModel.Levels = value; } + } + } +} diff --git a/tools/workbench/LibWorkBench/API/Pack/RPSysTagProcessor.cs b/tools/workbench/LibWorkBench/API/Pack/RPSysTagProcessor.cs new file mode 100644 index 0000000..5762661 --- /dev/null +++ b/tools/workbench/LibWorkBench/API/Pack/RPSysTagProcessor.cs @@ -0,0 +1,37 @@ +using LibWorkBench.Formats.JSystem.JMessage.Tag; + +namespace LibWorkBench.API.Pack +{ + /// + /// Tag processor for tag codes used by the original Pack Project (RP) games + /// + public sealed class RPSysTagProcessor : TagProcessorBase + { + /// + /// Number of variadic argument tags to support + /// + private const uint TAG_VAR_NUM = 10; + + /// + /// Constructor + /// + public RPSysTagProcessor() + { + for (uint i = 0; i < TAG_VAR_NUM; i++) + { + RegisterTag(0x00_0000 + i, $"VAR_{i}"); + } + + RegisterTag(0x01_0000, "GRAMMAR_BEGIN_SENTENCE"); + + RegisterTag(0x02_0000, "WINDOW_DELAY"); + RegisterTag(0x02_0001, "WINDOW_DEFAULT_CURSOR"); + RegisterTag(0x02_0002, "WINDOW_CANCEL_SE"); + RegisterTag(0x02_0003, "WINDOW_ALIGN"); + + RegisterTag(0xFF_0000, "COMMON_FONT_COLOR"); + RegisterTag(0xFF_0001, "COMMON_FONT_SIZE"); + RegisterTag(0xFF_0007, "COMMON_RUBY"); + } + } +} diff --git a/tools/workbench/LibWorkBench/API/Pack/WS2TagProcessor.cs b/tools/workbench/LibWorkBench/API/Pack/WS2TagProcessor.cs new file mode 100644 index 0000000..5b684b0 --- /dev/null +++ b/tools/workbench/LibWorkBench/API/Pack/WS2TagProcessor.cs @@ -0,0 +1,43 @@ +using LibWorkBench.Formats.JSystem.JMessage.Tag; + +namespace LibWorkBench.API.Pack +{ + /// + /// Tag processor for tag codes used by Wii Sports Resort (WS2) + /// + public sealed class WS2TagProcessor : TagProcessorBase + { + /// + /// Number of variadic argument tags to support + /// + private const uint TAG_VAR_NUM = 10; + + /// + /// Constructor + /// + public WS2TagProcessor() + { + for (uint i = 0; i < TAG_VAR_NUM; i++) + { + RegisterTag(0x00_0000 + i, $"VAR_{i}"); + } + + RegisterTag(0x01_0000, "GRAMMAR_BEGIN_SENTENCE"); + + RegisterTag(0x05_0000, "T05_0000"); + + RegisterTag(0x0A_0000, "T0A_0000"); + RegisterTag(0x0A_0001, "T0A_0001"); + RegisterTag(0x0A_0002, "T0A_0002"); + RegisterTag(0x0A_0003, "T0A_0003"); + RegisterTag(0x0A_0004, "T0A_0004"); + RegisterTag(0x0A_0005, "T0A_0005"); + RegisterTag(0x0A_0006, "T0A_0006"); + RegisterTag(0x0A_0007, "T0A_0007"); + + RegisterTag(0xFF_0000, "COMMON_FONT_COLOR"); + RegisterTag(0xFF_0001, "COMMON_FONT_SIZE"); + RegisterTag(0xFF_0007, "COMMON_RUBY"); + } + } +} diff --git a/tools/workbench/LibWorkBench/Attributes/BinaryBlockProfileAttribute.cs b/tools/workbench/LibWorkBench/Attributes/BinaryBlockProfileAttribute.cs new file mode 100644 index 0000000..05da9fb --- /dev/null +++ b/tools/workbench/LibWorkBench/Attributes/BinaryBlockProfileAttribute.cs @@ -0,0 +1,31 @@ +namespace LibWorkBench.Attributes +{ + /// + /// Attribute for describing binary block types + /// + [AttributeUsage(AttributeTargets.Class)] + public sealed class BinaryBlockProfileAttribute : Attribute + { + /// + /// Signature ("magic") used to identify this block in binary files + /// + public readonly string Signature; + + /// + /// Minimum model version required for this block + /// + public readonly uint MinVersion; + + /// + /// Constructor + /// + /// Block type signature + /// Minimum required model version + public BinaryBlockProfileAttribute(string signature, + uint minVersion = 0) + { + Signature = signature; + MinVersion = minVersion; + } + } +} diff --git a/tools/workbench/LibWorkBench/Attributes/BinaryModelProfileAttribute.cs b/tools/workbench/LibWorkBench/Attributes/BinaryModelProfileAttribute.cs new file mode 100644 index 0000000..016bb1b --- /dev/null +++ b/tools/workbench/LibWorkBench/Attributes/BinaryModelProfileAttribute.cs @@ -0,0 +1,39 @@ +namespace LibWorkBench.Attributes +{ + /// + /// Attribute for describing binary model types + /// + [AttributeUsage(AttributeTargets.Class)] + public sealed class BinaryModelProfileAttribute : Attribute + { + /// + /// Signature ("magic") used to identify this model in binary files + /// + public readonly string Signature; + + /// + /// Versions of this model that are supported by WorkBench + /// + public readonly uint[] Versions; + + /// + /// Required byte-alignment for blocks in this model + /// + public readonly ulong Alignment; + + /// + /// Constructor + /// + /// Model type signature + /// Supported model versions + /// Required byte-alignment for blocks + public BinaryModelProfileAttribute(string signature, + uint[]? versions = null, + ulong alignment = 4) + { + Signature = signature; + Versions = versions != null ? versions : []; + Alignment = alignment; + } + } +} diff --git a/tools/workbench/LibWorkBench/Attributes/Details/ProfileProxy.cs b/tools/workbench/LibWorkBench/Attributes/Details/ProfileProxy.cs new file mode 100644 index 0000000..3c528f0 --- /dev/null +++ b/tools/workbench/LibWorkBench/Attributes/Details/ProfileProxy.cs @@ -0,0 +1,51 @@ +using LibWorkBench.Exceptions; +using System.Reflection; + +namespace LibWorkBench.Attributes.Details +{ + /// + /// Profile accessor + /// + /// Profile attribute type + public abstract class ProfileProxy + where TProfile : Attribute + { + /// + /// Accesses the held profile + /// + public TProfile Profile => GetProfile(); + + /// + /// Accesses the held profile + /// + /// Profile instance + public TProfile GetProfile() => GetAttribute(GetType()); + + /// + /// Accesses the held profile (static) + /// + /// Self type (needed for derived type access) + /// Profile instance + public static TProfile GetProfileStatic() + => GetAttribute(typeof(THolder)); + + /// + /// Accesses the held attribute + /// + /// Derived self type + /// Attribute instance + private static TProfile GetAttribute(Type selfType) + { + TProfile? attribute = selfType.GetCustomAttribute(); + + if (attribute == null) + { + throw new MissingAttributeException( + $"Please register a ${typeof(TProfile).Name} " + + $"with the class ${selfType.FullName}"); + } + + return attribute; + } + } +} diff --git a/tools/workbench/LibWorkBench/Attributes/ResourceProfileAttribute.cs b/tools/workbench/LibWorkBench/Attributes/ResourceProfileAttribute.cs new file mode 100644 index 0000000..0dcf5c0 --- /dev/null +++ b/tools/workbench/LibWorkBench/Attributes/ResourceProfileAttribute.cs @@ -0,0 +1,29 @@ +namespace LibWorkBench.Attributes +{ + /// + /// Attribute for describing resource types + /// + [AttributeUsage(AttributeTargets.Class)] + public sealed class ResourceProfileAttribute : Attribute + { + /// + /// Internal name of this resource + /// + public readonly string Name; + + /// + /// File extension associated with this resource + /// + public readonly string Extension; + + /// + /// Constructor + /// + /// Resource name + public ResourceProfileAttribute(string name, string extension) + { + Name = name; + Extension = extension; + } + } +} diff --git a/tools/workbench/LibWorkBench/Converters/Details/HexJsonConverterImpl.cs b/tools/workbench/LibWorkBench/Converters/Details/HexJsonConverterImpl.cs new file mode 100644 index 0000000..ae4020e --- /dev/null +++ b/tools/workbench/LibWorkBench/Converters/Details/HexJsonConverterImpl.cs @@ -0,0 +1,43 @@ +using LibWorkBench.Utility; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Converters.Details +{ + /// + /// Base class for hexadecimal number JSON converters + /// + public class HexJsonConverterImpl : JsonConverter + where T : unmanaged + { + /// + /// Deserializes a hexadecimal number value from JSON + /// + /// JSON file reader + /// Destination type + /// Configuration for the deserializer + /// Number value + public override T Read(ref Utf8JsonReader reader, Type t, JsonSerializerOptions options) + { + string? str = reader.GetString(); + if (str == null) + { + return default; + } + + return Util.FromHex(str); + } + + /// + /// Serializes a number value to JSON as its hexadecimal representation + /// + /// JSON file writer + /// Numeric value + /// Configuration for the serializer + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + { + string hex = Util.ToHex(value, delimit: false, prefix: true); + writer.WriteStringValue(hex); + } + } +} diff --git a/tools/workbench/LibWorkBench/Converters/HexByteArrayJsonConverter.cs b/tools/workbench/LibWorkBench/Converters/HexByteArrayJsonConverter.cs new file mode 100644 index 0000000..df73452 --- /dev/null +++ b/tools/workbench/LibWorkBench/Converters/HexByteArrayJsonConverter.cs @@ -0,0 +1,42 @@ +using LibWorkBench.Utility; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Converters +{ + /// + /// JSON converter for byte arrays (saves as hex bytes instead of Base64) + /// + public sealed class HexByteArrayJsonConverter : JsonConverter + { + /// + /// Deserializes a byte array from JSON + /// + /// JSON file reader + /// Destination type + /// Configuration for the deserializer + /// Byte array + public override byte[]? Read(ref Utf8JsonReader reader, Type t, JsonSerializerOptions options) + { + string? str = reader.GetString(); + if (str == null) + { + return null; + } + + return Util.FromHex(str); + } + + /// + /// Serializes a byte array to JSON + /// + /// JSON file writer + /// Byte array + /// Configuration for the serializer + public override void Write(Utf8JsonWriter writer, byte[] value, JsonSerializerOptions options) + { + string str = Util.ToHex(value, prefix: true); + writer.WriteStringValue(str); + } + } +} diff --git a/tools/workbench/LibWorkBench/Converters/HexIntJsonConverterImplement.cs b/tools/workbench/LibWorkBench/Converters/HexIntJsonConverterImplement.cs new file mode 100644 index 0000000..8e245d3 --- /dev/null +++ b/tools/workbench/LibWorkBench/Converters/HexIntJsonConverterImplement.cs @@ -0,0 +1,54 @@ +using LibWorkBench.Converters.Details; + +namespace LibWorkBench.Converters +{ + /// + /// JSON hexadecimal converter for unsigned 8-bit integers + /// + public sealed class HexUInt8JsonConverter : HexJsonConverterImpl + { + } + /// + /// JSON hexadecimal converter for unsigned 16-bit integers + /// + public sealed class HexUInt16JsonConverter : HexJsonConverterImpl + { + } + /// + /// JSON hexadecimal converter for unsigned 32-bit integers + /// + public sealed class HexUInt32JsonConverter : HexJsonConverterImpl + { + } + /// + /// JSON hexadecimal converter for unsigned 64-bit integers + /// + public sealed class HexUInt64JsonConverter : HexJsonConverterImpl + { + } + + /// + /// JSON hexadecimal converter for signed 8-bit integers + /// + public sealed class HexInt8JsonConverter : HexJsonConverterImpl + { + } + /// + /// JSON hexadecimal converter for signed 16-bit integers + /// + public sealed class HexInt16JsonConverter : HexJsonConverterImpl + { + } + /// + /// JSON hexadecimal converter for signed 32-bit integers + /// + public sealed class HexInt32JsonConverter : HexJsonConverterImpl + { + } + /// + /// JSON hexadecimal converter for signed 64-bit integers + /// + public sealed class HexInt64JsonConverter : HexJsonConverterImpl + { + } +} diff --git a/tools/workbench/LibWorkBench/Core/IUseBinary.cs b/tools/workbench/LibWorkBench/Core/IUseBinary.cs new file mode 100644 index 0000000..5f77c0f --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/IUseBinary.cs @@ -0,0 +1,22 @@ +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Core +{ + /// + /// Interface for objects serialized as binary data + /// + public interface IUseBinary + { + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public abstract void Read(ReadStream reader); + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public abstract void Write(WriteStream writer); + } +} diff --git a/tools/workbench/LibWorkBench/Core/IUseHierarchy.cs b/tools/workbench/LibWorkBench/Core/IUseHierarchy.cs new file mode 100644 index 0000000..6ece7c1 --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/IUseHierarchy.cs @@ -0,0 +1,20 @@ +namespace LibWorkBench.Core +{ + /// + /// Interface for parent/child relationships + /// + /// Derived type + public interface IUseHierarchy + where TDerived : IUseHierarchy + { + /// + /// Parent object + /// + TDerived? Parent { get; set; } + + /// + /// Children objects + /// + List Children { get; set; } + } +} diff --git a/tools/workbench/LibWorkBench/Core/IUseJson.cs b/tools/workbench/LibWorkBench/Core/IUseJson.cs new file mode 100644 index 0000000..ce54f4c --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/IUseJson.cs @@ -0,0 +1,22 @@ +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Core +{ + /// + /// Interface for objects serialized as JSON data + /// + public interface IUseJson + { + /// + /// Deserializes the contents of this object from a file + /// + /// Stream to the JSON file + public abstract void Load(JsonFileReader reader); + + /// + /// Serializes the contents of this object to a file + /// + /// Stream to the JSON file + public abstract void Dump(JsonFileWriter writer); + } +} diff --git a/tools/workbench/LibWorkBench/Core/IUseName.cs b/tools/workbench/LibWorkBench/Core/IUseName.cs new file mode 100644 index 0000000..eff49fe --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/IUseName.cs @@ -0,0 +1,13 @@ +namespace LibWorkBench.Core +{ + /// + /// Interface for namable objects + /// + public interface IUseName + { + /// + /// Object name + /// + public string Name { get; set; } + } +} diff --git a/tools/workbench/LibWorkBench/Core/Models/Binary/BinaryBlockFactory.cs b/tools/workbench/LibWorkBench/Core/Models/Binary/BinaryBlockFactory.cs new file mode 100644 index 0000000..899e326 --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/Models/Binary/BinaryBlockFactory.cs @@ -0,0 +1,92 @@ +using LibWorkBench.Core.Models.Binary.Details; + +namespace LibWorkBench.Core.Models.Binary +{ + /// + /// Binary block factory. + /// Allows creation of block objects from their file signatures ("magic"). + /// + public class BinaryBlockFactory + { + /// + /// Block type registry. + /// Maps a block's signature ("magic") to its class type + /// + private readonly OrderedDictionary _registry = new(); + + /// + /// Binary model which owns all created blocks + /// + public BlockBinaryModel? Model = null; + + /// + /// Registers a new block type for creation via this factory + /// + /// Binary block type + /// The block type has already been registered + public void RegisterBlock() + where T : BinaryBlock, new() + { + Type blockType = typeof(T); + string signature = BinaryBlock.GetProfileStatic().Signature; + + if (_registry.ContainsKey(signature)) + { + throw new InvalidOperationException( + $"Block {blockType.FullName} has already been registered"); + } + + _registry[signature] = blockType; + } + + /// + /// Creates a new block of the specified type + /// + /// Binary block type + /// New block + public T CreateBlock() + where T : BinaryBlock, new() + { + return (T)CreateBlock(typeof(T)); + } + + /// + /// Creates a new block of the type matching the specified signature + /// + /// Block type magic/signature + /// New block + /// No block type matches the signature + /// The block could not be created + public BinaryBlock CreateBlock(string signature) + { + if (!_registry.ContainsKey(signature)) + { + throw new InvalidOperationException( + $"No block matches the signature {signature}"); + } + + return CreateBlock(_registry[signature]); + } + + /// + /// Creates a new block of the specified type + /// + /// Block type + /// New block + /// The block could not be created + public BinaryBlock CreateBlock(Type type) + { + object? obj = Activator.CreateInstance(type); + if (obj == null) + { + throw new InvalidOperationException( + $"Failed to instantiate block {type.FullName}"); + } + + BinaryBlock block = (BinaryBlock)obj; + block.Model = Model; + + return block; + } + } +} diff --git a/tools/workbench/LibWorkBench/Core/Models/Binary/BinaryBlockManager.cs b/tools/workbench/LibWorkBench/Core/Models/Binary/BinaryBlockManager.cs new file mode 100644 index 0000000..c78646a --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/Models/Binary/BinaryBlockManager.cs @@ -0,0 +1,194 @@ +using LibWorkBench.Core.Models.Binary.Details; + +namespace LibWorkBench.Core.Models.Binary +{ + /// + /// Binary block manager + /// + public class BinaryBlockManager + { + /// + /// Factory used for block creation + /// + private readonly BinaryBlockFactory _factory; + + /// + /// Blocks owned by this manager. + /// This maps a block type to all known instances. + /// + public OrderedDictionary> Blocks { get; } = new(); + + /// + /// Constructor + /// + /// Factory used for block creation + public BinaryBlockManager(BinaryBlockFactory factory) + { + _factory = factory; + } + + /// + /// Gets the first (eldest) block of the specified type + /// + /// Block type + /// Whether to create a new block if none exist + /// First owned block + public T GetOne(bool create = false) + where T : BinaryBlock, new() + { + return (T)GetAll(create).First(); + } + + /// + /// Gets the first (eldest) block of the specified type + /// + /// Block type + /// Whether to create a new block if none exist + /// First owned block + public BinaryBlock GetOne(Type type, bool create = false) + { + return GetAll(type, create).First(); + } + + /// + /// Gets all blocks of the specified type + /// + /// Block type + /// Whether to create a new block if none exist + /// First owned block + public List GetAll(bool create = false) + where T : BinaryBlock, new() + { + return GetAll(typeof(T), create); + } + + /// + /// Gets all blocks of the specified type + /// + /// Block type + /// Whether to create a new block if none exist + /// First owned block + public List GetAll(Type type, bool create = false) + { + // No blocks of this type have ever been created + bool noList = !Blocks.ContainsKey(type); + // All blocks of this type have been removed somehow + bool noBlocks = noList || Blocks[type].Count == 0; + + if ((noList || noBlocks) && !create) + { + throw new InvalidOperationException( + $"No blocks of type {type.FullName}, and we can't create"); + } + + // Need to create a list if this is the first block ever + if (noList) + { + Blocks[type] = new List(); + } + + List blockList = Blocks[type]; + + // Create the first block only if requested to do so + if (noList && create) + { + blockList.Add(_factory.CreateBlock(type)); + } + + return blockList; + } + + /// + /// Removes all blocks of the specified type + /// + /// Block type + public void RemoveAll() + where T : BinaryBlock, new() + { + Blocks.Remove(typeof(T)); + } + + /// + /// Removes all blocks of the specified type + /// + /// Block type + public void RemoveAll(Type type) + { + Blocks.Remove(type); + } + + /// + /// Creates a new block of the specified type + /// + /// Block type + /// Prevent the model from managing the new block + /// New block + public T CreateBlock(bool unmanaged = false) + where T : BinaryBlock, new() + { + T block = _factory.CreateBlock(); + + if (!unmanaged) + { + RegisterBlock(block); + } + + return block; + } + + /// + /// Creates a new block of the type matching the specified signature + /// + /// Block type magic/signature + /// Prevent the model from managing the new block + /// New block + public BinaryBlock CreateBlock(string signature, + bool unmanaged = false) + { + BinaryBlock block = _factory.CreateBlock(signature); + + if (!unmanaged) + { + RegisterBlock(block); + } + + return block; + } + + /// + /// Creates a new block of the specified type + /// + /// Block type + /// Prevent the model from managing the new block + /// New block + public BinaryBlock CreateBlock(Type type, bool unmanaged = false) + { + BinaryBlock block = _factory.CreateBlock(type); + + if (!unmanaged) + { + RegisterBlock(block); + } + + return block; + } + + /// + /// Registers a new block with this model + /// + /// New block + private void RegisterBlock(BinaryBlock block) + { + // Gets the derived type (even through a base class handle) + Type blockType = block.GetType(); + + // Need to create a list if this is the first block ever + if (!Blocks.ContainsKey(blockType)) + { + Blocks[blockType] = new List(); + } + + Blocks[blockType].Add(block); + } + } +} diff --git a/tools/workbench/LibWorkBench/Core/Models/Binary/BinaryModel.cs b/tools/workbench/LibWorkBench/Core/Models/Binary/BinaryModel.cs new file mode 100644 index 0000000..b6a9ea7 --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/Models/Binary/BinaryModel.cs @@ -0,0 +1,37 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Attributes.Details; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.Core.Models.Details; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Core.Models.Binary +{ + /// + /// Base class for binary-view models + /// + public abstract class BinaryModel : ProfileProxy, IUseBinary + { + /// + /// Resource that owns this model + /// + public ResourceImpl? Resource { get; set; } = null; + + /// + /// Deserializes the contents of this model from a file + /// + /// Binary stream to the file + public abstract void Read(ReadStream reader); + + /// + /// Serializes the contents of this model to a file + /// + /// Binary stream to the file + public abstract void Write(WriteStream writer); + + /// + /// Updates this model to match the contents of the data-view model + /// + /// Data-view model + public abstract void Sync(DataModel dataModel); + } +} diff --git a/tools/workbench/LibWorkBench/Core/Models/Binary/BlockBinaryModel.cs b/tools/workbench/LibWorkBench/Core/Models/Binary/BlockBinaryModel.cs new file mode 100644 index 0000000..7505175 --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/Models/Binary/BlockBinaryModel.cs @@ -0,0 +1,155 @@ +using LibWorkBench.Core.Models.Binary.Details; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Core.Models.Binary +{ + /// + /// Base class for binary-view models with blocks + /// + public abstract class BlockBinaryModel : BinaryModel + { + /// + /// Block manager + /// + protected readonly BinaryBlockManager _manager; + + /// + /// Number of blocks saved during the most recent Write operation + /// + public uint BlocksWritten { get; set; } = 0; + + /// + /// Constructor + /// + /// Factory used for block creation + public BlockBinaryModel(BinaryBlockFactory factory) + { + factory.Model = this; + _manager = new BinaryBlockManager(factory); + } + + /// + /// Gets the first (eldest) block of the specified type + /// + /// Block type + /// Whether to create a new block if none exist + /// First owned block + public T GetOne(bool create = false) + where T : BinaryBlock, new() + { + return _manager.GetOne(create); + } + + /// + /// Gets the first (eldest) block of the specified type + /// + /// Block type + /// Whether to create a new block if none exist + /// First owned block + public BinaryBlock GetOne(Type type, bool create = false) + { + return _manager.GetOne(type, create); + } + + /// + /// Gets all blocks of the specified type + /// + /// Block type + /// Whether to create a new block if none exist + /// First owned block + public List GetAll(bool create = false) + where T : BinaryBlock, new() + { + return _manager.GetAll(create); + } + + /// + /// Gets all blocks of the specified type + /// + /// Block type + /// Whether to create a new block if none exist + /// First owned block + public List GetAll(Type type, bool create = false) + { + return _manager.GetAll(type, create); + } + + /// + /// Removes all blocks of the specified type + /// + /// Block type + public void RemoveAll() + where T : BinaryBlock, new() + { + _manager.RemoveAll(); + } + + /// + /// Removes all blocks of the specified type + /// + /// Block type + public void RemoveAll(Type type) + { + _manager.RemoveAll(type); + } + + /// + /// Creates a new block of the specified type + /// + /// Block type + /// Prevent the model from managing the new block + /// New block + public T CreateBlock(bool unmanaged = false) + where T : BinaryBlock, new() + { + T block = _manager.CreateBlock(unmanaged); + block.Model = this; + return block; + } + + /// + /// Creates a new block of the type matching the specified signature + /// + /// Block type magic/signature + /// Prevent the model from managing the new block + /// New block + public BinaryBlock CreateBlock(string signature, + bool unmanaged = false) + { + BinaryBlock block = _manager.CreateBlock(signature, unmanaged); + block.Model = this; + return block; + } + + /// + /// Creates a new block of the specified type + /// + /// Block type + /// Prevent the model from managing the new block + /// New block + public BinaryBlock CreateBlock(Type type, bool unmanaged = false) + { + BinaryBlock block = _manager.CreateBlock(type, unmanaged); + block.Model = this; + return block; + } + + /// + /// Allows additional logic after reading each block in the model + /// + /// Binary stream that contained the block data + /// Block that was just read + public virtual void ReadBlockCallback(ReadStream reader, BinaryBlock block) + { + } + + /// + /// Allows additional logic after writing each block in the model + /// + /// Binary stream that will contain the block data + /// Block that was just written + public virtual void WriteBlockCallback(WriteStream writer, BinaryBlock block) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Core/Models/Binary/Details/BinaryBlock.cs b/tools/workbench/LibWorkBench/Core/Models/Binary/Details/BinaryBlock.cs new file mode 100644 index 0000000..72e58e8 --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/Models/Binary/Details/BinaryBlock.cs @@ -0,0 +1,69 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Attributes.Details; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Core.Models.Binary.Details +{ + /// + /// Base class for binary model blocks (implementation details) + /// + public abstract class BinaryBlock : ProfileProxy, IUseBinary + { + /// + /// Model that owns this block + /// + public BlockBinaryModel? Model { get; set; } = null; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + OnRead(reader); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + OnWrite(writer); + + // Model cannot track count because of recursive blocks + if (Model != null) + { + Model.BlocksWritten++; + } + } + + /// + /// Updates this block to match the contents of the data-view model + /// + /// Data-view model + public void Sync(DataModel dataModel) + { + OnSync(dataModel); + } + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public abstract void OnRead(ReadStream reader); + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public abstract void OnWrite(WriteStream writer); + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public abstract void OnSync(DataModel dataModel); + } +} diff --git a/tools/workbench/LibWorkBench/Core/Models/Binary/TBinaryBlock.cs b/tools/workbench/LibWorkBench/Core/Models/Binary/TBinaryBlock.cs new file mode 100644 index 0000000..7ffd04b --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/Models/Binary/TBinaryBlock.cs @@ -0,0 +1,21 @@ +using LibWorkBench.Core.Models.Binary.Details; + +namespace LibWorkBench.Core.Models.Binary +{ + /// + /// Base class for binary model blocks + /// + public abstract class TBinaryBlock : BinaryBlock + where TParentModel : BlockBinaryModel, new() + { + /// + /// Model that owns this block + /// + public new TParentModel? Model + { + get => (TParentModel?)base.Model; + set => base.Model = value; + } + } + +} diff --git a/tools/workbench/LibWorkBench/Core/Models/Data/DataModel.cs b/tools/workbench/LibWorkBench/Core/Models/Data/DataModel.cs new file mode 100644 index 0000000..9b89496 --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/Models/Data/DataModel.cs @@ -0,0 +1,37 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Details; +using LibWorkBench.IO.Streams; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Core.Models.Data +{ + /// + /// Base class for data-view models + /// + public abstract class DataModel : IUseJson + { + /// + /// Resource that owns this model + /// + [JsonIgnore] + public ResourceImpl? Resource { get; set; } = null; + + /// + /// Deserializes the contents of this model from a file + /// + /// Stream to the JSON file + public abstract void Load(JsonFileReader reader); + + /// + /// Serializes the contents of this model to a file + /// + /// Stream to the JSON file + public abstract void Dump(JsonFileWriter writer); + + /// + /// Updates this model to match the contents of the binary-view model + /// + /// Binary-view model + public abstract void Sync(BinaryModel binaryModel); + } +} diff --git a/tools/workbench/LibWorkBench/Core/Models/Details/ResourceImpl.cs b/tools/workbench/LibWorkBench/Core/Models/Details/ResourceImpl.cs new file mode 100644 index 0000000..7699ac4 --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/Models/Details/ResourceImpl.cs @@ -0,0 +1,78 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Attributes.Details; +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Core.Models.Details +{ + /// + /// Base class for resource types (implementation details) + /// + public abstract class ResourceImpl + : ProfileProxy, IUseBinary, IUseJson + { + /// + /// The binary-view model of this resource + /// + protected readonly BinaryModel _binaryModel; + /// + /// The data-view model of this resource + /// + protected readonly DataModel _dataModel; + + /// + /// Constructor + /// + /// Binary-view model + /// Data-view model + public ResourceImpl(BinaryModel binaryModel, + DataModel dataModel) + { + _binaryModel = binaryModel; + _dataModel = dataModel; + } + + /// + /// Deserializes the contents of the binary-view model from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + _binaryModel.Read(reader); + + // "Load" data-view model from new binary contents + _dataModel.Sync(_binaryModel); + } + + /// + /// Serializes the contents of the binary-view model to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + // "Save" data-view model as binary contents + _binaryModel.Sync(_dataModel); + + _binaryModel.Write(writer); + } + + /// + /// Deserializes the contents of the data-view model from a file + /// + /// Stream to the JSON file + public void Load(JsonFileReader reader) + { + _dataModel.Load(reader); + } + + /// + /// Serializes the contents of the data-view model to a file + /// + /// Stream to the JSON file + public void Dump(JsonFileWriter writer) + { + _dataModel.Dump(writer); + } + } +} diff --git a/tools/workbench/LibWorkBench/Core/Models/TResource.cs b/tools/workbench/LibWorkBench/Core/Models/TResource.cs new file mode 100644 index 0000000..2df54ae --- /dev/null +++ b/tools/workbench/LibWorkBench/Core/Models/TResource.cs @@ -0,0 +1,36 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.Core.Models.Details; + +namespace LibWorkBench.Core.Models +{ + /// + /// Base class for resource types + /// + /// Binary-view model class + /// Data-view model class + public class TResource : ResourceImpl + where TBinaryModel : BinaryModel, new() + where TDataModel : DataModel, new() + { + /// + /// Accesses the binary-view model + /// + protected TBinaryModel BinaryModel => (TBinaryModel)_binaryModel; + /// + /// Accesses the data-view model + /// + protected TDataModel DataModel => (TDataModel)_dataModel; + + /// + /// Constructor + /// + public TResource() + : base(new TBinaryModel(), + new TDataModel()) + { + _binaryModel.Resource = this; + _dataModel.Resource = this; + } + } +} diff --git a/tools/workbench/LibWorkBench/Exceptions/FileBrokenException.cs b/tools/workbench/LibWorkBench/Exceptions/FileBrokenException.cs new file mode 100644 index 0000000..20f4db3 --- /dev/null +++ b/tools/workbench/LibWorkBench/Exceptions/FileBrokenException.cs @@ -0,0 +1,24 @@ +namespace LibWorkBench.Exceptions +{ + /// + /// Thrown when a binary file holds invalid or corrupted state + /// + public sealed class FileBrokenException : WorkBenchException + { + /// + /// Constructor + /// + public FileBrokenException() + { + } + + /// + /// Constructor + /// + /// Exception error message + public FileBrokenException(string message) + : base(message) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Exceptions/FileNotSupportedException.cs b/tools/workbench/LibWorkBench/Exceptions/FileNotSupportedException.cs new file mode 100644 index 0000000..58e8bf6 --- /dev/null +++ b/tools/workbench/LibWorkBench/Exceptions/FileNotSupportedException.cs @@ -0,0 +1,24 @@ +namespace LibWorkBench.Exceptions +{ + /// + /// Thrown when a binary file describes a version or resource that is not supported by WorkBench + /// + public sealed class FileNotSupportedException : WorkBenchException + { + /// + /// Constructor + /// + public FileNotSupportedException() + { + } + + /// + /// Constructor + /// + /// Exception error message + public FileNotSupportedException(string message) + : base(message) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Exceptions/FileSignatureException.cs b/tools/workbench/LibWorkBench/Exceptions/FileSignatureException.cs new file mode 100644 index 0000000..7b05a06 --- /dev/null +++ b/tools/workbench/LibWorkBench/Exceptions/FileSignatureException.cs @@ -0,0 +1,24 @@ +namespace LibWorkBench.Exceptions +{ + /// + /// Thrown when a binary file does not match its expected signature / "magic" + /// + public sealed class FileSignatureException : WorkBenchException + { + /// + /// Constructor + /// + public FileSignatureException() + { + } + + /// + /// Constructor + /// + /// Exception error message + public FileSignatureException(string message) + : base(message) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Exceptions/MissingAttributeException.cs b/tools/workbench/LibWorkBench/Exceptions/MissingAttributeException.cs new file mode 100644 index 0000000..5cfa9df --- /dev/null +++ b/tools/workbench/LibWorkBench/Exceptions/MissingAttributeException.cs @@ -0,0 +1,24 @@ +namespace LibWorkBench.Exceptions +{ + /// + /// Thrown when a class type is missing an attribute required by WorkBench + /// + public sealed class MissingAttributeException : WorkBenchException + { + /// + /// Constructor + /// + public MissingAttributeException() + { + } + + /// + /// Constructor + /// + /// Exception error message + public MissingAttributeException(string message) + : base(message) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Exceptions/OperationException.cs b/tools/workbench/LibWorkBench/Exceptions/OperationException.cs new file mode 100644 index 0000000..0ad4e34 --- /dev/null +++ b/tools/workbench/LibWorkBench/Exceptions/OperationException.cs @@ -0,0 +1,24 @@ +namespace LibWorkBench.Exceptions +{ + /// + /// Thrown when a generic operation is not possible or has failed + /// + public sealed class OperationException : WorkBenchException + { + /// + /// Constructor + /// + public OperationException() + { + } + + /// + /// Constructor + /// + /// Exception error message + public OperationException(string message) + : base(message) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Exceptions/WorkBenchException.cs b/tools/workbench/LibWorkBench/Exceptions/WorkBenchException.cs new file mode 100644 index 0000000..096fcc3 --- /dev/null +++ b/tools/workbench/LibWorkBench/Exceptions/WorkBenchException.cs @@ -0,0 +1,24 @@ +namespace LibWorkBench.Exceptions +{ + /// + /// Base class for all WorkBench exception types + /// + public abstract class WorkBenchException : Exception + { + /// + /// Constructor + /// + public WorkBenchException() + { + } + + /// + /// Constructor + /// + /// Exception error message + public WorkBenchException(string message) + : base(message) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemBinaryBlockHeader.cs b/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemBinaryBlockHeader.cs new file mode 100644 index 0000000..c775ebd --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemBinaryBlockHeader.cs @@ -0,0 +1,52 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.JSystem; + +namespace LibWorkBench.Formats.JSystem.Details +{ + /// + /// Binary header for JSYSTEM blocks + /// + public sealed class JSystemBinaryBlockHeader : IUseBinary + { + /// + /// Signature/"magic" associated with this binary block + /// + public string Signature { get; set; } = ""; + + /// + /// Size of this binary block, in bytes + /// + public uint Size { get; set; } = 0; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Signature = reader.ReadString( + maxlen: JSystemDefine.BLOCK_SIGNATURE_LENGTH, + exact: true + ); + + Size = reader.ReadU32(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteString( + Signature, + maxlen: JSystemDefine.BLOCK_SIGNATURE_LENGTH, + terminate: false, + exact: true + ); + + writer.WriteU32(Size); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemBinaryFileHeader.cs b/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemBinaryFileHeader.cs new file mode 100644 index 0000000..d8fabe3 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemBinaryFileHeader.cs @@ -0,0 +1,56 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.JSystem.Details +{ + /// + /// Binary header for JSYSTEM resources + /// + public sealed class JSystemBinaryFileHeader : IUseBinary + { + /// + /// Signature/"magic" of this file + /// + public string Signature { get; set; } = ""; + + /// + /// Size of this resource file, in bytes + /// + public uint FileSize { get; set; } = 0; + + /// + /// Number of data blocks contained within this file + /// + public uint DataBlocks { get; set; } = 0; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Signature = reader.ReadString( + maxlen: JSystemDefine.HEADER_SIGNATURE_LENGTH + ); + + FileSize = reader.ReadU32(); + DataBlocks = reader.ReadU32(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteString( + Signature, + maxlen: JSystemDefine.HEADER_SIGNATURE_LENGTH, + terminate: false + ); + + writer.WriteU32(FileSize); + writer.WriteU32(DataBlocks); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemBinaryModel.cs new file mode 100644 index 0000000..30c5975 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemBinaryModel.cs @@ -0,0 +1,154 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Binary.Details; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.JSystem.Details +{ + /// + /// Base class for JSYSTEM binary-view models (implementation details) + /// + /// Parent resource class + /// Block factory class + public abstract class JSystemBinaryModel : BlockBinaryModel + { + /// + /// Constructor + /// + /// Factory used for block creation + public JSystemBinaryModel(BinaryBlockFactory factory) + : base(factory) + { + } + + /// + /// Deserializes the contents of this model from a file + /// + /// Binary stream to the file + public override void Read(ReadStream reader) + { + JSystemBinaryFileHeader fileHeader = new(); + fileHeader.Read(reader); + + if (fileHeader.Signature != Profile.Signature) + { + throw new FileSignatureException( + $"File signature does not match " + + $"(expected {Profile.Signature}, got {fileHeader.Signature})"); + } + + if (fileHeader.FileSize > reader.Length) + { + throw new FileBrokenException("File size is too large"); + } + + // Derived type may have its own header structure + OnRead(reader); + + // Align to the first block + reader.Align(Profile.Alignment); + + for (uint i = 0; i < fileHeader.DataBlocks; i++) + { + if (reader.Position % Profile.Alignment != 0) + { + throw new FileBrokenException( + "Binary block is misaligned"); + } + + // Need to save block position for jumping to the next block + ulong blockStart = reader.Position; + + JSystemBinaryBlockHeader blockHeader = new(); + blockHeader.Read(reader); + + // Factory decides what to do from the signature + BinaryBlock block = CreateBlock(blockHeader.Signature); + block.Read(reader); + + ReadBlockCallback(reader, block); + + // Jump to the next block + reader.Seek((long)(blockStart + blockHeader.Size), + SeekOrigin.Begin); + } + } + + /// + /// Serializes the contents of this model to a file + /// + /// Binary stream to the file + public override void Write(WriteStream writer) + { + BlocksWritten = 0; + + JSystemBinaryFileHeader fileHeader = new(); + fileHeader.Signature = Profile.Signature; + + // Work buffer for tracking filesize + WorkMemWriter content = new(new BinaryCharEncoding(), + writer.Endian); + + // Write header to make room, will need to correct it later + fileHeader.Write(content); + + // Derived type may have its own header structure + OnWrite(content); + + // Align up to first block + content.Align(Profile.Alignment); + + // Write blocks + foreach (var blockList in _manager.Blocks.Values) + { + foreach (var block in blockList) + { + block.Write(content); + content.Align(Profile.Alignment); + + WriteBlockCallback(content, block); + } + } + + // Go back and fix the header + fileHeader.FileSize = (uint)content.Length; + fileHeader.DataBlocks = BlocksWritten; + content.Seek(0, SeekOrigin.Begin); + fileHeader.Write(content); + + // Flush data to the real stream + writer.Write(content.Buffer, content.Length); + } + + /// + /// Updates this model to match the contents of the data-view model + /// + /// Data-view model + public override void Sync(DataModel dataModel) + { + JSystemDataModel src = (JSystemDataModel)dataModel; + + OnSync(src); + } + + /// + /// Deserializes the contents of this model from a file (derived implementation) + /// + /// Binary stream to the file + public abstract void OnRead(ReadStream reader); + + /// + /// Serializes the contents of this model to a file (derived implementation) + /// + /// Binary stream to the file + public abstract void OnWrite(WriteStream writer); + + /// + /// Updates this model to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public abstract void OnSync(JSystemDataModel dataModel); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemDataModel.cs b/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemDataModel.cs new file mode 100644 index 0000000..639af25 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/Details/JSystemDataModel.cs @@ -0,0 +1,29 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.JSystem.Details +{ + /// + /// Base class for JSYSTEM data-view models (implementation details) + /// + /// Parent resource class + public abstract class JSystemDataModel : DataModel + { + /// + /// Updates this model to match the contents of the binary-view model + /// + /// Binary-view model + public override void Sync(BinaryModel binaryModel) + { + JSystemBinaryModel src = (JSystemBinaryModel)binaryModel; + + OnSync(src); + } + + /// + /// Updates this model to match the contents of the binary-view model (derived implementation) + /// + /// Binary-view model + public abstract void OnSync(JSystemBinaryModel binaryModel); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/FlowChartBlock.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/FlowChartBlock.cs new file mode 100644 index 0000000..87d6a9f --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/FlowChartBlock.cs @@ -0,0 +1,44 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.JSystem.Details; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary.Blocks +{ + /// + /// MsgRes flowchart block + /// + [BinaryBlockProfile(signature: "FLW1")] + public sealed class FlowChartBlock : TJSystemBinaryBlock + { + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + throw new FileNotSupportedException( + "FlowChart block is not yet supported"); + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + throw new FileNotSupportedException( + "FlowChart block is not yet supported"); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(JSystemDataModel dataModel) + { + throw new FileNotSupportedException( + "FlowChart block is not yet supported"); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/FlowLabelBlock.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/FlowLabelBlock.cs new file mode 100644 index 0000000..df46805 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/FlowLabelBlock.cs @@ -0,0 +1,44 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.JSystem.Details; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary.Blocks +{ + /// + /// MsgRes flowlabel block + /// + [BinaryBlockProfile(signature: "FLI1")] + public sealed class FlowLabelBlock : TJSystemBinaryBlock + { + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + throw new FileNotSupportedException( + "FlowLabel block is not yet supported"); + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + throw new FileNotSupportedException( + "FlowLabel block is not yet supported"); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(JSystemDataModel dataModel) + { + throw new FileNotSupportedException( + "FlowLabel block is not yet supported"); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/MsgDataBlock.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/MsgDataBlock.cs new file mode 100644 index 0000000..f18d402 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/MsgDataBlock.cs @@ -0,0 +1,124 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.JSystem.Details; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Data; +using LibWorkBench.Formats.JSystem.JMessage.Tag; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary.Blocks +{ + /// + /// MsgRes message data block + /// + [BinaryBlockProfile(signature: "DAT1")] + public sealed class MsgDataBlock : TJSystemBinaryBlock + { + /// + /// Mapping of message offsets to strings + /// + public OrderedDictionary Contents { get; set; } = new(); + + /// + /// Mapping of message strings to offsets + /// + public Dictionary ContentsInv { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + Contents.Clear(); + + // Dummy empty string, so an offset of zero is valid + Contents[0] = ""; + + // Message info offsets are relative to the stream position + ulong startOffset = reader.Position; + + // Use message info to determine the string boundaries + MsgInfoBlock msgInfo = Model!.GetOne(); + foreach (var info in msgInfo.Contents) + { + // Multiple messages can point at the same string + if (Contents.ContainsKey(info.Offset)) + { + continue; + } + + // Ignore the empty string (we manage this ourselves) + if (info.Offset == 0) + { + continue; + } + + if (info.Offset + startOffset >= reader.Length) + { + throw new FileBrokenException("Message offset is invalid"); + } + + reader.Seek((long)(info.Offset + startOffset), SeekOrigin.Begin); + + // Convert any tag sequences to human-readable text + string s = Model!.Resource!.TagProcessor.Decode(reader, Model.Encoding); + + Contents[info.Offset] = s; + ContentsInv[s] = info.Offset; + } + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + foreach (var it in Contents.Values) + { + Model!.Resource!.TagProcessor.Encode(writer, Model.Encoding, it); + } + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(JSystemDataModel dataModel) + { + MsgResDataModel src = (MsgResDataModel)dataModel; + TagProcessorBase tagPro = Model!.Resource!.TagProcessor; + + Contents.Clear(); + ContentsInv.Clear(); + + // Calculate running offset for each string + ulong offset = 0; + + // Always hold the empty string at offset zero + Contents[0] = ""; + ContentsInv[""] = 0; + offset += tagPro.CalcStringSize(src.Encoding, ""); + + foreach (var it in src.Messages) + { + if (offset > uint.MaxValue) + { + throw new FileBrokenException( + "Message data is too big (over 32-bit limit)"); + } + + // Duplicate strings only waste space + if (ContentsInv.ContainsKey(it.Text)) + { + continue; + } + + Contents[(uint)offset] = it.Text; + ContentsInv[it.Text] = (uint)offset; + + offset += tagPro.CalcStringSize(src.Encoding, it.Text); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/MsgIDBlock.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/MsgIDBlock.cs new file mode 100644 index 0000000..396a486 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/MsgIDBlock.cs @@ -0,0 +1,106 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.JSystem.Details; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Data; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types; +using LibWorkBench.Formats.JSystem.JMessage.Utility; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary.Blocks +{ + /// + /// MsgRes message ID block + /// + [BinaryBlockProfile(signature: "MID1")] + public sealed class MsgIDBlock : TJSystemBinaryBlock + { + /// + /// Message ID format + /// + public Form Form { get; set; } = Form.Main; + + /// + /// Message ID supplemental format + /// + public FormSupplement FormSupplement { get; set; } = FormSupplement.Group24; + + /// + /// Message ID contents (list of IDs) + /// + public List Contents { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + ushort entryNum = reader.ReadU16(); + + // Should always be 1:1 with the info table + MsgInfoBlock msgInfo = Model!.GetOne(); + if (entryNum != msgInfo.Contents.Count) + { + throw new FileBrokenException("Message ID block is too small"); + } + + // Upper 4 bits is whether IDs are stored in sorted order, + // lower 4 bits is the message ID format + byte packed = reader.ReadU8(); + bool isOrdered = (packed & 0xF0) != 0; + byte form = (byte)(packed & 0x0F); + + Form = (Form)form; + FormSupplement = (FormSupplement)reader.ReadU8(); + + // Padding/unknown data + reader.Skip(4); + + for (uint i = 0; i < entryNum; i++) + { + Contents.Add(reader.ReadU32()); + } + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + if (Contents.Count > ushort.MaxValue) + { + throw new FileBrokenException("Too many message IDs"); + } + + writer.WriteU16((ushort)Contents.Count); + + // Always clear the isOrdered bit since EGG ignores it + writer.WriteU8((byte)Form); + writer.WriteU8((byte)FormSupplement); + + // Padding/unknown data + writer.Skip(4); + + // Write message IDs + Contents.ForEach(writer.WriteU32); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(JSystemDataModel dataModel) + { + MsgResDataModel src = (MsgResDataModel)dataModel; + + Form = src.Form; + FormSupplement = src.FormSupplement; + + Contents.Clear(); + + Contents = src.Messages.Select(it => + MessageUtil.JoinID(FormSupplement, it.Group, it.Index)).ToList(); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/MsgInfoBlock.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/MsgInfoBlock.cs new file mode 100644 index 0000000..3424851 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/MsgInfoBlock.cs @@ -0,0 +1,171 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.JSystem.Details; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Data; +using LibWorkBench.IO.Streams; +using LibWorkBench.Utility; + +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary.Blocks +{ + /// + /// MsgRes message info block + /// + [BinaryBlockProfile(signature: "INF1")] + public sealed class MsgInfoBlock : TJSystemBinaryBlock + { + /// + /// Minimum entry size (must include offset & attribute) + /// + private const int ENTRY_SIZE_MIN = 8; + + /// + /// Message info block entry + /// + public sealed class Entry + { + /// + /// Offset into the message data block + /// + public uint Offset = 0; + + /// + /// Message attributes + /// + public uint Attributes = 0; + + /// + /// Message extra attributes (per user spec.) + /// + public byte[] ExAttributes = []; + + /// + /// Constructor + /// + /// Offset into the message data block + /// Message attributes + /// Message extra attributes (per user spec.) + public Entry(uint offset, uint attributes, byte[] exAttributes) + { + Offset = offset; + Attributes = attributes; + ExAttributes = exAttributes; + } + } + + /// + /// Message info group ID + /// + public ushort GroupID { get; set; } = 0; + + /// + /// Message info contents + /// + public List Contents { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + Contents.Clear(); + + ushort entryNum = reader.ReadU16(); + ushort entrySize = reader.ReadU16(); + + if (entrySize % 4 != 0) + { + throw new FileBrokenException( + "Message info entry size must be aligned to 4 bytes"); + } + + if (entrySize < ENTRY_SIZE_MIN) + { + throw new FileBrokenException("Message info entry size is too small"); + } + + GroupID = reader.ReadU16(); + reader.Align(4); + + // Block data is a table of these entries + for (uint i = 0; i < entryNum; i++) + { + uint offset = reader.ReadU32(); + uint attributes = reader.ReadU32(); + + // Message tools allow custom attributes + uint exSize = (uint)(entrySize - ENTRY_SIZE_MIN); + byte[] exAttributes = reader.Read(exSize); + + Contents.Add(new(offset, attributes, exAttributes)); + } + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + /// There are too many messages + public override void DoWrite(WriteStream writer) + { + if (Contents.Count > ushort.MaxValue) + { + throw new FileBrokenException("Too many messages"); + } + + if (Contents.Any(it => + it.ExAttributes.Length != Contents.First().ExAttributes.Length)) + { + throw new FileBrokenException("Ex-attribute size mismatch"); + } + + ushort entryNum = (ushort)Contents.Count; + ushort entrySize = ENTRY_SIZE_MIN; + + // Include ex-attributes in the entry size + if (entryNum > 0) + { + entrySize += (ushort)Contents.First().ExAttributes.Length; + entrySize = Util.RoundUp(entrySize, 4); + } + + writer.WriteU16(entryNum); + writer.WriteU16(entrySize); + writer.WriteU16(GroupID); + writer.Align(4); + + foreach (var it in Contents) + { + writer.WriteU32(it.Offset); + writer.WriteU32(it.Attributes); + + writer.Write(it.ExAttributes); + writer.Align(4); + } + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(JSystemDataModel dataModel) + { + MsgResDataModel src = (MsgResDataModel)dataModel; + + MsgDataBlock msgData = Model!.GetOne(); + + GroupID = src.GroupID; + + Contents.Clear(); + + foreach (var it in src.Messages) + { + Contents.Add(new( + msgData.ContentsInv[it.Text], + it.Attributes, + it.ExAttributes + )); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/StrAttrBlock.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/StrAttrBlock.cs new file mode 100644 index 0000000..8879fc9 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/Blocks/StrAttrBlock.cs @@ -0,0 +1,44 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.JSystem.Details; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary.Blocks +{ + /// + /// MsgRes string attribute block + /// + [BinaryBlockProfile(signature: "STR1")] + public sealed class StrAttrBlock : TJSystemBinaryBlock + { + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + throw new FileNotSupportedException( + "StrAttr block is not yet supported"); + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + throw new FileNotSupportedException( + "StrAttr block is not yet supported"); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(JSystemDataModel dataModel) + { + throw new FileNotSupportedException( + "StrAttr block is not yet supported"); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/MsgResBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/MsgResBinaryModel.cs new file mode 100644 index 0000000..945ed81 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/MsgResBinaryModel.cs @@ -0,0 +1,79 @@ +using LibWorkBench.API.JSystem.JMessage; +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.JSystem.Details; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary.Blocks; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Data; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary +{ + /// + /// MsgRes binary-view model + /// + [BinaryModelProfile( + signature: "MESGbmg1", + alignment: JSystemDefine.BLOCK_ALIGNMENT + )] + public sealed class MsgResBinaryModel + : TJSystemBinaryModel + { + /// + /// Text encoding format used by this model + /// + public TextEncoding Encoding { get; set; } = TextEncoding.UTF16; + + /// + /// Deserializes the contents of this model from a file (derived implementation) + /// + /// Binary stream to the file + public override void OnRead(ReadStream reader) + { + Encoding = (TextEncoding)reader.ReadU8(); + + // GC-era files are known to use Undefined sometimes + if (Encoding == TextEncoding.Undefined) + { + Encoding = TextEncoding.CP1252; + } + + // TODO(kiwi) Streams need to support Shift-JIS + if (Encoding == TextEncoding.SJIS) + { + throw new FileNotSupportedException( + "Shift-JIS not yet supported"); + } + } + + /// + /// Serializes the contents of this model to a file (derived implementation) + /// + /// Binary stream to the file + public override void OnWrite(WriteStream writer) + { + writer.WriteU8((byte)Encoding); + } + + /// + /// Updates this model to match the contents of the data-view model + /// + /// Data-view model + public override void OnSync(JSystemDataModel dataModel) + { + MsgResDataModel src = (MsgResDataModel)dataModel; + + Encoding = src.Encoding; + + // Create any missing blocks in the order they should be written + MsgInfoBlock msgInfo = GetOne(create: true); + MsgDataBlock msgData = GetOne(create: true); + MsgIDBlock msgId = GetOne(create: true); + + // Sync string pool first to allow deduplication + msgData.Sync(src); + msgInfo.Sync(src); + msgId.Sync(src); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/MsgResBlockFactory.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/MsgResBlockFactory.cs new file mode 100644 index 0000000..d74a743 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Binary/MsgResBlockFactory.cs @@ -0,0 +1,24 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary.Blocks; + +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary +{ + /// + /// MsgRes binary block factory + /// + public sealed class MsgResBlockFactory : BinaryBlockFactory + { + /// + /// Constructor + /// + public MsgResBlockFactory() + { + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Data/Message.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Data/Message.cs new file mode 100644 index 0000000..68a63d5 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Data/Message.cs @@ -0,0 +1,56 @@ +using LibWorkBench.Converters; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Data +{ + /// + /// API representation of a single message + /// + public class Message + { + /// + /// Message group ID + /// + public uint Group { get; set; } = 0; + + /// + /// Message index within its group + /// + public uint Index { get; set; } = 0; + + /// + /// Message text string + /// + public string Text { get; set; } = ""; + + /// + /// Message attributes + /// + [JsonConverter(typeof(HexUInt32JsonConverter))] + public uint Attributes { get; set; } = 0; + + /// + /// Message extra attributes (per user spec.) + /// + [JsonConverter(typeof(HexByteArrayJsonConverter))] + public byte[] ExAttributes { get; set; } = []; + + /// + /// Constructor + /// + /// Group ID + /// Index + /// Text string + /// Message attributes + /// Extra attributes (per user spec.) + public Message(uint group, uint index, string text, uint attributes, + byte[] exAttributes) + { + Group = group; + Index = index; + Text = text; + Attributes = attributes; + ExAttributes = exAttributes; + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Data/MsgResDataModel.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Data/MsgResDataModel.cs new file mode 100644 index 0000000..22ff39f --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Data/MsgResDataModel.cs @@ -0,0 +1,104 @@ +using LibWorkBench.API.JSystem.JMessage; +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.JSystem.Details; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Binary.Blocks; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types; +using LibWorkBench.Formats.JSystem.JMessage.Utility; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Data +{ + /// + /// MsgRes data-view model + /// + public sealed class MsgResDataModel : TJSystemDataModel + { + /// + /// Text encoding format used by this model + /// + public TextEncoding Encoding { get; set; } = TextEncoding.UTF16; + + /// + /// Message info group ID + /// + public ushort GroupID { get; set; } = 0; + + /// + /// Message ID format + /// + public Form Form { get; set; } = Form.Main; + + /// + /// Message ID supplemental format + /// + public FormSupplement FormSupplement { get; set; } = FormSupplement.Group24; + + /// + /// Messages contained in this model + /// + public List Messages { get; set; } = new(); + + /// + /// Deserializes the contents of this model from a file + /// + /// Stream to the JSON file + public override void Load(JsonFileReader reader) + { + Messages.Clear(); + + reader.Deserialize(this); + } + + /// + /// Serializes the contents of this model to a file + /// + /// Stream to the JSON file + public override void Dump(JsonFileWriter writer) + { + writer.Serialize(this); + } + + /// + /// Updates this model to match the contents of the binary-view model + /// + /// Binary-view model + public override void OnSync(JSystemBinaryModel binaryModel) + { + MsgResBinaryModel src = (MsgResBinaryModel)binaryModel; + + MsgInfoBlock msgInfo = src.GetOne(); + MsgDataBlock msgData = src.GetOne(); + MsgIDBlock msgID = src.GetOne(); + + Encoding = src.Encoding; + GroupID = msgInfo.GroupID; + Form = msgID.Form; + FormSupplement = msgID.FormSupplement; + + Messages.Clear(); + + // Message info should always line up with the ID table + if (msgInfo.Contents.Count != msgID.Contents.Count) + { + throw new FileBrokenException("Message count mismatch"); + } + + for (int i = 0; i < msgInfo.Contents.Count; i++) + { + MsgInfoBlock.Entry entry = msgInfo.Contents[i]; + + uint group, index; + MessageUtil.SplitID(msgID.Contents[i], FormSupplement, + out group, out index); + + Messages.Add(new( + group, index, + text: msgData.Contents[entry.Offset], + attributes: entry.Attributes, + exAttributes: entry.ExAttributes + )); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Types/Form.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Types/Form.cs new file mode 100644 index 0000000..7e69e4d --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Types/Form.cs @@ -0,0 +1,13 @@ +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types +{ + /// + /// Message ID format type + /// + public enum Form + { + /// + /// Only known format + /// + Main + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Types/FormSupplement.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Types/FormSupplement.cs new file mode 100644 index 0000000..1c5c752 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Types/FormSupplement.cs @@ -0,0 +1,33 @@ +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types +{ + /// + /// Message ID supplemental format type + /// + public enum FormSupplement + { + /// + /// Group ID is 32 bits wide + /// + Group32, + + /// + /// Group ID is 24 bits wide + /// + Group24, + + /// + /// Group ID is 16 bits wide + /// + Group16, + + /// + /// Group ID is 8 bits wide + /// + Group8, + + /// + /// No group ID is provided + /// + Group0, + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Types/TextEncoding.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Types/TextEncoding.cs new file mode 100644 index 0000000..d77baeb --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/MsgRes/Types/TextEncoding.cs @@ -0,0 +1,33 @@ +namespace LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types +{ + /// + /// Text encoding type + /// + public enum TextEncoding + { + /// + /// Encoding not set (legacy support) + /// + Undefined, + + /// + /// Windows-1252 encoding + /// + CP1252, + + /// + /// UTF-16 encoding + /// + UTF16, + + /// + /// Shift-JIS encoding + /// + SJIS, + + /// + /// UTF-8 encoding + /// + UTF8, + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Tag/TagCode.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Tag/TagCode.cs new file mode 100644 index 0000000..5ab35e7 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Tag/TagCode.cs @@ -0,0 +1,115 @@ +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.JSystem.JMessage.Utility; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types; + +namespace LibWorkBench.Formats.JSystem.JMessage.Tag +{ + /// + /// Message tag code + /// + public sealed class TagCode + { + /// + /// Marker for the start of a tag code + /// + public const byte MARK = 0x1A; + + /// + /// Minimum length of a tag code + /// + public const int LENGTH_MIN = 4; + + /// + /// Unique identifier of this tag code + /// + public uint ID = 0; + + /// + /// Parameters for this tag code + /// + public byte[] Params = []; + + /// + /// Group ID of this tag code + /// + public uint Group => ID & 0x00FF0000; + + /// + /// Index of this tag code + /// + public uint Index => ID & 0x0000FFFF; + + /// + /// Constructor + /// + public TagCode() + { + } + + /// + /// Constructor + /// + /// Unique identifier + /// Parameters + public TagCode(uint id, byte[] params_) + { + ID = id; + Params = params_; + } + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader, TextEncoding encoding) + { + // Length and ID are packed as one 32-bit value + // LLLL LLLL DDDD DDDD | DDDD DDDD DDDD DDDD + uint packed = reader.ReadU32(); + + uint length = (packed & 0xFF000000) >> 24; + ID = packed & 0x00FFFFFF; + + if (length > 0) + { + int paramSize = (int)length - + (int)EncodingUtil.GetCharSize(encoding) - // Tag mark + LENGTH_MIN; // Length/ID packed field + + // Parameters are optional + if (paramSize > 0) + { + Params = reader.Read((ulong)paramSize); + } + } + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer, TextEncoding encoding) + { + // Tag code mark is a character, so it must match the encoding + EncodingUtil.WriteChar(writer, encoding, MARK); + + uint length = EncodingUtil.GetCharSize(encoding) + // Tag mark + LENGTH_MIN + // Length/ID packed field + (uint)Params.Length; // Tag parameters (optional) + + // Only one byte is reserved for the tag code length + if (length > 0xFF) + { + throw new FileBrokenException("Tag code is too long"); + } + + // Length and ID are packed as one 32-bit value + // LLLL LLLL DDDD DDDD | DDDD DDDD DDDD DDDD + uint packed = (length & 0x000000FF) << 24 | ID; + writer.WriteU32(packed); + + writer.Write(Params); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Tag/TagProcessorBase.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Tag/TagProcessorBase.cs new file mode 100644 index 0000000..4818fcc --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Tag/TagProcessorBase.cs @@ -0,0 +1,202 @@ +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; +using LibWorkBench.Utility; +using System.Text; +using System.Text.RegularExpressions; +using LibWorkBench.Formats.JSystem.JMessage.Utility; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types; + +namespace LibWorkBench.Formats.JSystem.JMessage.Tag +{ + /// + /// Base class for message tag code processors + /// + public abstract class TagProcessorBase + { + /// + /// Regular expression to use when extracting tag instances + /// + private readonly Regex TAG_INSTANCE_REGEX = new("(\\{[^{}]+\\})"); + + /// + /// Regular expression to use when replacing tag escape characters + /// + private readonly Regex TAG_ESCAPE_REGEX = new("{|}"); + + /// + /// Mapping of tag code IDs to names + /// + private readonly Dictionary _tagIDToName = new(); + + /// + /// Mapping of tag code names to IDs + /// + private readonly Dictionary _tagNameToID = new(); + + /// + /// Registers a new tag code with this tag processor + /// + /// Tag code unique ID + /// Tag code readable name + public void RegisterTag(uint id, string name) + { + _tagIDToName[id] = name; + _tagNameToID[name] = id; + } + + /// + /// Encodes the specified string and writes it to the output stream + /// + /// Binary output stream + /// Text encoding type + /// Message text + public void Encode(WriteStream writer, TextEncoding encoding, + string text) + { + // Separate tag codes from text + string[] tokens = TAG_INSTANCE_REGEX.Split(text); + + foreach (var token in tokens) + { + // Not a tag, just write the raw text + if (!token.StartsWith('{')) + { + // Convert Unicode escape sequences back into characters + EncodingUtil.WriteString(writer, encoding, + Regex.Unescape(token), terminate: false); + } + // Encode the tag into binary form + else + { + EncodeTag(writer, encoding, token); + } + } + + // Null terminator + EncodingUtil.WriteChar(writer, encoding, 0x00); + } + + /// + /// Decodes the string from the input stream at the current position + /// + /// Binary input stream + /// Text encoding type + /// Decoded string + public string Decode(ReadStream reader, TextEncoding encoding) + { + // Resulting string + StringBuilder builder = new(); + // Whether we are currently inside of a tag code + bool isTag = false; + + while (!reader.EOF) + { + // Decode the tag if we just saw the marker + if (isTag) + { + builder.Append(DecodeTag(reader, encoding)); + + isTag = false; + continue; + } + + uint ch = EncodingUtil.ReadChar(reader, encoding); + + // Null terminator + if (ch == 0) + { + break; + } + + // Tag code marker + if (ch == TagCode.MARK) + { + isTag = true; + continue; + } + + builder.Append( + EncodingUtil.DecodeChar(encoding, reader.Endian, ch)); + } + + return builder.ToString(); + } + + /// + /// Calculates the byte-size of the specified string after it has been encoded + /// + /// Text encoding + /// Text string + /// Bytes needed to encode the string + public ulong CalcStringSize(TextEncoding encoding, string text) + { + WorkMemWriter writer = new(new BinaryCharEncoding(), + EndianUtil.Type.Big); + + Encode(writer, encoding, text); + return writer.Length; + } + + /// + /// Encodes a message tag code and writes it to the specified stream + /// + /// Output binary stream + /// Text encoding + /// Tag string + /// The tag name is unknown + private void EncodeTag(WriteStream writer, TextEncoding encoding, + string s) + { + // Remove tag escape characters + s = TAG_ESCAPE_REGEX.Replace(s, string.Empty).Trim(); + + // Everything after the name is considered a parameter + string[] tokens = s.Split((char[]?)null, count: 2, + options: StringSplitOptions.RemoveEmptyEntries); + + string name = tokens[0]; + + // Need to map the provided name to an ID + if (!_tagNameToID.TryGetValue(name, out uint id)) + { + throw new FileBrokenException($"Unknown tag name: {name}"); + } + + byte[] params_ = tokens.Length > 1 + ? Util.FromHex(tokens[1]) : []; + + TagCode tag = new(id, params_); + tag.Write(writer, encoding); + } + + /// + /// Decodes a message tag code from the specified stream + /// + /// Input binary stream + /// The string representation of the tag and its parameters + /// The tag ID is unknown + private string DecodeTag(ReadStream reader, TextEncoding encoding) + { + TagCode tag = new(); + tag.Read(reader, encoding); + + // Need to map the provided ID to a name + if (!_tagIDToName.TryGetValue(tag.ID, out string? name)) + { + throw new FileBrokenException($"Unknown tag ID: {tag.ID}"); + } + + if (tag.Params.Length > 0) + { + // { NAME 00 01 02 ... } + return $"{{ {name} {Util.ToHex(tag.Params)} }}"; + } + else + { + // { NAME } + return $"{{ {name} }}"; + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Utility/EncodingUtil.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Utility/EncodingUtil.cs new file mode 100644 index 0000000..64bbf87 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Utility/EncodingUtil.cs @@ -0,0 +1,190 @@ +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; +using LibWorkBench.Utility; +using System.Text; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types; + +namespace LibWorkBench.Formats.JSystem.JMessage.Utility +{ + /// + /// Text encoding utilities + /// + public static class EncodingUtil + { + /// + /// Reads a single character from a stream in the specified encoding + /// + /// Input stream + /// Text encoding + /// 32-bit character code + /// Invalid text encoding was provided + public static uint ReadChar(ReadStream reader, TextEncoding encoding) + { + switch (encoding) + { + case TextEncoding.CP1252: + case TextEncoding.UTF8: + return reader.ReadU8(); + + case TextEncoding.UTF16: + case TextEncoding.SJIS: + return reader.ReadU16(); + + default: + throw new OperationException("Invalid TextEncoding"); + } + } + + /// + /// Writes a single character to a stream in the specified encoding + /// + /// Output stream + /// Text encoding + /// 32-bit character code + /// Invalid text encoding was provided + public static void WriteChar(WriteStream writer, TextEncoding encoding, + uint value) + { + byte oneByte = (byte)value; + ushort twoByte = (ushort)value; + + switch (encoding) + { + case TextEncoding.CP1252: + case TextEncoding.UTF8: + writer.WriteU8(oneByte); + break; + + case TextEncoding.UTF16: + case TextEncoding.SJIS: + writer.WriteU16(twoByte); + break; + + default: + throw new OperationException("Invalid TextEncoding"); + } + } + + /// + /// Decodes a character code into its string representation + /// + /// Text encoding + /// Endianness + /// 32-bit character code + /// String representation of the character code + /// Invalid text encoding was provided + public static string DecodeChar(TextEncoding encoding, + EndianUtil.Type endian, uint value) + { + byte oneByte = (byte)value; + ushort twoByte = (ushort)value; + + switch (encoding) + { + case TextEncoding.CP1252: + return Encoding.ASCII.GetString([oneByte]); + + case TextEncoding.UTF8: + return Encoding.UTF8.GetString([oneByte]); + + case TextEncoding.UTF16: + return Encoding.Unicode.GetString( + BitConverter.GetBytes(twoByte)); + + case TextEncoding.SJIS: + throw new NotImplementedException("Not yet implemented"); + + default: + throw new OperationException("Invalid TextEncoding"); + } + } + + /// + /// Reads a string from the stream, using the specified text encoding + /// + /// Input stream + /// Message text encoding type + /// Maximum string length + /// String value + /// Text encoding type is invalid + public static string ReadString(ReadStream reader, + TextEncoding encoding, + int maxlen = int.MaxValue) + { + switch (encoding) + { + // TODO(kiwi) Are these safe to merge? + case TextEncoding.CP1252: + case TextEncoding.UTF8: + return reader.ReadString(maxlen); + + case TextEncoding.UTF16: + return reader.ReadWideString(maxlen); + + case TextEncoding.SJIS: + return reader.ReadWideString(maxlen); + + default: + throw new OperationException("Invalid TextEncoding"); + } + } + + /// + /// Writes a string to the stream, using the specified text encoding + /// + /// Output stream + /// Message text encoding type + /// Message text string + /// Maximum string length + /// Whether to null-terminate the string (binary modes only) + /// Text encoding type is invalid + public static void WriteString(WriteStream writer, + TextEncoding encoding, string text, + int maxlen = int.MaxValue, + bool terminate = true) + { + switch (encoding) + { + // TODO(kiwi) Are these safe to merge? + case TextEncoding.CP1252: + case TextEncoding.UTF8: + writer.WriteString(text, maxlen, terminate); + break; + + case TextEncoding.UTF16: + writer.WriteWideString(text, maxlen, terminate); + break; + + case TextEncoding.SJIS: + writer.WriteSjisString(text, maxlen, terminate); + break; + + default: + throw new OperationException("Invalid TextEncoding"); + } + } + + /// + /// Gets the byte-size of a single character in the specified text encoding + /// + /// Text encoding + /// Number of bytes needed to represent a single character + /// Invalid text encoding was provided + public static uint GetCharSize(TextEncoding encoding) + { + switch (encoding) + { + case TextEncoding.CP1252: + case TextEncoding.UTF8: + return 1; + + case TextEncoding.UTF16: + case TextEncoding.SJIS: + return 2; + + default: + throw new OperationException("Invalid TextEncoding"); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Utility/MessageUtil.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Utility/MessageUtil.cs new file mode 100644 index 0000000..cb77c1a --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JMessage/Utility/MessageUtil.cs @@ -0,0 +1,115 @@ +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.JSystem.JMessage.MsgRes.Types; + +namespace LibWorkBench.Formats.JSystem.JMessage.Utility +{ + /// + /// Message utilities + /// + public static class MessageUtil + { + /// + /// Splits the specified message id into its group and index components + /// + /// Message ID + /// Message ID format + /// Message group + /// Message index + /// Invalid supplemental form was provided + public static void SplitID(uint id, FormSupplement form, + out uint group, out uint index) + { + switch (form) + { + case FormSupplement.Group32: + group = id; + index = 0; + break; + + case FormSupplement.Group24: + group = (id & 0xFFFFFF00) >> 8; + index = id & 0x000000FF; + break; + + case FormSupplement.Group16: + group = (id & 0xFFFF0000) >> 16; + index = id & 0x0000FFFF; + break; + + case FormSupplement.Group8: + group = (id & 0xFF000000) >> 24; + index = id & 0x000000FF; + break; + + case FormSupplement.Group0: + group = 0; + index = id; + break; + + default: + throw new OperationException("Invalid FormSupplement"); + } + } + + /// + /// Joins the specified message group and index into a unique ID. + /// The components are validated to ensure they are compataible with the specified form. + /// + /// Message ID format + /// Message group + /// Message index + /// Message ID + /// Invalid supplemental form was provided + /// Message group/index is too large + public static uint JoinID(FormSupplement form, uint group, uint index) + { + switch (form) + { + case FormSupplement.Group32: + return group; + + case FormSupplement.Group24: + if ((group & ~0x00FFFFFF) != 0) + { + throw new OperationException("Group is too large for this form"); + } + if ((index & ~0x000000FF) != 0) + { + throw new OperationException("Index is too large for this form"); + } + + return (group & 0x00FFFFFF) << 8 | index & 0x000000FF; + + case FormSupplement.Group16: + if ((group & ~0x0000FFFF) != 0) + { + throw new OperationException("Group is too large for this form"); + } + if ((index & ~0x0000FFFF) != 0) + { + throw new OperationException("Index is too large for this form"); + } + + return (group & 0x0000FFFF) << 16 | index & 0x0000FFFF; + + case FormSupplement.Group8: + if ((group & ~0x000000FF) != 0) + { + throw new OperationException("Group is too large for this form"); + } + if ((index & ~0x00FFFFFF) != 0) + { + throw new OperationException("Index is too large for this form"); + } + + return (group & 0x000000FF) << 24 | index & 0x00FFFFFF; + + case FormSupplement.Group0: + return index; + + default: + throw new OperationException("Invalid FormSupplement"); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/JSystemDefine.cs b/tools/workbench/LibWorkBench/Formats/JSystem/JSystemDefine.cs new file mode 100644 index 0000000..a4fa945 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/JSystemDefine.cs @@ -0,0 +1,23 @@ +namespace LibWorkBench.Formats.JSystem +{ + /// + /// Shared JSYSTEM constants + /// + public static class JSystemDefine + { + /// + /// Maximum length for the Signature field of binary headers + /// + public const int HEADER_SIGNATURE_LENGTH = 8; + + /// + /// Maximum length for the Signature field of binary blocks + /// + public const int BLOCK_SIGNATURE_LENGTH = 4; + + /// + /// Byte alignment for all binary blocks + /// + public const ulong BLOCK_ALIGNMENT = 32; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemBinaryBlock.cs b/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemBinaryBlock.cs new file mode 100644 index 0000000..919124d --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemBinaryBlock.cs @@ -0,0 +1,86 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.Formats.JSystem.Details; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; +using LibWorkBench.Utility; + +namespace LibWorkBench.Formats.JSystem +{ + /// + /// Base class for JSYSTEM binary-view blocks + /// + /// Parent model class + public abstract class TJSystemBinaryBlock : TBinaryBlock + where TParentModel : JSystemBinaryModel, new() + { + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public override void OnRead(ReadStream reader) + { + DoRead(reader); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public override void OnWrite(WriteStream writer) + { + JSystemBinaryBlockHeader blockHeader = new(); + blockHeader.Signature = Profile.Signature; + + // Work buffer for tracking filesize + WorkMemWriter content = new(new BinaryCharEncoding(), + writer.Endian); + + // Write header to make room, will need to correct it later + blockHeader.Write(content); + + // Derived block contents + DoWrite(content); + + // Reflect accurate block size in the header + blockHeader.Size = Util.RoundUp((uint)content.Length, + Model!.Profile.Alignment); + + // Go back and fix the header + content.Seek(0, SeekOrigin.Begin); + blockHeader.Write(content); + + // Flush data to the real stream + writer.Write(content.Buffer, content.Length); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void OnSync(DataModel dataModel) + { + JSystemDataModel src = (JSystemDataModel)dataModel; + + DoSync(src); + } + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public abstract void DoRead(ReadStream reader); + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public abstract void DoWrite(WriteStream writer); + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public abstract void DoSync(JSystemDataModel dataModel); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemBinaryModel.cs new file mode 100644 index 0000000..55ae318 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemBinaryModel.cs @@ -0,0 +1,30 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Details; +using LibWorkBench.Formats.JSystem.Details; + +namespace LibWorkBench.Formats.JSystem +{ + /// + /// Base class for JSYSTEM binary-view models + /// + /// Parent resource class + /// Block factory class + public abstract class TJSystemBinaryModel : JSystemBinaryModel + where TParentResource : ResourceImpl + where TBlockFactory : BinaryBlockFactory, new() + { + /// + /// Resource that owns this model + /// + public new TParentResource? Resource + => (TParentResource?)base.Resource; + + /// + /// Constructor + /// + public TJSystemBinaryModel() + : base(new TBlockFactory()) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemDataModel.cs b/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemDataModel.cs new file mode 100644 index 0000000..9540485 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemDataModel.cs @@ -0,0 +1,21 @@ +using LibWorkBench.Core.Models.Details; +using LibWorkBench.Formats.JSystem.Details; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Formats.JSystem +{ + /// + /// Base class for JSYSTEM data-view models + /// + /// Parent resource class + public abstract class TJSystemDataModel : JSystemDataModel + where TParentResource : ResourceImpl + { + /// + /// Resource that owns this model + /// + [JsonIgnore] + public new TParentResource? Resource + => (TParentResource?)base.Resource; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemResource.cs b/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemResource.cs new file mode 100644 index 0000000..d435b77 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/JSystem/TJSystemResource.cs @@ -0,0 +1,17 @@ +using LibWorkBench.Core.Models; +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.JSystem +{ + /// + /// Base class for JSYSTEM resources + /// + /// Binary-view model class + /// Data-view model class + public abstract class TJSystemResource : TResource + where TBinaryModel : BinaryModel, new() + where TDataModel : DataModel, new() + { + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/ByteOrder.cs b/tools/workbench/LibWorkBench/Formats/NW4R/ByteOrder.cs new file mode 100644 index 0000000..cab02ee --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/ByteOrder.cs @@ -0,0 +1,18 @@ +namespace LibWorkBench.Formats.NW4R +{ + /// + /// Byte-order mark + /// + public enum ByteOrder + { + /// + /// The resource is stored in big endian + /// + Big = 0xFEFF, + + /// + /// The resource is stored in little endian + /// + Little = 0xFFFE + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RBinaryBlockHeader.cs b/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RBinaryBlockHeader.cs new file mode 100644 index 0000000..641add3 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RBinaryBlockHeader.cs @@ -0,0 +1,57 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; + +namespace LibWorkBench.Formats.NW4R.Details +{ + /// + /// Binary header for NW4R blocks + /// + public sealed class NW4RBinaryBlockHeader : IUseBinary + { + /// + /// Size of this structure when saved in binary form + /// + public const int STRUCT_SIZE = 8; + + /// + /// Signature/"magic" associated with this binary block + /// + public string Signature { get; set; } = ""; + + /// + /// Size of this binary block, in bytes + /// + public uint Size { get; set; } = 0; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Signature = reader.ReadString( + maxlen: NW4RDefine.BLOCK_SIGNATURE_LENGTH, + exact: true + ); + + Size = reader.ReadU32(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteString( + Signature, + maxlen: NW4RDefine.BLOCK_SIGNATURE_LENGTH, + terminate: false, + exact: true + ); + + writer.WriteU32(Size); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RBinaryFileHeader.cs b/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RBinaryFileHeader.cs new file mode 100644 index 0000000..e316451 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RBinaryFileHeader.cs @@ -0,0 +1,85 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; + +namespace LibWorkBench.Formats.NW4R.Details +{ + /// + /// Binary header for NW4R resources + /// + public sealed class NW4RBinaryFileHeader : IUseBinary + { + /// + /// Size of this structure when saved in binary form + /// + public const int STRUCT_SIZE = 16; + + /// + /// Signature/"magic" of this file + /// + public string Signature { get; set; } = ""; + + /// + /// Byte-order/endianness of this file + /// + public ByteOrder ByteOrder { get; set; } = ByteOrder.Big; + + /// + /// Version of this file's specification + /// + public ushort Version { get; set; } = 0; + + /// + /// Size of this file, in bytes + /// + public uint FileSize { get; set; } = 0; + + /// + /// Size of this file's header, in bytes + /// + public ushort HeaderSize { get; set; } = 0; + + /// + /// Number of data blocks contained within this file + /// + public ushort DataBlocks { get; set; } = 0; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Signature = reader.ReadString( + maxlen: NW4RDefine.HEADER_SIGNATURE_LENGTH, + exact: true + ); + + ByteOrder = (ByteOrder)reader.ReadU16(); + Version = reader.ReadU16(); + FileSize = reader.ReadU32(); + HeaderSize = reader.ReadU16(); + DataBlocks = reader.ReadU16(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteString( + Signature, + maxlen: NW4RDefine.HEADER_SIGNATURE_LENGTH, + terminate: false, + exact: true + ); + + writer.WriteU16((ushort)ByteOrder); + writer.WriteU16(Version); + writer.WriteU32(FileSize); + writer.WriteU16(HeaderSize); + writer.WriteU16(DataBlocks); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RBinaryModel.cs new file mode 100644 index 0000000..52548c7 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RBinaryModel.cs @@ -0,0 +1,197 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Binary.Details; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; +using LibWorkBench.Utility; + +namespace LibWorkBench.Formats.NW4R.Details +{ + /// + /// Base class for NW4R binary-view models (implementation details) + /// + /// Parent resource class + /// Block factory class + public abstract class NW4RBinaryModel : BlockBinaryModel + { + /// + /// Version of this file's specification + /// + public uint Version { get; set; } = 0; + + /// + /// Constructor + /// + /// Factory used for block creation + public NW4RBinaryModel(BinaryBlockFactory factory) + : base(factory) + { + } + + /// + /// Deserializes the contents of this model from a file + /// + /// Binary stream to the file + public override void Read(ReadStream reader) + { + NW4RBinaryFileHeader fileHeader = new(); + fileHeader.Read(reader); + + if (fileHeader.Signature != Profile.Signature) + { + throw new FileSignatureException( + $"File signature does not match " + + $"(expected {Profile.Signature}, got {fileHeader.Signature})"); + } + + Version = fileHeader.Version; + if (!Profile.Versions.Contains(Version)) + { + throw new FileNotSupportedException( + $"This version ({Version}) is not supported"); + } + + if (fileHeader.FileSize > reader.Length) + { + throw new FileBrokenException("File size is too large"); + } + + if (fileHeader.HeaderSize > fileHeader.FileSize + || fileHeader.HeaderSize > reader.Length) + { + throw new FileBrokenException("Header size is too large"); + } + + // Derived type may have its own header structure + OnRead(reader); + + // Align to the first block + reader.Align(Profile.Alignment); + + for (uint i = 0; i < fileHeader.DataBlocks; i++) + { + if (reader.Position % Profile.Alignment != 0) + { + throw new FileBrokenException( + "Binary block is misaligned"); + } + + // Need to save block position for jumping to the next block + ulong blockStart = reader.Position; + + NW4RBinaryBlockHeader blockHeader = new(); + blockHeader.Read(reader); + + // Factory decides what to do from the signature + BinaryBlock block = CreateBlock(blockHeader.Signature); + block.Read(reader); + + ReadBlockCallback(reader, block); + + // Jump to the next block + reader.Seek((long)(blockStart + blockHeader.Size), + SeekOrigin.Begin); + } + } + + /// + /// Serializes the contents of this model to a file + /// + /// Binary stream to the file + public override void Write(WriteStream writer) + { + // Version may have been changed so check again + if (!Profile.Versions.Contains(Version)) + { + throw new FileNotSupportedException( + $"This version ({Version}) is not supported"); + } + + BlocksWritten = 0; + + NW4RBinaryFileHeader fileHeader = new(); + fileHeader.Signature = Profile.Signature; + fileHeader.Version = (ushort)Version; + + fileHeader.ByteOrder = writer.Endian == EndianUtil.Type.Big + ? ByteOrder.Big : ByteOrder.Little; + + // Work buffer for tracking filesize + WorkMemWriter content = new(new BinaryCharEncoding(), + writer.Endian); + + // Write header to make room, will need to correct it later + fileHeader.Write(content); + + // Derived type may have its own header structure + OnWrite(content); + + // Save header size for later + fileHeader.HeaderSize = (ushort)content.Length; + + // Align up to first block + content.Align(Profile.Alignment); + + // Write blocks + foreach (var blockList in _manager.Blocks.Values) + { + foreach (var block in blockList) + { + // Make sure all blocks are compatible + if (Version < block.Profile.MinVersion) + { + throw new FileNotSupportedException( + $"{block.GetType().Name} requires at least " + + $"version {block.Profile.MinVersion}"); + } + + block.Write(content); + content.Align(Profile.Alignment); + + WriteBlockCallback(content, block); + } + } + + // Go back and fix the header + fileHeader.FileSize = (uint)content.Length; + fileHeader.DataBlocks = (ushort)BlocksWritten; + content.Seek(0, SeekOrigin.Begin); + fileHeader.Write(content); + + // Flush data to the real stream + writer.Write(content.Buffer, content.Length); + } + + /// + /// Updates this model to match the contents of the data-view model + /// + /// Data-view model + public override void Sync(DataModel dataModel) + { + NW4RDataModel src = (NW4RDataModel)dataModel; + + Version = src.Version; + + OnSync(src); + } + + /// + /// Deserializes the contents of this model from a file (derived implementation) + /// + /// Binary stream to the file + public abstract void OnRead(ReadStream reader); + + /// + /// Serializes the contents of this model to a file (derived implementation) + /// + /// Binary stream to the file + public abstract void OnWrite(WriteStream writer); + + /// + /// Updates this model to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public abstract void OnSync(NW4RDataModel dataModel); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RDataModel.cs b/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RDataModel.cs new file mode 100644 index 0000000..395932d --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/Details/NW4RDataModel.cs @@ -0,0 +1,39 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.Formats.NW4R.Details; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Formats.NW4R +{ + /// + /// Base class for NW4R data-view models (implementation details) + /// + /// Parent resource class + public abstract class NW4RDataModel : DataModel + { + /// + /// Version of this file's specification + /// + [JsonPropertyOrder(int.MinValue)] + public uint Version { get; set; } = 0; + + /// + /// Updates this model to match the contents of the binary-view model + /// + /// Binary-view model + public override void Sync(BinaryModel binaryModel) + { + NW4RBinaryModel src = (NW4RBinaryModel)binaryModel; + + Version = src.Version; + + OnSync(src); + } + + /// + /// Updates this model to match the contents of the binary-view model (derived implementation) + /// + /// Binary-view model + public abstract void OnSync(NW4RBinaryModel binaryModel); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/AnimationDefine.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/AnimationDefine.cs new file mode 100644 index 0000000..2ad8463 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/AnimationDefine.cs @@ -0,0 +1,53 @@ +using LibWorkBench.Formats.NW4R.LayoutLib.Layout; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation +{ + /// + /// Shared layout animation constants + /// + public static class AnimationDefine + { + /// + /// Animation name target length + /// + public static readonly int TARGET_NAME_LEN = + // (Target can be either pane/material) + Math.Max(LayoutDefine.RES_NAME_LEN, LayoutDefine.MAT_NAME_LEN); + + /// + /// Animation info block signature lenght + /// + public const int ANIM_INFO_SIGNATURE_LEN = 4; + + /// + /// Pane S/R/T transformation animation + /// + public const string SIGNATURE_ANMPANESRT = "RLPA"; + /// + /// Pane visibility animation + /// + public const string SIGNATURE_ANMPANEVIS = "RLVI"; + + /// + /// Vertex color animation + /// + public const string SIGNATURE_ANMVTXCLR = "RLVC"; + /// + /// Material color animation + /// + public const string SIGNATURE_ANMMATCLR = "RLMC"; + + /// + /// Texture S/R/T transformation animation + /// + public const string SIGNATURE_ANMTEXSRT = "RLTS"; + /// + /// Texture pattern animation + /// + public const string SIGNATURE_ANMTEXPAT = "RLTP"; + /// + /// Indirect texture S/R/T transformation animation + /// + public const string SIGNATURE_ANMINDTEXSRT = "RLIM"; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationBinaryModel.cs new file mode 100644 index 0000000..b421fc6 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationBinaryModel.cs @@ -0,0 +1,42 @@ +using LibWorkBench.API.NW4R.LayoutLib; +using LibWorkBench.Attributes; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary +{ + /// + /// Layout animation binary-view model + /// + [BinaryModelProfile( + signature: "RLAN", + versions: [8, 10], + alignment: NW4RDefine.BLOCK_ALIGNMENT + )] + public sealed class AnimationBinaryModel + : TNW4RBinaryModel + { + /// + /// Deserializes the contents of this model from a file (derived implementation) + /// + /// Binary stream to the file + public override void OnRead(ReadStream reader) + { + } + + /// + /// Serializes the contents of this model to a file (derived implementation) + /// + /// Binary stream to the file + public override void OnWrite(WriteStream writer) + { + } + + /// + /// Updates this model to match the contents of the data-view model + /// + /// Data-view model + public override void OnSync(NW4RDataModel dataModel) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationBlockFactory.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationBlockFactory.cs new file mode 100644 index 0000000..bb097e2 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationBlockFactory.cs @@ -0,0 +1,19 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary.Blocks; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary +{ + /// + /// Layout animation binary block factory + /// + public sealed class AnimationBlockFactory : BinaryBlockFactory + { + /// + /// Constructor + /// + public AnimationBlockFactory() + { + RegisterBlock(); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationContent.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationContent.cs new file mode 100644 index 0000000..8d1838b --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationContent.cs @@ -0,0 +1,120 @@ +using LibWorkBench.Core; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary +{ + /// + /// Layout animation content + /// + public sealed class AnimationContent : IUseBinary + { + /// + /// Animation target name + /// + public string Target { get; set; } = ""; + + /// + /// Animation content type + /// + public AnimContentKind Kind { get; set; } = AnimContentKind.Pane; + + /// + /// Animation data + /// + public List Animations { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + // Info offsets are relative to this content + long contentPos = (long)reader.Position; + + Target = reader.ReadString( + maxlen: AnimationDefine.TARGET_NAME_LEN, + exact: true + ); + + byte infoNum = reader.ReadU8(); + Kind = (AnimContentKind)reader.ReadU8(); + reader.Align(4); + + // Parse animation info table + List infoOffsets = new(); + for (uint i = 0; i < infoNum; i++) + { + infoOffsets.Add(reader.ReadU32()); + } + + foreach (var it in infoOffsets) + { + if ((ulong)contentPos + it > reader.Length) + { + throw new FileBrokenException("Invalid info offset"); + } + + reader.Seek(contentPos + it, SeekOrigin.Begin); + + AnimationInfo info = new(); + info.Read(reader); + Animations.Add(info); + } + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + WorkMemWriter work = new(new BinaryCharEncoding(), + writer.Endian); + + work.WriteString( + Target, + maxlen: AnimationDefine.TARGET_NAME_LEN, + terminate: false, + exact: true + ); + + if (Animations.Count > byte.MaxValue) + { + throw new FileBrokenException("Too many animation infos"); + } + + work.WriteU8((byte)Animations.Count); + work.WriteU8((byte)Kind); + work.Align(4); + + // Reserve space for animation info offset table + long infoTblPos = (long)work.Position; + work.WriteDebugFill((uint)Animations.Count * sizeof(uint)); + + List offsetList = new(); + foreach (var it in Animations) + { + if (work.Position > uint.MaxValue) + { + throw new FileBrokenException( + "Animation info table is too large"); + } + + offsetList.Add((uint)work.Position); + it.Write(work); + } + + // Go back and fix offset table + work.Seek(infoTblPos, SeekOrigin.Begin); + offsetList.ForEach(work.WriteU32); + + // Flush data to the real stream + writer.Write(work.Buffer, work.Length); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationInfo.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationInfo.cs new file mode 100644 index 0000000..06ed710 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/AnimationInfo.cs @@ -0,0 +1,148 @@ +using LibWorkBench.Core; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types.Details; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Utility; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary +{ + /// + /// Layout animation info + /// + public sealed class AnimationInfo : IUseBinary + { + /// + /// Animation info type + /// + public AnimInfoKind Kind { get; set; } = AnimInfoKind.PaneSrt; + + /// + /// Targets this animation will control + /// + public List Targets { get; set; } = new(); + + /// + /// Creates a new animation target for this animation info + /// + /// Animation target matching this info's animation type + /// Animation info type is invalid + public AnimationTargetImpl CreateTarget() + { + switch (Kind) + { + case AnimInfoKind.PaneSrt: + return new AnimationTargetPaneSrt(); + + case AnimInfoKind.PaneVis: + return new AnimationTargetPaneVis(); + + case AnimInfoKind.VtxClr: + return new AnimationTargetVtxClr(); + + case AnimInfoKind.MatClr: + return new AnimationTargetMatClr(); + + case AnimInfoKind.TexSrt: + return new AnimationTargetTexSrt(); + + case AnimInfoKind.TexPat: + return new AnimationTargetTexPat(); + + case AnimInfoKind.IndTexSrt: + return new AnimationTargetIndTexSrt(); + + default: + throw new OperationException( + $"Invalid animation info type: {Kind}"); + } + } + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + // Target offsets are relative to this info + long infoPos = (long)reader.Position; + + string signature = reader.ReadString( + maxlen: AnimationDefine.ANIM_INFO_SIGNATURE_LEN, + exact: true + ); + + Kind = AnimationUtil.GetAnimInfoKind(signature); + + byte targetNum = reader.ReadU8(); + reader.Align(4); + + // Parse animation target table + List targetOffsets = new(); + for (uint i = 0; i < targetNum; i++) + { + targetOffsets.Add(reader.ReadU32()); + } + + foreach (var it in targetOffsets) + { + if ((ulong)infoPos + it > reader.Length) + { + throw new FileBrokenException("Invalid target offset"); + } + + reader.Seek(infoPos + it, SeekOrigin.Begin); + + AnimationTargetImpl target = CreateTarget(); + target.Read(reader); + Targets.Add(target); + } + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + WorkMemWriter work = new(new BinaryCharEncoding(), + writer.Endian); + + if (Targets.Count > byte.MaxValue) + { + throw new FileBrokenException("Too many animation targets"); + } + + work.WriteU32((uint)Kind); + + work.WriteU8((byte)Targets.Count); + work.Align(4); + + // Reserve space for offset table + long offsetTablePos = (long)work.Position; + work.WriteDebugFill((ulong)Targets.Count * sizeof(uint)); + + // Calculate offset for each material + List offsetList = new(); + foreach (var it in Targets) + { + if (work.Position > uint.MaxValue) + { + throw new FileBrokenException("Target list is too large"); + } + + offsetList.Add((uint)work.Position); + it.Write(work); + } + + // Go back and fix the offset table + work.Seek(offsetTablePos, SeekOrigin.Begin); + offsetList.ForEach(work.WriteU32); + + // Flush data to the real stream + writer.Write(work.Buffer, work.Length); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/Blocks/AnimationInfoBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/Blocks/AnimationInfoBlock.cs new file mode 100644 index 0000000..e775b24 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/Blocks/AnimationInfoBlock.cs @@ -0,0 +1,198 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.Details; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary.Blocks +{ + /// + /// Layout animation info block + /// + [BinaryBlockProfile(signature: "pai1")] + public sealed class AnimationInfoBlock : TNW4RBinaryBlock + { + /// + /// Number of frames in this animation + /// + public ushort Length { get; set; } = 0; + + /// + /// Whether this animation should loop + /// + public bool Loop { get; set; } = false; + + /// + /// Animation contents + /// + public List Contents { get; set; } = new(); + + /// + /// Names of all texture resources required by this animation + /// + public List TextureNames { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + // Content table offset is relative to this block + long blockPos = (long)reader.Position + - NW4RBinaryBlockHeader.STRUCT_SIZE; + + Length = reader.ReadU16(); + + Loop = reader.ReadBool(); + reader.Align(4); + + ushort textureNum = reader.ReadU16(); + ushort animContNum = reader.ReadU16(); + uint animContOffsetTblOffset = reader.ReadU32(); + + // Parse texture string table + long textureTblPos = (long)reader.Position; + List textureOffsets = new(); + + for (uint i = 0; i < textureNum; i++) + { + textureOffsets.Add(reader.ReadU32()); + } + + foreach (var it in textureOffsets) + { + if ((ulong)textureTblPos + it > reader.Length) + { + throw new FileBrokenException( + "Invalid string table offset"); + } + + reader.Seek(textureTblPos + it, SeekOrigin.Begin); + TextureNames.Add(reader.ReadString()); + } + + // Parse animation content table + reader.Seek(blockPos + animContOffsetTblOffset, SeekOrigin.Begin); + List contentOffsets = new(); + + for (uint i = 0; i < animContNum; i++) + { + contentOffsets.Add(reader.ReadU32()); + } + + foreach (var it in contentOffsets) + { + reader.Seek(blockPos + it, SeekOrigin.Begin); + + AnimationContent content = new(); + content.Read(reader); + Contents.Add(content); + } + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + WorkMemWriter work = new(new BinaryCharEncoding(), + writer.Endian); + + work.WriteU16(Length); + work.WriteBool(Loop); + work.Align(4); + + if (TextureNames.Count > ushort.MaxValue) + { + throw new FileBrokenException("Too many texture names"); + } + + work.WriteU16((ushort)TextureNames.Count); + + if (Contents.Count > ushort.MaxValue) + { + throw new FileBrokenException("Too many animation contents"); + } + + work.WriteU16((ushort)Contents.Count); + + // Reserve space for content offset table offset + long contentOffsetTblOffsetPos = (long)work.Position; + work.WriteDebugFill(sizeof(uint)); + + // Reserve space for the texture string table + long textureTblPos = (long)work.Position; + work.WriteDebugFill((ulong)TextureNames.Count * sizeof(uint)); + + // Calculate offset for each texture name + List textureOffsets = new(); + foreach (var it in TextureNames) + { + ulong offset = work.Position - (ulong)textureTblPos; + + if (offset > uint.MaxValue) + { + throw new FileBrokenException( + "Texture string table too large"); + } + + textureOffsets.Add((uint)offset); + work.WriteString(it); + } + + work.Align(4); + + // Reserve space for content offset table + long contentOffsetTblPos = (long)work.Position; + work.WriteDebugFill((ulong)Contents.Count * sizeof(uint)); + + // Calculate offset for each animation content + List contentOffsets = new(); + foreach (var it in Contents) + { + // Offset includes the data block header + ulong offset = work.Position + + NW4RBinaryBlockHeader.STRUCT_SIZE; + + if (offset > uint.MaxValue) + { + throw new FileBrokenException( + "Animation content table too large"); + } + + contentOffsets.Add((uint)offset); + it.Write(work); + } + + // Go back and fix content offset table offset + work.Seek(contentOffsetTblOffsetPos, SeekOrigin.Begin); + // Offset includes the data block header + work.WriteU32((uint)contentOffsetTblPos + + NW4RBinaryBlockHeader.STRUCT_SIZE); + + // Go back and fix texture string table + work.Seek(textureTblPos, SeekOrigin.Begin); + textureOffsets.ForEach(work.WriteU32); + + // Go back and fix content offset table + work.Seek(contentOffsetTblPos, SeekOrigin.Begin); + contentOffsets.ForEach(work.WriteU32); + + // Flush data to the real stream + writer.Write(work.Buffer, work.Length); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/Blocks/AnimationShareBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/Blocks/AnimationShareBlock.cs new file mode 100644 index 0000000..8e6cbf6 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/Blocks/AnimationShareBlock.cs @@ -0,0 +1,49 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary.Blocks +{ + /// + /// Layout animation share block + /// + [BinaryBlockProfile( + signature: "pah1", + minVersion: 10 + )] + public sealed class AnimationShareBlock : TNW4RBinaryBlock + { + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + throw new FileNotSupportedException( + "AnimationShare block is not yet supported"); + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + throw new FileNotSupportedException( + "AnimationShare block is not yet supported"); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + throw new FileNotSupportedException( + "AnimationShare block is not yet supported"); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/Blocks/AnimationTagBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/Blocks/AnimationTagBlock.cs new file mode 100644 index 0000000..cc87536 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Binary/Blocks/AnimationTagBlock.cs @@ -0,0 +1,49 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary.Blocks +{ + /// + /// Layout animation tag block + /// + [BinaryBlockProfile( + signature: "pat1", + minVersion: 10 + )] + public sealed class AnimationTagBlock : TNW4RBinaryBlock + { + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + throw new FileNotSupportedException( + "AnimationTag block is not yet supported"); + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + throw new FileNotSupportedException( + "AnimationTag block is not yet supported"); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + throw new FileNotSupportedException( + "AnimationTag block is not yet supported"); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Data/AnimationDataModel.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Data/AnimationDataModel.cs new file mode 100644 index 0000000..c788c96 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Data/AnimationDataModel.cs @@ -0,0 +1,67 @@ +using LibWorkBench.API.NW4R.LayoutLib; +using LibWorkBench.Formats.NW4R.Details; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Binary.Blocks; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Data +{ + /// + /// Layout animation data-view model + /// + public sealed class AnimationDataModel : TNW4RDataModel + { + /// + /// Number of frames in this animation + /// + public ushort Length { get; set; } = 0; + + /// + /// Whether this animation should loop + /// + public bool Loop { get; set; } = false; + + /// + /// Names of all texture resources required by this animation + /// + public List TextureNames { get; set; } = new(); + + /// + /// Animation contents + /// + public List Contents { get; set; } = new(); + + /// + /// Deserializes the contents of this model from a file + /// + /// Stream to the JSON file + public override void Load(JsonFileReader reader) + { + reader.Deserialize(this); + } + + /// + /// Serializes the contents of this model to a file + /// + /// Stream to the JSON file + public override void Dump(JsonFileWriter writer) + { + writer.Serialize(this); + } + + /// + /// Updates this model to match the contents of the binary-view model + /// + /// Binary-view model + public override void OnSync(NW4RBinaryModel binaryModel) + { + AnimationBinaryModel src = (AnimationBinaryModel)binaryModel; + + AnimationInfoBlock animInfo = src.GetOne(); + Length = animInfo.Length; + Loop = animInfo.Loop; + Contents = animInfo.Contents; + TextureNames = animInfo.TextureNames; + } + } +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimContentKind.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimContentKind.cs new file mode 100644 index 0000000..8c353d7 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimContentKind.cs @@ -0,0 +1,18 @@ +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types +{ + /// + /// Animation content type + /// + public enum AnimContentKind + { + /// + /// Animation targets a pane by name + /// + Pane, + + /// + /// Animation targets a material by name + /// + Material + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimInfoKind.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimInfoKind.cs new file mode 100644 index 0000000..d87274a --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimInfoKind.cs @@ -0,0 +1,43 @@ +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types +{ + /// + /// Animation info type + /// + public enum AnimInfoKind + { + /// + /// Pane S/R/T transformation animation + /// + PaneSrt, + + /// + /// Pane visibility animation + /// + PaneVis, + + /// + /// Vertex color animation + /// + VtxClr, + + /// + /// Material color animation + /// + MatClr, + + /// + /// Texture S/R/T transformation animation + /// + TexSrt, + + /// + /// Texture pattern animation + /// + TexPat, + + /// + /// Indirect texture S/R/T transformation animation + /// + IndTexSrt + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimTargetElement.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimTargetElement.cs new file mode 100644 index 0000000..2bca2cf --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimTargetElement.cs @@ -0,0 +1,373 @@ +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types +{ + /// + /// Pane S/R/T transformation animation target element + /// + public enum AnimTargetElementPaneSrt + { + /// + /// Translation x-component + /// + TransX, + + /// + /// Translation y-component + /// + TransY, + + /// + /// Translation z-component + /// + TransZ, + + /// + /// Rotation x-component + /// + RotateX, + + /// + /// Rotation y-component + /// + RotateY, + + /// + /// Rotation z-component + /// + RotateZ, + + /// + /// Scale x-component + /// + ScaleX, + + /// + /// Scale y-component + /// + ScaleY, + + /// + /// Size x-component (width) + /// + SizeX, + + /// + /// Size y-component (height) + /// + SizeY, + + /// + /// Opaqueness + /// + Alpha = 16 + } + + + /// + /// Pane visibility animation target element + /// + public enum AnimTargetElementPaneVis + { + /// + /// Pane visibility + /// + Visiblility, + } + + + /// + /// Vertex color animation target element + /// + public enum AnimTargetElementVtxClr + { + /// + /// Top-left vertex color, red component + /// + LeftTop_R, + + /// + /// Top-left vertex color, green component + /// + LeftTop_G, + + /// + /// Top-left vertex color, blue component + /// + LeftTop_B, + + /// + /// Top-left vertex color, alpha component + /// + LeftTop_A, + + /// + /// Top-right vertex color, red component + /// + RightTop_R, + + /// + /// Top-right vertex color, green component + /// + RightTop_G, + + /// + /// Top-right vertex color, blue component + /// + RightTop_B, + + /// + /// Top-right vertex color, alpha component + /// + RightTop_A, + + /// + /// Bottom-left vertex color, red component + /// + LeftBottom_R, + + /// + /// Bottom-left vertex color, green component + /// + LeftBottom_G, + + /// + /// Bottom-left vertex color, blue component + /// + LeftBottom_B, + + /// + /// Bottom-left vertex color, alpha component + /// + LeftBottom_A, + + /// + /// Bottom-right vertex color, red component + /// + RightBottom_R, + + /// + /// Bottom-right vertex color, green component + /// + RightBottom_G, + + /// + /// Bottom-right vertex color, blue component + /// + RightBottom_B, + + /// + /// Bottom-right vertex color, alpha component + /// + RightBottom_A, + } + + + /// + /// Material color animation target element + /// + public enum AnimTargetElementMatClr + { + /// + /// Material color, red component + /// + Material_R, + + /// + /// Material color, green component + /// + Material_G, + + /// + /// Material color, blue component + /// + Material_B, + + /// + /// Material color, alpha component + /// + Material_A, + + /// + /// TEV color register 0, red component + /// + Tev0_R, + + /// + /// TEV color register 0, green component + /// + Tev0_G, + + /// + /// TEV color register 0, blue component + /// + Tev0_B, + + /// + /// TEV color register 0, alpha component + /// + Tev0_A, + + /// + /// TEV color register 1, red component + /// + Tev1_R, + + /// + /// TEV color register 1, green component + /// + Tev1_G, + + /// + /// TEV color register 1, blue component + /// + Tev1_B, + + /// + /// TEV color register 1, alpha component + /// + Tev1_A, + + /// + /// TEV color register 2, red component + /// + Tev2_R, + + /// + /// TEV color register 2, green component + /// + Tev2_G, + + /// + /// TEV color register 2, blue component + /// + Tev2_B, + + /// + /// TEV color register 2, alpha component + /// + Tev2_A, + + /// + /// TEV constant color register 0, red component + /// + TevK0_R, + + /// + /// TEV constant color register 0, green component + /// + TevK0_G, + + /// + /// TEV constant color register 0, blue component + /// + TevK0_B, + + /// + /// TEV constant color register 0, alpha component + /// + TevK0_A, + + /// + /// TEV constant color register 1, red component + /// + TevK1_R, + + /// + /// TEV constant color register 1, green component + /// + TevK1_G, + + /// + /// TEV constant color register 1, blue component + /// + TevK1_B, + + /// + /// TEV constant color register 1, alpha component + /// + TevK1_A, + + /// + /// TEV constant color register 2, red component + /// + TevK2_R, + + /// + /// TEV constant color register 2, green component + /// + TevK2_G, + + /// + /// TEV constant color register 2, blue component + /// + TevK2_B, + + /// + /// TEV constant color register 2, alpha component + /// + TevK2_A, + + /// + /// TEV constant color register 3, red component + /// + TevK3_R, + + /// + /// TEV constant color register 3, green component + /// + TevK3_G, + + /// + /// TEV constant color register 3, blue component + /// + TevK3_B, + + /// + /// TEV constant color register 3, alpha component + /// + TevK3_A, + } + + + /// + /// Texture pattern animation target element + /// + public enum AnimTargetElementTexPat + { + /// + /// Texture image + /// + Image + } + + + /// + /// Texture S/R/T transformation animation target element + /// + public enum AnimTargetElementTexSrt + { + /// + /// Translation x-component + /// + TransX, + + /// + /// Translation y-component + /// + TransY, + + /// + /// Rotation + /// + Rotate, + + /// + /// Scale x-component + /// + ScaleX, + + /// + /// Scale y-component + /// + ScaleY + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimationTargetImplement.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimationTargetImplement.cs new file mode 100644 index 0000000..9283784 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/AnimationTargetImplement.cs @@ -0,0 +1,60 @@ +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types.Details; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types +{ + /// + /// Pane S/R/T transformation animation target + /// + public sealed class AnimationTargetPaneSrt + : AnimationTarget + { + } + + /// + /// Pane visibility animation target + /// + public sealed class AnimationTargetPaneVis + : AnimationTarget + { + } + + /// + /// Pane vertex color animation target + /// + public sealed class AnimationTargetVtxClr + : AnimationTarget + { + } + + /// + /// Pane material color animation target + /// + public sealed class AnimationTargetMatClr + : AnimationTarget + { + } + + /// + /// Pane texture S/R/T transformation animation target + /// + public sealed class AnimationTargetTexSrt + : AnimationTarget + { + } + + /// + /// Pane texture pattern animation target + /// + public sealed class AnimationTargetTexPat + : AnimationTarget + { + } + + /// + /// Pane indirect texture S/R/T transformation animation target + /// + public sealed class AnimationTargetIndTexSrt + : AnimationTarget + { + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/Details/AnimationTarget.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/Details/AnimationTarget.cs new file mode 100644 index 0000000..08ea0de --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/Details/AnimationTarget.cs @@ -0,0 +1,114 @@ +using LibWorkBench.Core; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types.Details +{ + /// + /// Specialized template for layout animation targets + /// + public abstract class AnimationTarget : AnimationTargetImpl, IUseBinary + where TAnimTarget : Enum + where TKeyFrame : KeyFrameImpl, new() + { + /// + /// Target element type + /// + // TODO(kiwi) Better way to set default value? + public TAnimTarget TargetType { get; set; } = (TAnimTarget)(dynamic)0; + + /// + /// Animation keyframes + /// + public List KeyFrames { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public override void Read(ReadStream reader) + { + // Keyframe offsets are relative to this target + long targetPos = (long)reader.Position; + + TargetID = reader.ReadU8(); + TargetType = (TAnimTarget)(dynamic)reader.ReadU8(); + + // TODO(kiwi) Can we send KeyType as a template argument? + KeyFrameImpl.Type curveType = (KeyFrameImpl.Type)reader.ReadU8(); + if (curveType != new TKeyFrame().KeyType) + { + throw new FileBrokenException("Not for this class"); + } + + reader.Align(4); + + ushort keyNum = reader.ReadU16(); + reader.Align(4); + + uint keysOffset = reader.ReadU32(); + if ((ulong)targetPos + keysOffset > reader.Length) + { + throw new FileBrokenException("Invalid keyframe offset"); + } + + // Parse keyframes + reader.Seek(targetPos + keysOffset, SeekOrigin.Begin); + + for (uint i = 0; i < keyNum; i++) + { + TKeyFrame frame = new(); + frame.Read(reader); + KeyFrames.Add(frame); + } + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public override void Write(WriteStream writer) + { + WorkMemWriter work = new(new BinaryCharEncoding(), + writer.Endian); + + if (KeyFrames.Count > ushort.MaxValue) + { + throw new FileBrokenException("Too many keyframes"); + } + + // Since they all match, we can assume the type from the first one + KeyFrameImpl.Type keyType = KeyFrames.First().KeyType; + + if (KeyFrames.Any(it => it.KeyType != keyType)) + { + throw new FileBrokenException("Cannot mix types of keyframes"); + } + + work.WriteU8(TargetID); + work.WriteU8((byte)(dynamic)TargetType); + + work.WriteU8((byte)keyType); + work.Align(4); + + work.WriteU16((ushort)KeyFrames.Count); + work.Align(4); + + // Reserve space for keyframe offset + long keyOffsetPos = (long)work.Position; + work.WriteDebugFill(sizeof(uint)); + + // Write keyframe data + uint keyOffset = (uint)work.Position; + KeyFrames.ForEach(it => it.Write(work)); + + // Go back and fix keyframe offset + work.Seek(keyOffsetPos, SeekOrigin.Begin); + work.WriteU32(keyOffset); + + // Flush data to the real stream + writer.Write(work.Buffer, work.Length); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/Details/AnimationTargetImpl.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/Details/AnimationTargetImpl.cs new file mode 100644 index 0000000..4626fb5 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/Details/AnimationTargetImpl.cs @@ -0,0 +1,39 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types.Details +{ + /// + /// Base class for layout animation targets + /// + [JsonPolymorphic(TypeDiscriminatorPropertyName = "kind")] + [JsonDerivedType(typeof(AnimationTargetPaneSrt), typeDiscriminator: "pane_srt")] + [JsonDerivedType(typeof(AnimationTargetPaneVis), typeDiscriminator: "pane_vis")] + [JsonDerivedType(typeof(AnimationTargetVtxClr), typeDiscriminator: "vertex_color")] + [JsonDerivedType(typeof(AnimationTargetMatClr), typeDiscriminator: "material_color")] + [JsonDerivedType(typeof(AnimationTargetTexSrt), typeDiscriminator: "texture_srt")] + [JsonDerivedType(typeof(AnimationTargetTexPat), typeDiscriminator: "texture_pattern")] + [JsonDerivedType(typeof(AnimationTargetIndTexSrt), typeDiscriminator: "indirect_texture_srt")] + public abstract class AnimationTargetImpl : IUseBinary + { + /// + /// Target element index + /// + [JsonPropertyOrder(int.MinValue)] + public byte TargetID { get; set; } = 0; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public abstract void Read(ReadStream reader); + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public abstract void Write(WriteStream writer); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/Details/KeyFrameImpl.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/Details/KeyFrameImpl.cs new file mode 100644 index 0000000..77373ff --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/Details/KeyFrameImpl.cs @@ -0,0 +1,70 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types.Details +{ + /// + /// Base class for animation key frames + /// + [JsonPolymorphic(TypeDiscriminatorPropertyName = "curve")] + [JsonDerivedType(typeof(StepKey), typeDiscriminator: "step")] + [JsonDerivedType(typeof(HermiteKey), typeDiscriminator: "hermite")] + public abstract class KeyFrameImpl : IUseBinary + { + /// + /// Key frame type + /// + public enum Type + { + /// + /// Value is constant + /// + None, + + /// + /// Value changes through linear frame values + /// + Step, + + /// + /// Value changes through Hermite interpolation + /// + Hermite + } + + /// + /// Key frame type + /// + [JsonPropertyOrder(int.MinValue)] + public Type KeyType { get; private set; } = Type.None; + + /// + /// Key frame index + /// + [JsonPropertyOrder(int.MinValue + 1)] + public float Frame { get; set; } = 0.0f; + + /// + /// Constructor + /// + /// Key frame type + public KeyFrameImpl(Type type) + { + KeyType = type; + } + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public abstract void Read(ReadStream reader); + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public abstract void Write(WriteStream writer); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/HermiteKey.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/HermiteKey.cs new file mode 100644 index 0000000..8c8a569 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/HermiteKey.cs @@ -0,0 +1,51 @@ +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types.Details; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types +{ + /// + /// Hermite interpolation keyframe + /// + public sealed class HermiteKey : KeyFrameImpl + { + /// + /// Frame value + /// + public float Value { get; set; } = 0.0f; + + /// + /// Hermite slope + /// + public float Slope { get; set; } = 0.0f; + + /// + /// Constructor + /// + public HermiteKey() + : base(Type.Hermite) + { + } + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public override void Read(ReadStream reader) + { + Frame = reader.ReadF32(); + Value = reader.ReadF32(); + Slope = reader.ReadF32(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public override void Write(WriteStream writer) + { + writer.WriteF32(Frame); + writer.WriteF32(Value); + writer.WriteF32(Slope); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/StepKey.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/StepKey.cs new file mode 100644 index 0000000..a190435 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Types/StepKey.cs @@ -0,0 +1,46 @@ +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types.Details; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types +{ + /// + /// Linear step keyframe + /// + public sealed class StepKey : KeyFrameImpl + { + /// + /// Frame value + /// + public ushort Value { get; set; } = 0; + + /// + /// Constructor + /// + public StepKey() + : base(Type.Step) + { + } + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public override void Read(ReadStream reader) + { + Frame = reader.ReadF32(); + Value = reader.ReadU16(); + reader.Align(4); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public override void Write(WriteStream writer) + { + writer.WriteF32(Frame); + writer.WriteU16(Value); + writer.Align(4); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Utility/AnimationUtil.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Utility/AnimationUtil.cs new file mode 100644 index 0000000..86e8e70 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Animation/Utility/AnimationUtil.cs @@ -0,0 +1,84 @@ +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation; +using LibWorkBench.Formats.NW4R.LayoutLib.Animation.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Animation.Utility +{ + /// + /// Animation utilities + /// + public static class AnimationUtil + { + /// + /// Converts the specified animation info block signature into the corresponding enum value + /// + /// Animation info block signature + /// Animation info kind + /// Block signature is unknown + public static AnimInfoKind GetAnimInfoKind(string signature) + { + switch (signature) + { + case AnimationDefine.SIGNATURE_ANMPANESRT: + return AnimInfoKind.PaneSrt; + + case AnimationDefine.SIGNATURE_ANMPANEVIS: + return AnimInfoKind.PaneVis; + + case AnimationDefine.SIGNATURE_ANMVTXCLR: + return AnimInfoKind.VtxClr; + + case AnimationDefine.SIGNATURE_ANMMATCLR: + return AnimInfoKind.MatClr; + + case AnimationDefine.SIGNATURE_ANMTEXSRT: + return AnimInfoKind.TexSrt; + + case AnimationDefine.SIGNATURE_ANMTEXPAT: + return AnimInfoKind.TexPat; + + case AnimationDefine.SIGNATURE_ANMINDTEXSRT: + return AnimInfoKind.IndTexSrt; + + default: + throw new OperationException("Unknown signature"); + } + } + + /// + /// Converts the specified animation info kind into the corresponding block signature + /// + /// Animation info kind + /// Animation info block signature + /// Animation info kind is invalid + public static string GetAnimInfoSignature(AnimInfoKind kind) + { + switch (kind) + { + case AnimInfoKind.PaneSrt: + return AnimationDefine.SIGNATURE_ANMPANESRT; + + case AnimInfoKind.PaneVis: + return AnimationDefine.SIGNATURE_ANMPANEVIS; + + case AnimInfoKind.VtxClr: + return AnimationDefine.SIGNATURE_ANMVTXCLR; + + case AnimInfoKind.MatClr: + return AnimationDefine.SIGNATURE_ANMMATCLR; + + case AnimInfoKind.TexSrt: + return AnimationDefine.SIGNATURE_ANMTEXSRT; + + case AnimInfoKind.TexPat: + return AnimationDefine.SIGNATURE_ANMTEXPAT; + + case AnimInfoKind.IndTexSrt: + return AnimationDefine.SIGNATURE_ANMINDTEXSRT; + + default: + throw new OperationException("Invalid animation info kind"); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/BoundingBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/BoundingBlock.cs new file mode 100644 index 0000000..f6440cd --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/BoundingBlock.cs @@ -0,0 +1,13 @@ +using LibWorkBench.Attributes; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout bounding block + /// + [BinaryBlockProfile(signature: "bnd1")] + public sealed class BoundingBlock : PaneBlock + { + // Bounding provides no additional data beyond the base pane + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/Details/ResListBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/Details/ResListBlock.cs new file mode 100644 index 0000000..935dcaf --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/Details/ResListBlock.cs @@ -0,0 +1,121 @@ +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks.Details +{ + /// + /// Base class for resource list blocks + /// + public abstract class ResListBlock : TNW4RBinaryBlock + { + /// + /// Size of the binary resource entries (res::Font, res::Texture, etc.) + /// + private const uint RES_ENTRY_SIZE = 8; + + /// + /// Resource entry + /// + public class Entry + { + /// + /// Resource name + /// + public string Name { get; set; } = ""; + + /// + /// Resource type + /// + public byte Kind { get; set; } = 0; + + /// + /// Constructor + /// + /// Resource name + /// Resource type + public Entry(string name, byte kind = 0) + { + Name = name; + Kind = kind; + } + } + + /// + /// Resources described within this block + /// + public List Resources { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + Resources.Clear(); + + ushort entryNum = reader.ReadU16(); + reader.Align(4); + + // Start position is the base for name offsets + ulong startOffset = reader.Position; + + List offsetList = new(); + List kindList = new(); + + for (ushort i = 0; i < entryNum; i++) + { + offsetList.Add(reader.ReadU32()); + + kindList.Add(reader.ReadU8()); + reader.Align(4); + } + + // Resolve name string offsets + for (ushort i = 0; i < entryNum; i++) + { + reader.Seek((long)(startOffset + offsetList[i]), + SeekOrigin.Begin); + + Resources.Add(new( + name: reader.ReadString(), + kind: kindList[i] + )); + } + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + if (Resources.Count > ushort.MaxValue) + { + throw new FileBrokenException("Too many resources"); + } + + writer.WriteU16((ushort)Resources.Count); + writer.Align(4); + + // Calculate running offset for name strings + uint offset = (uint)Resources.Count * RES_ENTRY_SIZE; + + // Write resource entries + foreach (var it in Resources) + { + writer.WriteU32(offset); + + writer.WriteU8(it.Kind); + writer.Align(4); + + // Adjust offset for name (include null terminator) + offset += (uint)it.Name.Length + 1; + } + + // Write resource string pool + Resources.ForEach(it => writer.WriteString(it.Name)); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/FontListBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/FontListBlock.cs new file mode 100644 index 0000000..6045ad9 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/FontListBlock.cs @@ -0,0 +1,58 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks.Details; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout font list block + /// + [BinaryBlockProfile(signature: "fnl1")] + public class FontListBlock : ResListBlock + { + /// + /// Font set used when building the resource list + /// + private HashSet _fontWork = new(); + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + LayoutDataModel src = (LayoutDataModel)dataModel; + + Resources.Clear(); + + _fontWork.Clear(); + FindFonts(src.RootPane); + + // Original tools seem to sort these alphabetically + Resources.Sort((lhs, rhs) => lhs.Name.CompareTo(rhs.Name)); + } + + /// + /// Finds all unique font resources in the pane hierarchy + /// + /// Root pane + private void FindFonts(Pane pane) + { + // Only textboxes can reference font resources + if (pane.GetType() == typeof(TextBox)) + { + TextBox textBox = (TextBox)pane; + + // Don't include duplicate resources + if (!_fontWork.Contains(textBox.FontName)) + { + _fontWork.Add(textBox.FontName); + Resources.Add(new(textBox.FontName)); + } + } + + pane.Children.ForEach(FindFonts); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/GroupBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/GroupBlock.cs new file mode 100644 index 0000000..8068e08 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/GroupBlock.cs @@ -0,0 +1,141 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Core; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout group block + /// + [BinaryBlockProfile(signature: "grp1")] + public class GroupBlock : TNW4RBinaryBlock, IUseName, IUseHierarchy + { + /// + /// Group name + /// + public string Name { get; set; } = ""; + + /// + /// Names of all panes contained within this group + /// + public List PaneNames { get; set; } = new(); + + /// + /// Parent group + /// + public GroupBlock? Parent { get; set; } = null; + + /// + /// Child groups + /// + public List Children { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + Name = reader.ReadString( + maxlen: LayoutDefine.RES_NAME_LEN, + exact: true + ); + + ushort paneNum = reader.ReadU16(); + reader.Align(4); + + for (ushort i = 0; i < paneNum; i++) + { + string paneName = reader.ReadString( + maxlen: LayoutDefine.RES_NAME_LEN, + exact: true + ); + + PaneNames.Add(paneName); + } + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + writer.WriteString( + Name, + maxlen: LayoutDefine.RES_NAME_LEN, + terminate: false, + exact: true + ); + + if (PaneNames.Count > ushort.MaxValue) + { + throw new FileBrokenException("Too many pane names"); + } + + writer.WriteU16((ushort)PaneNames.Count); + writer.Align(4); + + foreach (var it in PaneNames) + { + writer.WriteString( + it, + maxlen: LayoutDefine.RES_NAME_LEN, + terminate: false, + exact: true + ); + } + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + LayoutDataModel src = (LayoutDataModel)dataModel; + + // This group will hold all children + SyncGroup(src.RootGroup); + } + + /// + /// Updates this block to match the contents of a data-view group + /// + /// Data-view group + /// Group data is invalid + private void SyncGroup(Group group) + { + Parent = null; + Children.Clear(); + + if (group.Name.Length > LayoutDefine.RES_NAME_LEN) + { + throw new FileBrokenException( + $"Group name is too long (> {LayoutDefine.RES_NAME_LEN} " + + $"characters): {group.Name}" + ); + } + + Name = group.Name; + PaneNames = group.PaneNames; + + foreach (var it in group.Children) + { + GroupBlock child = + Model!.CreateBlock(unmanaged: true); + + child.SyncGroup(it); + + child.Parent = this; + Children.Add(child); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/GroupEndBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/GroupEndBlock.cs new file mode 100644 index 0000000..d8a6a17 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/GroupEndBlock.cs @@ -0,0 +1,39 @@ +using LibWorkBench.Attributes; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout group children end block + /// + [BinaryBlockProfile(signature: "gre1")] + public sealed class GroupEndBlock : TNW4RBinaryBlock + { + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/GroupStartBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/GroupStartBlock.cs new file mode 100644 index 0000000..04dc2f2 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/GroupStartBlock.cs @@ -0,0 +1,36 @@ +using LibWorkBench.Attributes; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout group children start block + /// + [BinaryBlockProfile(signature: "grs1")] + public sealed class GroupStartBlock : TNW4RBinaryBlock + { + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/LayoutBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/LayoutBlock.cs new file mode 100644 index 0000000..c536c97 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/LayoutBlock.cs @@ -0,0 +1,63 @@ +using LibWorkBench.Attributes; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout main block + /// + [BinaryBlockProfile(signature: "lyt1")] + public class LayoutBlock : TNW4RBinaryBlock + { + /// + /// Position origin type + /// + public OriginType OriginType { get; set; } = OriginType.TopLeft; + + /// + /// Size of this layout + /// + public Size Size { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + OriginType = (OriginType)reader.ReadU8(); + reader.Align(4); + + Size.Read(reader); + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + writer.WriteU8((byte)OriginType); + writer.Align(4); + + Size.Write(writer); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + LayoutDataModel src = (LayoutDataModel)dataModel; + + OriginType = src.OriginType; + Size = src.Size; + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/MaterialListBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/MaterialListBlock.cs new file mode 100644 index 0000000..3c1897d --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/MaterialListBlock.cs @@ -0,0 +1,183 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.Details; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout material list block + /// + [BinaryBlockProfile(signature: "mat1")] + public class MaterialListBlock : TNW4RBinaryBlock + { + /// + /// Size of this block's header when saved in binary form + /// + public const int HEADER_SIZE = 12; + + /// + /// Material list + /// + public List Materials { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + // Material offsets are relative to the start of the block data + ulong startOffset = + reader.Position - NW4RBinaryBlockHeader.STRUCT_SIZE; + + ushort matNum = reader.ReadU16(); + reader.Align(4); + + List offsetList = new(); + for (uint i = 0; i < matNum; i++) + { + offsetList.Add(reader.ReadU32()); + } + + foreach (var it in offsetList) + { + reader.Seek((long)(startOffset + it), SeekOrigin.Begin); + + ResMaterial material = new(); + material.Read(reader); + Materials.Add(material); + } + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + WorkMemWriter work = new(new BinaryCharEncoding(), + writer.Endian); + + if (Materials.Count > ushort.MaxValue) + { + throw new FileBrokenException("Too many materials"); + } + + work.WriteU16((ushort)Materials.Count); + work.Align(4); + + // Reserve space for offset table + long offsetTablePos = (long)work.Position; + work.WriteDebugFill((ulong)Materials.Count * sizeof(uint)); + + // Calculate running offset for each material + List offsetList = new(); + foreach (var it in Materials) + { + // Offset includes the data block header + ulong offset = work.Position + + NW4RBinaryBlockHeader.STRUCT_SIZE; + + if (offset > uint.MaxValue) + { + throw new FileBrokenException("Material list is too large"); + } + + offsetList.Add((uint)offset); + it.Write(work); + } + + // Go back and fix the offset table + work.Seek(offsetTablePos, SeekOrigin.Begin); + offsetList.ForEach(work.WriteU32); + + // Flush data to the real stream + writer.Write(work.Buffer, work.Length); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + LayoutDataModel src = (LayoutDataModel)dataModel; + + Materials.Clear(); + HashSet names = new(); + + foreach (var it in src.Materials) + { + // Materials cannot have duplicate names + if (names.Contains(it.Name)) + { + throw new FileBrokenException( + $"Duplicate material name: {it.Name}"); + } + + Materials.Add(ConvertMaterial(it)); + } + } + + /// + /// Converts a data-view material to its binary representation + /// + /// Data-view material + /// Binary-view material + private ResMaterial ConvertMaterial(Material mat) + { + ResMaterial res = new(); + + res.Name = mat.Name; + res.TevColors = mat.TevColors; + res.TevKColors = mat.TevKColors; + res.TexMaps = mat.TexMaps.Select(ConvertTexMap).ToList(); + res.TexSrts = mat.TexSrts; + res.TexCoordGens = mat.TexCoordGens; + res.TevSwapTable = mat.TevSwapTable; + res.IndTexSrts = mat.IndTexSrts; + res.IndStages = mat.IndStages; + res.TevStages = mat.TevStages; + res.AlphaCompare = mat.AlphaCompare; + res.BlendMode = mat.BlendMode; + res.ChanCtrl = mat.ChanCtrl; + res.MaterialColor = mat.MaterialColor; + + return res; + } + + /// + /// Converts a data-view texture map to its binary representation + /// + /// Data-view texture map + /// Binary-view texture map + /// Invalid texture was provided + private ResTexMap ConvertTexMap(TexMap texMap) + { + ResTexMap res = new(); + + TextureListBlock texList = Model!.GetOne(); + + int index = texList.Resources.FindIndex( + it => it.Name == texMap.TextureName); + + if (index < 0) + { + throw new FileBrokenException( + $"Texture does not exist: {texMap.TextureName}"); + } + + res.TextureIndex = (ushort)index; + res.WrapS = texMap.WrapS; + res.WrapT = texMap.WrapT; + + return res; + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PaneBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PaneBlock.cs new file mode 100644 index 0000000..ffc5741 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PaneBlock.cs @@ -0,0 +1,248 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Core; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; +using LibWorkBench.Formats.NW4R.SystemLib.Types; +using LibWorkBench.Utility; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout pane block + /// + [BinaryBlockProfile(signature: "pan1")] + public class PaneBlock : TNW4RBinaryBlock, IUseName, IUseHierarchy + { + /// + /// Bit flag indices + /// + public enum Flag + { + /// + /// Controls whether the pane will be rendered + /// + Visible, + + /// + /// Controls whether the pane's alpha is influenced by its parent + /// + InfluencedAlpha, + + /// + /// Whether the pane's scale should be influenced by location adjust + /// + LocationAdjust + } + + /// + /// Bit flag array + /// + public BitFlag Flags { get; set; } = new(); + + /// + /// Base position configuration + /// + public BasePosition BasePosition { get; set; } = new(); + + /// + /// Opaqueness + /// + public byte Alpha { get; set; } = 0; + + /// + /// Pane name + /// + public string Name { get; set; } = ""; + + /// + /// Pane userdata + /// + public string UserData { get; set; } = ""; + + /// + /// Pane translation/position + /// + public VEC3 Translate { get; set; } = new(); + + /// + /// Pane rotation (in degrees) + /// + public VEC3 Rotate { get; set; } = new(); + + /// + /// Pane scale + /// + public VEC2 Scale { get; set; } = new(); + + /// + /// Pane size + /// + public Size Size { get; set; } = new(); + + /// + /// Parent pane + /// + public PaneBlock? Parent { get; set; } = null; + + /// + /// Child panes + /// + public List Children { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + Flags.SetDirect(reader.ReadU8()); + BasePosition.Read(reader); + + Alpha = reader.ReadU8(); + reader.Align(4); + + Name = reader.ReadString( + maxlen: LayoutDefine.RES_NAME_LEN, + exact: true + ); + + UserData = reader.ReadString( + maxlen: LayoutDefine.USERDATA_LEN, + exact: true + ); + + Translate.Read(reader); + Rotate.Read(reader); + Scale.Read(reader); + Size.Read(reader); + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + writer.WriteU8(Flags.GetDirect()); + BasePosition.Write(writer); + + writer.WriteU8(Alpha); + writer.Align(4); + + writer.WriteString( + Name, + maxlen: LayoutDefine.RES_NAME_LEN, + terminate: false, + exact: true + ); + + writer.WriteString( + UserData, + maxlen: LayoutDefine.USERDATA_LEN, + terminate: false, + exact: true + ); + + Translate.Write(writer); + Rotate.Write(writer); + Scale.Write(writer); + Size.Write(writer); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + LayoutDataModel src = (LayoutDataModel)dataModel; + + // This pane block will hold all children + SyncPane(src.RootPane); + } + + /// + /// Updates this block to match the contents of a data-view pane + /// + /// Data-view pane + /// Pane data is invalid + protected virtual void SyncPane(Pane pane) + { + Parent = null; + Children.Clear(); + + if (pane.Name.Length > LayoutDefine.RES_NAME_LEN) + { + throw new FileBrokenException( + $"Pane name is too long (> {LayoutDefine.RES_NAME_LEN} " + + $"characters): {pane.Name}" + ); + } + + if (pane.UserData.Length > LayoutDefine.USERDATA_LEN) + { + throw new FileBrokenException( + "Pane userdata is too long (> " + + $"{LayoutDefine.RES_NAME_LEN} characters): {pane.Name}" + ); + } + + Flags.MakeAllZero(); + Flags.ChangeBit(Flag.Visible, pane.Visible); + Flags.ChangeBit(Flag.InfluencedAlpha, pane.InfluencedAlpha); + Flags.ChangeBit(Flag.LocationAdjust, pane.LocationAdjust); + + BasePosition = pane.BasePosition; + Alpha = pane.Alpha; + + Name = pane.Name; + UserData = pane.UserData; + + Translate = pane.Translate; + Rotate = pane.Rotate; + Scale = pane.Scale; + Size = pane.Size; + + foreach (var it in pane.Children) + { + PaneBlock child = + Model!.CreateBlock(unmanaged: true); + + switch (it) + { + case Bounding bounding: + child = + Model!.CreateBlock(unmanaged: true); + break; + + case Picture picture: + child = + Model!.CreateBlock(unmanaged: true); + break; + + case TextBox textBox: + child = + Model!.CreateBlock(unmanaged: true); + break; + + case Window window: + child = + Model!.CreateBlock(unmanaged: true); + break; + } + + child.Model = Model!; + child.SyncPane(it); + + child.Parent = this; + Children.Add(child); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PaneEndBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PaneEndBlock.cs new file mode 100644 index 0000000..346d3fd --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PaneEndBlock.cs @@ -0,0 +1,39 @@ +using LibWorkBench.Attributes; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout pane children end block + /// + [BinaryBlockProfile(signature: "pae1")] + public sealed class PaneEndBlock : TNW4RBinaryBlock + { + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PaneStartBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PaneStartBlock.cs new file mode 100644 index 0000000..764ab77 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PaneStartBlock.cs @@ -0,0 +1,39 @@ +using LibWorkBench.Attributes; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout pane children start block + /// + [BinaryBlockProfile(signature: "pas1")] + public sealed class PaneStartBlock : TNW4RBinaryBlock + { + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PictureBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PictureBlock.cs new file mode 100644 index 0000000..5ee639c --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/PictureBlock.cs @@ -0,0 +1,113 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout picture block + /// + [BinaryBlockProfile(signature: "pic1")] + public class PictureBlock : PaneBlock + { + /// + /// Vertex colors + /// + public VertexColorSet VertexColors { get; set; } = new(); + + /// + /// Material list index + /// + public ushort MaterialIndex { get; set; } = 0; + + /// + /// Texture coordinates + /// + public List TexCoords { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + // Common pane attributes + base.DoRead(reader); + + VertexColors.Read(reader); + MaterialIndex = reader.ReadU16(); + + byte texCoordNum = reader.ReadU8(); + if (texCoordNum > (byte)GXTexCoordID.GX_MAX_TEXCOORD) + { + throw new FileBrokenException("Too many texture coordinates"); + } + + // Padding after texture coordinate count + reader.Align(4); + + for (uint i = 0; i < texCoordNum; i++) + { + TexCoord texCoord = new(); + texCoord.Read(reader); + TexCoords.Add(texCoord); + } + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + // Common pane attributes + base.DoWrite(writer); + + VertexColors.Write(writer); + writer.WriteU16(MaterialIndex); + + if (TexCoords.Count > (byte)GXTexCoordID.GX_MAX_TEXCOORD) + { + throw new FileBrokenException("Too many texture coordinates"); + } + + writer.WriteU8((byte)TexCoords.Count); + + // Padding after texture coordinate count + writer.Align(4); + + // Texture coordinate data + TexCoords.ForEach(it => it.Write(writer)); + } + + /// + /// Updates this block to match the contents of a data-view pane + /// + /// Data-view pane + /// Pane data is invalid + protected override void SyncPane(Pane pane) + { + // Common pane attributes + base.SyncPane(pane); + Picture picture = (Picture)pane; + + MaterialListBlock matList = Model!.GetOne(); + + int index = matList.Materials.FindIndex( + it => it.Name == picture.MaterialName); + + if (index < 0) + { + throw new FileBrokenException( + $"Material does not exist: {picture.MaterialName}"); + } + + VertexColors = picture.VertexColors; + MaterialIndex = (ushort)index; + TexCoords = picture.TexCoords; + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/TextBoxBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/TextBoxBlock.cs new file mode 100644 index 0000000..44beecc --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/TextBoxBlock.cs @@ -0,0 +1,209 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.Details; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout textbox block + /// + [BinaryBlockProfile(signature: "txt1")] + public class TextBoxBlock : PaneBlock + { + /// + /// Text buffer capacity, in bytes + /// + public ushort TextCapacity { get; set; } = 0; + + /// + /// Material list index + /// + public ushort MaterialIndex { get; set; } = 0; + + /// + /// Font list index + /// + public ushort FontIndex { get; set; } = 0; + + /// + /// Text base position + /// + public BasePosition TextPosition { get; set; } = new(); + + /// + /// Text alignment + /// + public TextAlignment TextAlignment { get; set; } = TextAlignment.Left; + + /// + /// Text vertex colors + /// + public TextColorSet TextColors { get; set; } = new(); + + /// + /// Text font size + /// + public Size FontSize { get; set; } = new(); + + /// + /// Spacing between characters + /// + public float CharSpace { get; set; } = 0.0f; + + /// + /// Spacing between lines + /// + public float LineSpace { get; set; } = 0.0f; + + /// + /// Text string contents + /// + public string TextContent { get; set; } = ""; + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + // Start position is the base for offsets + ulong startOffset = reader.Position; + + // Common pane attributes + base.DoRead(reader); + + TextCapacity = reader.ReadU16(); + ushort textBytes = reader.ReadU16(); + + MaterialIndex = reader.ReadU16(); + FontIndex = reader.ReadU16(); + + TextPosition.Read(reader); + TextAlignment = (TextAlignment)reader.ReadU8(); + + // Padding after text alignment + reader.Align(4); + + // Text offset is relative to the start of the block data + uint textOffset = + reader.ReadU32() - NW4RBinaryBlockHeader.STRUCT_SIZE; + + TextColors.Read(reader); + FontSize.Read(reader); + + CharSpace = reader.ReadF32(); + LineSpace = reader.ReadF32(); + + reader.Seek((long)(startOffset + textOffset), SeekOrigin.Begin); + + TextContent = reader.ReadWideString( + maxlen: textBytes / sizeof(ushort)); + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + WorkMemWriter work = new(new BinaryCharEncoding(), + writer.Endian); + + // Common pane attributes + base.DoWrite(work); + + // Null terminator is included in the byte size + uint textBytes = ((uint)TextContent.Length + 1) * sizeof(ushort); + if (textBytes > ushort.MaxValue) + { + throw new FileBrokenException("Text content is too long"); + } + + // Capacity must at least fit the text content + TextCapacity = Math.Max(TextCapacity, (ushort)textBytes); + + work.WriteU16(TextCapacity); + work.WriteU16((ushort)textBytes); + + work.WriteU16(MaterialIndex); + work.WriteU16(FontIndex); + + TextPosition.Write(work); + work.WriteU8((byte)TextAlignment); + + // Padding after text alignment + work.Align(4); + + // Reserve space for text offset + long textOffsetPos = (long)work.Position; + work.WriteDebugFill(sizeof(uint)); + + TextColors.Write(work); + FontSize.Write(work); + + work.WriteF32(CharSpace); + work.WriteF32(LineSpace); + + uint textOffset = + (uint)work.Position + NW4RBinaryBlockHeader.STRUCT_SIZE; + + work.WriteWideString(TextContent); + + // Go back and fix the text offset + work.Seek(textOffsetPos, SeekOrigin.Begin); + work.WriteU32(textOffset); + + // Flush data to the real stream + writer.Write(work.Buffer, work.Length); + } + + /// + /// Updates this block to match the contents of a data-view pane + /// + /// Data-view pane + /// Pane data is invalid + protected override void SyncPane(Pane pane) + { + // Common pane attributes + base.SyncPane(pane); + TextBox textBox = (TextBox)pane; + + MaterialListBlock matList = Model!.GetOne(); + + int matIndex = matList.Materials.FindIndex( + it => it.Name == textBox.MaterialName); + + if (matIndex < 0) + { + throw new FileBrokenException( + $"Material does not exist: {textBox.MaterialName}"); + } + + FontListBlock fontList = Model!.GetOne(); + + int fontIndex = fontList.Resources.FindIndex( + it => it.Name == textBox.FontName); + + if (fontIndex < 0) + { + throw new FileBrokenException( + $"Font does not exist: {textBox.FontName}"); + } + + TextCapacity = textBox.TextCapacity; + MaterialIndex = (ushort)matIndex; + FontIndex = (ushort)fontIndex; + TextPosition = textBox.TextPosition; + TextAlignment = textBox.TextAlignment; + TextColors = textBox.TextColors; + FontSize = textBox.FontSize; + CharSpace = textBox.CharSpace; + LineSpace = textBox.LineSpace; + TextContent = textBox.TextContent; + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/TextureListBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/TextureListBlock.cs new file mode 100644 index 0000000..202e027 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/TextureListBlock.cs @@ -0,0 +1,42 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks.Details; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout texture list block + /// + [BinaryBlockProfile(signature: "txl1")] + public class TextureListBlock : ResListBlock + { + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + LayoutDataModel src = (LayoutDataModel)dataModel; + + Resources.Clear(); + HashSet names = new(); + + foreach (var mat in src.Materials) + { + foreach (var tex in mat.TexMaps) + { + // Don't include duplicate resources + if (!names.Contains(tex.TextureName)) + { + names.Add(tex.TextureName); + Resources.Add(new(tex.TextureName)); + } + } + } + + // Original tools seem to sort these alphabetically + Resources.Sort((lhs, rhs) => lhs.Name.CompareTo(rhs.Name)); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/UserDataBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/UserDataBlock.cs new file mode 100644 index 0000000..1df1cea --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/UserDataBlock.cs @@ -0,0 +1,46 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout userdata block + /// + [BinaryBlockProfile(signature: "usd1")] + public class UserDataBlock : TNW4RBinaryBlock + { + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + throw new FileNotSupportedException( + "Userdata block is not yet supported"); + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + throw new FileNotSupportedException( + "Userdata block is not yet supported"); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void DoSync(NW4RDataModel dataModel) + { + throw new FileNotSupportedException( + "Userdata block is not yet supported"); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/WindowBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/WindowBlock.cs new file mode 100644 index 0000000..5e7f10c --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/Blocks/WindowBlock.cs @@ -0,0 +1,246 @@ +using LibWorkBench.Attributes; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.Details; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks +{ + /// + /// Layout window block + /// + [BinaryBlockProfile(signature: "wnd1")] + public class WindowBlock : PaneBlock + { + /// + /// Content inflation + /// + public WindowInflation Inflation { get; set; } = new(); + + /// + /// Window content + /// + public ResWindowContent Content { get; set; } = new(); + + /// + /// Texture coordinates + /// + public List TexCoords { get; set; } = new(); + + /// + /// Window frames + /// + public List Frames { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public override void DoRead(ReadStream reader) + { + // Frame offsets are relative to the start of the block data + ulong startOffset = + reader.Position - NW4RBinaryBlockHeader.STRUCT_SIZE; + + // Common pane attributes + base.DoRead(reader); + + Inflation.Read(reader); + + byte frameNum = reader.ReadU8(); + reader.Align(4); + + uint contentOffset = reader.ReadU32(); + uint frameOffsetTblOffset = reader.ReadU32(); + + // Seek to window content + reader.Seek((long)(startOffset + contentOffset), SeekOrigin.Begin); + Content.Read(reader); + + // Texture coordinates follow the window content + for (uint i = 0; i < Content.TexCoordNum; i++) + { + TexCoord texCoord = new(); + texCoord.Read(reader); + TexCoords.Add(texCoord); + } + + // Seek to frame offset table + reader.Seek((long)(startOffset + frameOffsetTblOffset), + SeekOrigin.Begin); + + List offsetList = new(); + for (uint i = 0; i < frameNum; i++) + { + offsetList.Add(reader.ReadU32()); + } + + // Use offsets to read window frame data + foreach (var it in offsetList) + { + reader.Seek((long)(startOffset + it), SeekOrigin.Begin); + + ResWindowFrame frame = new(); + frame.Read(reader); + Frames.Add(frame); + } + } + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public override void DoWrite(WriteStream writer) + { + WorkMemWriter work = new(new BinaryCharEncoding(), + writer.Endian); + + // Common pane attributes + base.DoWrite(work); + + Inflation.Write(work); + + if (Frames.Count > byte.MaxValue) + { + throw new FileBrokenException("Too many window frames"); + } + + work.WriteU8((byte)Frames.Count); + work.Align(4); + + // Reserve space for content offset + long contentOffsetPos = (long)work.Position; + work.WriteDebugFill(sizeof(uint)); + + // Reserve space for frame offset table offset + long frameOffsetTblOffsetPos = (long)work.Position; + work.WriteDebugFill(sizeof(uint)); + + if (TexCoords.Count > byte.MaxValue) + { + throw new FileBrokenException("Too many texture coordinates"); + } + + Content.TexCoordNum = (byte)TexCoords.Count; + + uint contentOffset = (uint)work.Position; + Content.Write(work); + + // Texture coordinates follow the window content + TexCoords.ForEach(it => it.Write(work)); + + // Reserve space for frame offset table + long frameOffsetTblPos = (long)work.Position; + work.WriteDebugFill((ulong)(sizeof(uint) * Frames.Count)); + + List offsetList = new(); + foreach (var it in Frames) + { + offsetList.Add((uint)work.Position); + it.Write(work); + } + + // Go back and fix the content offset + work.Seek(contentOffsetPos, SeekOrigin.Begin); + // Offset includes the data block header + work.WriteU32(contentOffset + NW4RBinaryBlockHeader.STRUCT_SIZE); + + // Go back and fix the frame offset table offset + work.Seek(frameOffsetTblOffsetPos, SeekOrigin.Begin); + // Offset includes the data block header + work.WriteU32((uint)frameOffsetTblPos + + NW4RBinaryBlockHeader.STRUCT_SIZE); + + // Go back and fix the frame offset table + work.Seek(frameOffsetTblPos, SeekOrigin.Begin); + // Frame offset includes the data block header + offsetList.ForEach( + it => work.WriteU32(it + NW4RBinaryBlockHeader.STRUCT_SIZE)); + + // Flush data to the real stream + writer.Write(work.Buffer, work.Length); + } + + /// + /// Updates this block to match the contents of a data-view pane + /// + /// Data-view pane + /// Pane data is invalid + protected override void SyncPane(Pane pane) + { + // Common pane attributes + base.SyncPane(pane); + Window window = (Window)pane; + + Inflation = window.Inflation; + Content = ConvertWindowConvent(window.Content); + TexCoords = window.Content.TexCoords; + Frames = window.Frames.Select(ConvertWindowFrame).ToList(); + } + + /// + /// Converts data-view window content into its binary-view representation + /// + /// Data-view window content + /// Binary-view window content + /// Content material is invalid + /// Content holds too many texture coordinates + private ResWindowContent ConvertWindowConvent(WindowContent content) + { + ResWindowContent res = new(); + + MaterialListBlock matList = Model!.GetOne(); + + int index = matList.Materials.FindIndex( + it => it.Name == content.MaterialName); + + if (index < 0) + { + throw new FileBrokenException( + $"Material does not exist: {content.MaterialName}"); + } + + if (content.TexCoords.Count > byte.MaxValue) + { + throw new FileBrokenException( + "Too many texture coordinates"); + } + + res.VertexColors = content.VertexColors; + res.MaterialIndex = (ushort)index; + res.TexCoordNum = (byte)content.TexCoords.Count; + + return res; + } + + /// + /// Converts a data-view window frame into its binary-view representation + /// + /// Data-view window frame + /// Binary-view window frame + /// Frame material is invalid + private ResWindowFrame ConvertWindowFrame(WindowFrame frame) + { + ResWindowFrame res = new(); + + MaterialListBlock matList = Model!.GetOne(); + + int index = matList.Materials.FindIndex( + it => it.Name == frame.MaterialName); + + if (index < 0) + { + throw new FileBrokenException( + $"Material does not exist: {frame.MaterialName}"); + } + + res.MaterialIndex = (ushort)index; + res.TextureFlip = frame.TextureFlip; + + return res; + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/LayoutBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/LayoutBinaryModel.cs new file mode 100644 index 0000000..40fa97b --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/LayoutBinaryModel.cs @@ -0,0 +1,286 @@ +using LibWorkBench.API.NW4R.LayoutLib; +using LibWorkBench.Attributes; +using LibWorkBench.Core.Models.Binary.Details; +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary +{ + /// + /// Layout binary-view model + /// + [BinaryModelProfile( + signature: "RLYT", + versions: [8, 10], + alignment: NW4RDefine.BLOCK_ALIGNMENT + )] + public sealed class LayoutBinaryModel + : TNW4RBinaryModel + { + /// + /// Current parent pane (for use while parsing) + /// + private PaneBlock? _parentWork = null; + + /// + /// Most recent pane (for use while parsing) + /// + private PaneBlock? _prevWork = null; + + /// + /// Root of the pane hierarchy + /// + private PaneBlock? _rootPane = null; + + /// + /// Root of the group hierarchy + /// + private GroupBlock? _rootGroup = null; + + /// + /// Deserializes the contents of this model from a file (derived implementation) + /// + /// Binary stream to the file + public override void OnRead(ReadStream reader) + { + } + + /// + /// Serializes the contents of this model to a file (derived implementation) + /// + /// Binary stream to the file + public override void OnWrite(WriteStream writer) + { + // Remove virtual block types + RemoveAll(); + RemoveAll(); + RemoveAll(); + RemoveAll(); + } + + /// + /// Updates this model to match the contents of the data-view model + /// + /// Data-view model + public override void OnSync(NW4RDataModel dataModel) + { + LayoutDataModel src = (LayoutDataModel)dataModel; + + GetOne(create: true).Sync(src); + + GetOne(create: true).Sync(src); + GetOne(create: true).Sync(src); + GetOne(create: true).Sync(src); + + GetOne(create: true).Sync(src); + GetOne(create: true).Sync(src); + } + + /// + /// Allows additional logic after reading each block in the model + /// + /// Binary stream that contained the block data + /// Block that was just read + public override void ReadBlockCallback(ReadStream reader, BinaryBlock block) + { + switch (block) + { + case PaneBlock pane: + OnReadPaneBlock(reader, pane); + break; + + case GroupBlock group: + OnReadGroupBlock(reader, group); + break; + + case PaneStartBlock paneStart: + OnReadPaneStartBlock(reader, paneStart); + break; + + case PaneEndBlock paneEnd: + OnReadPaneEndBlock(reader, paneEnd); + break; + } + } + + /// + /// Allows additional logic after writing each block in the model + /// + /// Binary stream that will contain the block data + /// Block that was just written + public override void WriteBlockCallback(WriteStream writer, BinaryBlock block) + { + switch (block) + { + case PaneBlock pane: + OnWritePaneBlock(writer, pane); + break; + + case GroupBlock group: + OnWriteGroupBlock(writer, group); + break; + } + } + + /// + /// Performs additional hierarchy logic after reading a pane block + /// + /// Binary stream that contained the block data + /// Pane block that was just read + /// The root pane is missing or malformed + private void OnReadPaneBlock(ReadStream reader, PaneBlock pane) + { + // The first pane in the file must be the root pane + if (_rootPane == null) + { + // RootPane cannot be derived pane types + if (pane.GetType() != typeof(PaneBlock)) + { + throw new FileBrokenException( + "The root pane must only be a Pane"); + } + + if (pane.Name != "RootPane") + { + throw new FileBrokenException( + "The root pane must be named RootPane"); + } + + _rootPane = pane; + } + + // Child panes are owned by their parent (not by this model) + if (_parentWork != null) + { + _parentWork.Children.Add(pane); + pane.Parent = _parentWork; + + // Block list should only hold the root pane + GetAll(pane.GetType()).Remove(pane); + } + + _prevWork = pane; + } + + /// + /// Performs additional hierarchy logic after reading a group block + /// + /// Binary stream that contained the block data + /// Group block that was just read + /// The root group is missing or is malformed + private void OnReadGroupBlock(ReadStream reader, GroupBlock group) + { + // The first group in the file must be the root group + if (_rootGroup == null) + { + if (group.Name != "RootGroup") + { + throw new FileBrokenException( + "The root group must be named RootGroup"); + } + + _rootGroup = group; + } + // Child groups are owned by their parent (not by this model) + else + { + _rootGroup.Children.Add(group); + group.Parent = _rootGroup; + + // Block list should only hold the root group + GetAll().Remove(group); + } + } + + /// + /// Performs additional hierarchy logic after reading a pane start block + /// + /// Binary stream that contained the block data + /// Pane start block that was just read + private void OnReadPaneStartBlock(ReadStream reader, PaneStartBlock paneStart) + { + _parentWork = _prevWork; + } + + /// + /// Performs additional hierarchy logic after reading a pane end block + /// + /// Binary stream that contained the block data + /// Pane end block that was just read + /// The pane hierarchy is invalid + private void OnReadPaneEndBlock(ReadStream reader, PaneEndBlock paneEnd) + { + if (_prevWork == null || _parentWork == null) + { + throw new FileBrokenException("Pane child underflow"); + } + + _prevWork = _parentWork; + _parentWork = _prevWork.Parent; + } + + /// + /// Performs additional hierarchy logic after writing a pane block + /// + /// Binary stream that will contain the block data + /// Pane block that was just written + private void OnWritePaneBlock(WriteStream writer, PaneBlock pane) + { + if (pane.Children.Count == 0) + { + return; + } + + PaneStartBlock start + = CreateBlock(unmanaged: true); + + start.Write(writer); + + foreach (var it in pane.Children) + { + it.Write(writer); + writer.Align(Profile.Alignment); + + WriteBlockCallback(writer, it); + } + + PaneEndBlock end = + CreateBlock(unmanaged: true); + + end.Write(writer); + } + + /// + /// Performs additional hierarchy logic after writing a group block + /// + /// Binary stream that will contain the block data + /// Group block that was just written + private void OnWriteGroupBlock(WriteStream writer, GroupBlock group) + { + if (group.Children.Count == 0) + { + return; + } + + GroupStartBlock start + = CreateBlock(unmanaged: true); + + start.Write(writer); + + foreach (var it in group.Children) + { + it.Write(writer); + writer.Align(Profile.Alignment); + + WriteBlockCallback(writer, it); + } + + GroupEndBlock end = + CreateBlock(unmanaged: true); + + end.Write(writer); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/LayoutBlockFactory.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/LayoutBlockFactory.cs new file mode 100644 index 0000000..5cfc382 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/LayoutBlockFactory.cs @@ -0,0 +1,33 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary +{ + /// + /// Layout binary block factory + /// + public sealed class LayoutBlockFactory : BinaryBlockFactory + { + /// + /// Constructor + /// + public LayoutBlockFactory() + { + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + RegisterBlock(); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/MaterialResourceNum.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/MaterialResourceNum.cs new file mode 100644 index 0000000..07ec6a9 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/MaterialResourceNum.cs @@ -0,0 +1,157 @@ +using LibWorkBench.Core; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary +{ + /// + /// Material resource counts + /// + public sealed class MaterialResourceNum : IUseBinary + { + /// + /// Number of texture maps used by this material + /// + public byte TexMapNum { get; set; } = 0; + + /// + /// Number of texture S/R/T transformations used by this material + /// + public byte TexSrtNum { get; set; } = 0; + + /// + /// Number of texture coordinate generators used by this material + /// + public byte TexCoordGenNum { get; set; } = 0; + + /// + /// Whether this material uses a TEV swap table + /// + public bool HasTevSwapTable { get; set; } = false; + + /// + /// Number of indirect texture S/R/T transformations used by this material + /// + public byte IndTexSrtNum { get; set; } = 0; + + /// + /// Number of indirect stages used by this material + /// + public byte IndStageNum { get; set; } = 0; + + /// + /// Number of TEV stages used by this material + /// + public byte TevStageNum { get; set; } = 0; + + /// + /// Whether this material uses a visibility test + /// + public bool HasAlphaCompare { get; set; } = false; + + /// + /// Whether this material configures a blend mode + /// + public bool HasBlendMode { get; set; } = false; + + /// + /// Whether this material configures channels + /// + public bool HasChanCtrl { get; set; } = false; + + /// + /// Whether this material has a color + /// + public bool HasMatColor { get; set; } = false; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + uint packed = reader.ReadU32(); + + TexMapNum = (byte)(packed >> 0 & 0b1111); + TexSrtNum = (byte)(packed >> 4 & 0b1111); + TexCoordGenNum = (byte)(packed >> 8 & 0b1111); + HasTevSwapTable = (packed >> 12 & 0b1) != 0; + IndTexSrtNum = (byte)(packed >> 13 & 0b11); + IndStageNum = (byte)(packed >> 15 & 0b111); + TevStageNum = (byte)(packed >> 18 & 0b11111); + HasAlphaCompare = (packed >> 23 & 0b1) != 0; + HasBlendMode = (packed >> 24 & 0b1) != 0; + HasChanCtrl = (packed >> 25 & 0b1) != 0; + HasMatColor = (packed >> 27 & 0b1) != 0; + + Validate(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + Validate(); + + uint packed = 0; + + packed |= (uint)((TexMapNum & 0b1111) << 0); + packed |= (uint)((TexSrtNum & 0b1111) << 4); + packed |= (uint)((TexCoordGenNum & 0b1111) << 8); + packed |= (uint)((HasTevSwapTable ? 1 : 0) << 12); + packed |= (uint)((IndTexSrtNum & 0b11) << 13); + packed |= (uint)((IndStageNum & 0b111) << 15); + packed |= (uint)((TevStageNum & 0b11111) << 18); + packed |= (uint)((HasAlphaCompare ? 1 : 0) << 23); + packed |= (uint)((HasBlendMode ? 1 : 0) << 24); + packed |= (uint)((HasChanCtrl ? 1 : 0) << 25); + packed |= (uint)((HasMatColor ? 1 : 0) << 27); + + writer.WriteU32(packed); + } + + /// + /// Validates that all resource counts are within the expected range + /// + /// Resource configuration is invalid + private void Validate() + { + if (TexMapNum > (byte)GXTexMapID.GX_MAX_TEXMAP) + { + throw new FileBrokenException("Too many texture maps"); + } + + if (TexSrtNum > LayoutDefine.MAX_TEX_SRT) + { + throw new FileBrokenException( + "Too many texture S/R/T transformations"); + } + + if (TexCoordGenNum > (byte)GXTexCoordID.GX_MAX_TEXCOORD) + { + throw new FileBrokenException( + "Too many texture coordinate generators"); + } + + if (IndTexSrtNum > LayoutDefine.MAX_IND_SRT) + { + throw new FileBrokenException( + "Too many indirect texture S/R/T transformations"); + } + + if (IndStageNum > (byte)GXIndTexStageID.GX_MAX_INDTEXSTAGE) + { + throw new FileBrokenException("Too many indirect stages"); + } + + if (TevStageNum > (byte)GXTevStageID.GX_MAX_TEVSTAGE) + { + throw new FileBrokenException("Too many TEV stages"); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResMaterial.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResMaterial.cs new file mode 100644 index 0000000..331ee77 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResMaterial.cs @@ -0,0 +1,240 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary +{ + /// + /// Material configuration (binary-view) + /// + public sealed class ResMaterial : IUseBinary + { + /// + /// Material name + /// + public string Name { get; set; } = ""; + + /// + /// TEV color register settings + /// + public TevColorSet TevColors { get; set; } = new(); + + /// + /// TEV constant color register settings + /// + public TevKonstColorSet TevKColors { get; set; } = new(); + + /// + /// Texture map settings + /// + public List TexMaps { get; set; } = new(); + + /// + /// Texture S/R/T transformation settings + /// + public List TexSrts { get; set; } = new(); + + /// + /// Texture coordinate generator settings + /// + public List TexCoordGens { get; set; } = new(); + + /// + /// TEV color channel swap settings + /// + public TevSwapTable? TevSwapTable { get; set; } = null; + + /// + /// Indirect texture S/R/T transformation settings + /// + public List IndTexSrts { get; set; } = new(); + + /// + /// Indirect texture stages + /// + public List IndStages { get; set; } = new(); + + /// + /// TEV stages + /// + public List TevStages { get; set; } = new(); + + /// + /// Visibility test + /// + public AlphaCompare? AlphaCompare { get; set; } = null; + + /// + /// Blend mode settings + /// + public BlendMode? BlendMode { get; set; } = null; + + /// + /// Channel control settings + /// + public ChanCtrl? ChanCtrl { get; set; } = null; + + /// + /// Material color (GX_COLOR0A0) + /// + public GXColor? MaterialColor { get; set; } = null; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Name = reader.ReadString( + maxlen: LayoutDefine.MAT_NAME_LEN, + exact: true + ); + + TevColors.Read(reader); + TevKColors.Read(reader); + + // Resource num describes how the variable data looks + MaterialResourceNum resNum = new(); + resNum.Read(reader); + + for (uint i = 0; i < resNum.TexMapNum; i++) + { + ResTexMap texMap = new(); + texMap.Read(reader); + TexMaps.Add(texMap); + } + + for (uint i = 0; i < resNum.TexSrtNum; i++) + { + TexSrt texSrt = new(); + texSrt.Read(reader); + TexSrts.Add(texSrt); + } + + for (uint i = 0; i < resNum.TexCoordGenNum; i++) + { + TexCoordGen texCoordGen = new(); + texCoordGen.Read(reader); + TexCoordGens.Add(texCoordGen); + } + + if (resNum.HasChanCtrl) + { + ChanCtrl = new(); + ChanCtrl.Read(reader); + } + + if (resNum.HasMatColor) + { + MaterialColor = new(); + MaterialColor.Read(reader); + } + + if (resNum.HasTevSwapTable) + { + TevSwapTable = new(); + TevSwapTable.Read(reader); + } + + for (uint i = 0; i < resNum.IndTexSrtNum; i++) + { + TexSrt indTexSrt = new(); + indTexSrt.Read(reader); + IndTexSrts.Add(indTexSrt); + } + + for (uint i = 0; i < resNum.IndStageNum; i++) + { + IndirectStage indStage = new(); + indStage.Read(reader); + IndStages.Add(indStage); + } + + for (uint i = 0; i < resNum.TevStageNum; i++) + { + TevStage tevStage = new(); + tevStage.Read(reader); + TevStages.Add(tevStage); + } + + if (resNum.HasAlphaCompare) + { + AlphaCompare = new(); + AlphaCompare.Read(reader); + } + + if (resNum.HasBlendMode) + { + BlendMode = new(); + BlendMode.Read(reader); + } + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteString( + Name, + maxlen: LayoutDefine.MAT_NAME_LEN, + terminate: false, + exact: true + ); + + TevColors.Write(writer); + TevKColors.Write(writer); + + // Resource num describes how the variable data looks + MaterialResourceNum resNum = new(); + resNum.TexMapNum = (byte)TexMaps.Count; + resNum.TexSrtNum = (byte)TexSrts.Count; + resNum.TexCoordGenNum = (byte)TexCoordGens.Count; + resNum.HasTevSwapTable = TevSwapTable != null; + resNum.IndTexSrtNum = (byte)IndTexSrts.Count; + resNum.IndStageNum = (byte)IndStages.Count; + resNum.TevStageNum = (byte)TevStages.Count; + resNum.HasAlphaCompare = AlphaCompare != null; + resNum.HasBlendMode = BlendMode != null; + resNum.HasChanCtrl = ChanCtrl != null; + resNum.HasMatColor = MaterialColor != null; + resNum.Write(writer); + + TexMaps.ForEach(it => it.Write(writer)); + TexSrts.ForEach(it => it.Write(writer)); + TexCoordGens.ForEach(it => it.Write(writer)); + + if (TevSwapTable != null) + { + TevSwapTable.Write(writer); + } + + IndTexSrts.ForEach(it => it.Write(writer)); + IndStages.ForEach(it => it.Write(writer)); + TevStages.ForEach(it => it.Write(writer)); + + if (AlphaCompare != null) + { + AlphaCompare.Write(writer); + } + + if (BlendMode != null) + { + BlendMode.Write(writer); + } + + if (ChanCtrl != null) + { + ChanCtrl.Write(writer); + } + + if (MaterialColor != null) + { + MaterialColor.Write(writer); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResTexMap.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResTexMap.cs new file mode 100644 index 0000000..fcce669 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResTexMap.cs @@ -0,0 +1,49 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary +{ + /// + /// Material texture map (binary-view) + /// + public sealed class ResTexMap : IUseBinary + { + /// + /// Texture list index + /// + public ushort TextureIndex { get; set; } = 0; + + /// + /// Texture wrap mode (S) + /// + public GXTexWrapMode WrapS { get; set; } = GXTexWrapMode.GX_CLAMP; + + /// + /// Texture wrap mode (T) + /// + public GXTexWrapMode WrapT { get; set; } = GXTexWrapMode.GX_CLAMP; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + TextureIndex = reader.ReadU16(); + WrapS = (GXTexWrapMode)reader.ReadU8(); + WrapT = (GXTexWrapMode)reader.ReadU8(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU16(TextureIndex); + writer.WriteU8((byte)WrapS); + writer.WriteU8((byte)WrapT); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResWindowContent.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResWindowContent.cs new file mode 100644 index 0000000..9c3421e --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResWindowContent.cs @@ -0,0 +1,53 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary +{ + /// + /// Window content (binary-view) + /// + public sealed class ResWindowContent : IUseBinary + { + /// + /// Vertex colors + /// + public VertexColorSet VertexColors { get; set; } = new(); + + /// + /// Material list index + /// + public ushort MaterialIndex { get; set; } = 0; + + /// + /// Number of texture coordinates + /// + public byte TexCoordNum { get; set; } = 0; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + VertexColors.Read(reader); + + MaterialIndex = reader.ReadU16(); + TexCoordNum = reader.ReadU8(); + reader.Align(4); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + VertexColors.Write(writer); + + writer.WriteU16(MaterialIndex); + writer.WriteU8(TexCoordNum); + writer.Align(4); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResWindowFrame.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResWindowFrame.cs new file mode 100644 index 0000000..d900419 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Binary/ResWindowFrame.cs @@ -0,0 +1,48 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary +{ + /// + /// Window frame (binary-view) + /// + public sealed class ResWindowFrame : IUseBinary + { + /// + /// Material list index + /// + public ushort MaterialIndex { get; set; } = 0; + + /// + /// Texture flip type + /// + public TextureFlip TextureFlip { get; set; } = TextureFlip.None; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + MaterialIndex = reader.ReadU16(); + TextureFlip = (TextureFlip)reader.ReadU8(); + + // Padding after texture flip + reader.Align(4); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU16(MaterialIndex); + writer.WriteU8((byte)TextureFlip); + + // Padding after texture flip + writer.Align(4); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Bounding.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Bounding.cs new file mode 100644 index 0000000..8ebe3db --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Bounding.cs @@ -0,0 +1,10 @@ +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Bounding box + /// + public sealed class Bounding : Pane + { + // Bounding provides no additional data beyond the base pane + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Group.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Group.cs new file mode 100644 index 0000000..26ba814 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Group.cs @@ -0,0 +1,57 @@ +using LibWorkBench.Core; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Collection of UI panes + /// + public sealed class Group : IUseName, IUseHierarchy + { + /// + /// Group name + /// + public string Name { get; set; } = ""; + + /// + /// Names of all panes contained within this group + /// + public List PaneNames { get; set; } = new(); + + /// + /// Parent group + /// + [JsonIgnore] + public Group? Parent { get; set; } = null; + + /// + /// Child groups + /// + public List Children { get; set; } = new(); + + /// + /// Appends a new child of this group + /// + /// Child group + public void AppendChild(Group child) + { + Children.Add(child); + child.Parent = this; + } + + /// + /// Removes a child of this group + /// + /// Child group + public void RemoveChild(Group child) + { + Children.Remove(child); + + // Avoid clobbering other hierarchy + if (child.Parent == this) + { + child.Parent = null; + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/LayoutDataModel.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/LayoutDataModel.cs new file mode 100644 index 0000000..8bb1510 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/LayoutDataModel.cs @@ -0,0 +1,380 @@ +using LibWorkBench.API.NW4R.LayoutLib; +using LibWorkBench.Exceptions; +using LibWorkBench.Formats.NW4R.Details; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Binary.Blocks; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Layout data-view model + /// + public sealed class LayoutDataModel : TNW4RDataModel + { + /// + /// Texture names from the binary + /// + private List _textureNames = new(); + + /// + /// Font names from the binary + /// + private List _fontNames = new(); + + /// + /// Position origin type + /// + public OriginType OriginType { get; set; } = OriginType.TopLeft; + + /// + /// Size of this layout + /// + public Size Size { get; set; } = new(); + + /// + /// Root of the pane hierarchy + /// + public Pane RootPane { get; set; } = new(); + + /// + /// Root of the group hierarchy + /// + public Group RootGroup { get; set; } = new(); + + /// + /// Pane materials + /// + public List Materials { get; set; } = new(); + + /// + /// Constructor + /// + public LayoutDataModel() + { + RootPane.Name = "RootPane"; + RootGroup.Name = "RootGroup"; + } + + /// + /// Deserializes the contents of this model from a file + /// + /// Stream to the JSON file + public override void Load(JsonFileReader reader) + { + reader.Deserialize(this); + } + + /// + /// Serializes the contents of this model to a file + /// + /// Stream to the JSON file + public override void Dump(JsonFileWriter writer) + { + writer.Serialize(this); + } + + /// + /// Updates this model to match the contents of the binary-view model + /// + /// Binary-view model + public override void OnSync(NW4RBinaryModel binaryModel) + { + LayoutBinaryModel src = (LayoutBinaryModel)binaryModel; + + // Layout-wide configuration + LayoutBlock layout = src.GetOne(); + OriginType = layout.OriginType; + Size = layout.Size; + + TextureListBlock texList = src.GetOne(); + _textureNames.Clear(); + _textureNames = texList.Resources.Select(it => it.Name).ToList(); + + FontListBlock fontList = src.GetOne(); + _fontNames.Clear(); + _fontNames = fontList.Resources.Select(it => it.Name).ToList(); + + MaterialListBlock matList = src.GetOne(); + Materials.Clear(); + Materials = matList.Materials.Select(ConvertMaterial).ToList(); + + // Traverse the pane/group hierarchy + RootPane = ConvertPane(src.GetOne()); + RootGroup = ConvertGroup(src.GetOne()); + } + + /// + /// Converts a binary-view material to its data-view representation + /// + /// Binary-view material + /// Data-view material + private Material ConvertMaterial(ResMaterial res) + { + Material mat = new(); + + mat.Name = res.Name; + mat.TevColors = res.TevColors; + mat.TevKColors = res.TevKColors; + mat.TexMaps = res.TexMaps.Select(ConvertTexMap).ToList(); + mat.TexSrts = res.TexSrts; + mat.TexCoordGens = res.TexCoordGens; + mat.TevSwapTable = res.TevSwapTable; + mat.IndTexSrts = res.IndTexSrts; + mat.IndStages = res.IndStages; + mat.TevStages = res.TevStages; + mat.AlphaCompare = res.AlphaCompare; + mat.BlendMode = res.BlendMode; + mat.ChanCtrl = res.ChanCtrl; + mat.MaterialColor = res.MaterialColor; + + return mat; + } + + /// + /// Converts a binary-view pane to its data-view representation + /// + /// Binary-view pane + /// Data-view pane + private Pane ConvertPane(PaneBlock block) + { + switch (block) + { + case BoundingBlock bounding: + return ConvertBounding(bounding); + + case PictureBlock picture: + return ConvertPicture(picture); + + case TextBoxBlock textBox: + return ConvertTextBox(textBox); + + case WindowBlock window: + return ConvertWindow(window); + + default: + // Must be just the base Pane class + Pane pane = new(); + SyncPane(pane, block); + return pane; + } + } + + /// + /// Converts a binary-view bounding to its data-view representation + /// + /// Binary-view bounding + /// Data-view bounding + private Bounding ConvertBounding(BoundingBlock block) + { + Bounding bounding = new(); + + // Common pane attributes + SyncPane(bounding, block); + + return bounding; + } + + /// + /// Converts a binary-view picture to its data-view representation + /// + /// Binary-view picture + /// Data-view picture + private Picture ConvertPicture(PictureBlock block) + { + Picture picture = new(); + + // Common pane attributes + SyncPane(picture, block); + + if (block.MaterialIndex >= Materials.Count) + { + throw new FileBrokenException("Invalid material index"); + } + + picture.MaterialName = Materials[block.MaterialIndex].Name; + picture.VertexColors = block.VertexColors; + picture.TexCoords = block.TexCoords; + + return picture; + } + + /// + /// Converts a binary-view textbox to its data-view representation + /// + /// Binary-view textbox + /// Data-view textbox + private TextBox ConvertTextBox(TextBoxBlock block) + { + TextBox textBox = new(); + + // Common pane attributes + SyncPane(textBox, block); + + if (block.MaterialIndex >= Materials.Count) + { + throw new FileBrokenException("Invalid material index"); + } + if (block.FontIndex >= _fontNames.Count) + { + throw new FileBrokenException("Invalid font index"); + } + + textBox.MaterialName = Materials[block.MaterialIndex].Name; + textBox.FontName = _fontNames[block.FontIndex]; + + textBox.FontSize = block.FontSize; + textBox.CharSpace = block.CharSpace; + textBox.LineSpace = block.LineSpace; + textBox.TextContent = block.TextContent; + textBox.TextCapacity = block.TextCapacity; + textBox.TextPosition = block.TextPosition; + textBox.TextAlignment = block.TextAlignment; + textBox.TextColors = block.TextColors; + + return textBox; + } + + /// + /// Converts a binary-view window to its data-view representation + /// + /// Binary-view window + /// Data-view window + private Window ConvertWindow(WindowBlock block) + { + Window window = new(); + + // Common pane attributes + SyncPane(window, block); + + window.Content = ConvertWindowContent(block.Content); + window.Content.TexCoords = block.TexCoords; + + window.Inflation = block.Inflation; + window.Frames = block.Frames.Select(ConvertWindowFrame).ToList(); + + return window; + } + + /// + /// Converts a binary-view pane to its data-view representation + /// + /// Data-view pane + /// Binary-view pane + private void SyncPane(Pane pane, PaneBlock block) + { + pane.Parent = null; + pane.Children.Clear(); + + pane.Name = block.Name; + pane.UserData = block.UserData; + + pane.Visible = + block.Flags.GetBit(PaneBlock.Flag.Visible); + pane.InfluencedAlpha = + block.Flags.GetBit(PaneBlock.Flag.InfluencedAlpha); + pane.LocationAdjust = + block.Flags.GetBit(PaneBlock.Flag.LocationAdjust); + + pane.BasePosition = block.BasePosition; + pane.Alpha = block.Alpha; + pane.Translate = block.Translate; + pane.Rotate = block.Rotate; + pane.Scale = block.Scale; + pane.Size = block.Size; + + foreach (var it in block.Children) + { + Pane child = ConvertPane(it); + pane.AppendChild(child); + } + } + + /// + /// Converts a binary-view group to its data-view representation + /// + /// Binary-view group + /// Data-view group + private Group ConvertGroup(GroupBlock block) + { + Group group = new(); + + group.Name = block.Name; + group.PaneNames = block.PaneNames; + + foreach (var it in block.Children) + { + Group child = ConvertGroup(it); + group.AppendChild(child); + } + + return group; + } + + /// + /// Converts a binary-view texture map to its data-view representation + /// + /// Binary-view texture map + /// Data-view texture map + /// Texture index is invalid + private TexMap ConvertTexMap(ResTexMap res) + { + TexMap texMap = new(); + + if (res.TextureIndex >= _textureNames.Count) + { + throw new FileBrokenException("Invalid texture index"); + } + + texMap.TextureName = _textureNames[res.TextureIndex]; + texMap.WrapS = res.WrapS; + texMap.WrapT = res.WrapT; + + return texMap; + } + + /// + /// Converts binary-view window content to its data-view representation + /// + /// Binary-view window content + /// Data-view window content + /// Material index is invalid + private WindowContent ConvertWindowContent(ResWindowContent res) + { + WindowContent content = new(); + + if (res.MaterialIndex >= Materials.Count) + { + throw new FileBrokenException("Invalid material index"); + } + + content.MaterialName = Materials[res.MaterialIndex].Name; + content.VertexColors = res.VertexColors; + + // Caller is responsible for texture coordinates + return content; + } + + /// + /// Converts a binary-view window frame to its data-view representation + /// + /// Binary-view window frame + /// Data-view window frame + /// Material index is invalid + private WindowFrame ConvertWindowFrame(ResWindowFrame res) + { + WindowFrame frame = new(); + + if (res.MaterialIndex >= Materials.Count) + { + throw new FileBrokenException("Invalid material index"); + } + + frame.MaterialName = Materials[res.MaterialIndex].Name; + frame.TextureFlip = res.TextureFlip; + + return frame; + } + } +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Material.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Material.cs new file mode 100644 index 0000000..057b730 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Material.cs @@ -0,0 +1,81 @@ +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Pane material + /// + public sealed class Material + { + /// + /// Material name + /// + public string Name { get; set; } = ""; + + /// + /// TEV color register settings + /// + public TevColorSet TevColors { get; set; } = new(); + + /// + /// TEV constant color register settings + /// + public TevKonstColorSet TevKColors { get; set; } = new(); + + /// + /// Texture map settings + /// + public List TexMaps { get; set; } = new(); + + /// + /// Texture S/R/T transformation settings + /// + public List TexSrts { get; set; } = new(); + + /// + /// Texture coordinate generator settings + /// + public List TexCoordGens { get; set; } = new(); + + /// + /// TEV color channel swap settings + /// + public TevSwapTable? TevSwapTable { get; set; } = null; + + /// + /// Indirect texture S/R/T transformation settings + /// + public List IndTexSrts { get; set; } = new(); + + /// + /// Indirect texture stages + /// + public List IndStages { get; set; } = new(); + + /// + /// TEV stages + /// + public List TevStages { get; set; } = new(); + + /// + /// Visibility test + /// + public AlphaCompare? AlphaCompare { get; set; } = null; + + /// + /// Blend mode settings + /// + public BlendMode? BlendMode { get; set; } = null; + + /// + /// Channel control settings + /// + public ChanCtrl? ChanCtrl { get; set; } = null; + + /// + /// Material color (GX_COLOR0A0) + /// + public GXColor? MaterialColor { get; set; } = null; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Pane.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Pane.cs new file mode 100644 index 0000000..d99caa7 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Pane.cs @@ -0,0 +1,111 @@ +using LibWorkBench.Core; +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; +using LibWorkBench.Formats.NW4R.SystemLib.Types; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Simple UI element + /// + [JsonPolymorphic(TypeDiscriminatorPropertyName = "kind")] + [JsonDerivedType(typeof(Pane), typeDiscriminator: "pane")] + [JsonDerivedType(typeof(Bounding), typeDiscriminator: "bounding")] + [JsonDerivedType(typeof(Picture), typeDiscriminator: "picture")] + [JsonDerivedType(typeof(TextBox), typeDiscriminator: "textbox")] + [JsonDerivedType(typeof(Window), typeDiscriminator: "window")] + public class Pane : IUseName, IUseHierarchy + { + /// + /// Pane name (must be unique) + /// + public string Name { get; set; } = ""; + + /// + /// User-specific data + /// + public string UserData { get; set; } = ""; + + /// + /// Whether the pane will be rendered + /// + public bool Visible { get; set; } = true; + + /// + /// Whether the pane's alpha is influenced by its parent + /// + public bool InfluencedAlpha { get; set; } = false; + + /// + /// Whether the pane's scale should be influenced by location adjust + /// + public bool LocationAdjust { get; set; } = false; + + /// + /// Position origin settings + /// + public BasePosition BasePosition { get; set; } = new(); + + /// + /// Opaqueness + /// + public byte Alpha { get; set; } = 255; + + /// + /// Pane translation/position + /// + public VEC3 Translate { get; set; } = new(); + + /// + /// Pane rotation (in degrees) + /// + public VEC3 Rotate { get; set; } = new(); + + /// + /// Pane scale + /// + public VEC2 Scale { get; set; } = new(); + + /// + /// Pane size + /// + public Size Size { get; set; } = new(); + + /// + /// Parent pane + /// + [JsonIgnore] + public Pane? Parent { get; set; } = null; + + /// + /// Child panes + /// + [JsonPropertyOrder(int.MaxValue)] + public List Children { get; set; } = new(); + + /// + /// Appends a new child of this pane + /// + /// Child pane + public void AppendChild(Pane child) + { + Children.Add(child); + child.Parent = this; + } + + /// + /// Removes a child of this pane + /// + /// Child pane + public void RemoveChild(Pane child) + { + Children.Remove(child); + + // Avoid clobbering other hierarchy + if (child.Parent == this) + { + child.Parent = null; + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Picture.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Picture.cs new file mode 100644 index 0000000..a5f20c6 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Picture.cs @@ -0,0 +1,25 @@ +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Image pane + /// + public sealed class Picture : Pane + { + /// + /// Material name + /// + public string MaterialName { get; set; } = ""; + + /// + /// Vertex colors + /// + public VertexColorSet VertexColors { get; set; } = new(); + + /// + /// Texture coordinates + /// + public List TexCoords { get; set; } = new(); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/TexMap.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/TexMap.cs new file mode 100644 index 0000000..595bc50 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/TexMap.cs @@ -0,0 +1,25 @@ +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Material texture map (data-view) + /// + public sealed class TexMap + { + /// + /// Texture name + /// + public string TextureName { get; set; } = ""; + + /// + /// Texture wrap mode (S) + /// + public GXTexWrapMode WrapS { get; set; } = GXTexWrapMode.GX_CLAMP; + + /// + /// Texture wrap mode (T) + /// + public GXTexWrapMode WrapT { get; set; } = GXTexWrapMode.GX_CLAMP; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/TextBox.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/TextBox.cs new file mode 100644 index 0000000..dfeb1e4 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/TextBox.cs @@ -0,0 +1,61 @@ +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Text pane + /// + public sealed class TextBox : Pane + { + /// + /// Material name + /// + public string MaterialName { get; set; } = ""; + + /// + /// Font name + /// + public string FontName { get; set; } = ""; + + /// + /// Font size + /// + public Size FontSize { get; set; } = new(); + + /// + /// Spacing between characters + /// + public float CharSpace { get; set; } = 0.0f; + + /// + /// Spacing between lines + /// + public float LineSpace { get; set; } = 0.0f; + + /// + /// Text string contents + /// + public string TextContent { get; set; } = ""; + + /// + /// Text string maximum size. + /// If the text content overflows, the capacity is automatically updated. + /// + public ushort TextCapacity { get; set; } = 0; + + /// + /// Text position origin settings + /// + public BasePosition TextPosition { get; set; } = new(); + + /// + /// Text alignment type + /// + public TextAlignment TextAlignment { get; set; } = TextAlignment.Left; + + /// + /// Text vertex colors + /// + public TextColorSet TextColors { get; set; } = new(); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Window.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Window.cs new file mode 100644 index 0000000..6a7e1b6 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/Window.cs @@ -0,0 +1,25 @@ +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Window frame pane + /// + public sealed class Window : Pane + { + /// + /// Window content + /// + public WindowContent Content { get; set; } = new(); + + /// + /// Content inflation + /// + public WindowInflation Inflation { get; set; } = new(); + + /// + /// Window frames + /// + public List Frames { get; set; } = new(); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/WindowContent.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/WindowContent.cs new file mode 100644 index 0000000..032d8b9 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/WindowContent.cs @@ -0,0 +1,25 @@ +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Window content (data-view) + /// + public sealed class WindowContent + { + /// + /// Material name + /// + public string MaterialName { get; set; } = ""; + + /// + /// Vertex colors + /// + public VertexColorSet VertexColors { get; set; } = new(); + + /// + /// Texture coordinates + /// + public List TexCoords { get; set; } = new(); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/WindowFrame.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/WindowFrame.cs new file mode 100644 index 0000000..fc9eabb --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Data/WindowFrame.cs @@ -0,0 +1,20 @@ +using LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Data +{ + /// + /// Window frame (data-view) + /// + public sealed class WindowFrame + { + /// + /// Material name + /// + public string MaterialName { get; set; } = ""; + + /// + /// Texture flip type + /// + public TextureFlip TextureFlip { get; set; } = TextureFlip.None; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/LayoutDefine.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/LayoutDefine.cs new file mode 100644 index 0000000..8bbd64c --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/LayoutDefine.cs @@ -0,0 +1,37 @@ +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout +{ + /// + /// Shared layout constants + /// + public static class LayoutDefine + { + /// + /// Resource name string length + /// + public const int RES_NAME_LEN = 16; + + /// + /// Material name string length + /// + public const int MAT_NAME_LEN = 20; + + /// + /// Pane userdata string length + /// + public const int USERDATA_LEN = 8; + + /// + /// Maximum number of texture S/R/T transformations + /// + public const int MAX_TEX_SRT = + (GXTexMtx.GX_TEXMTX9 - GXTexMtx.GX_TEXMTX0) / 3 + 1; + + /// + /// Maximum number of indirect texture S/R/T transformations + /// + public const int MAX_IND_SRT = + GXIndTexMtxID.GX_ITM_2 - GXIndTexMtxID.GX_ITM_0 + 1; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/AlphaCompare.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/AlphaCompare.cs new file mode 100644 index 0000000..6c12119 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/AlphaCompare.cs @@ -0,0 +1,68 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Visibility test + /// + public sealed class AlphaCompare : IUseBinary + { + /// + /// Compare operation #0 + /// + public GXCompare Compare0 { get; set; } = GXCompare.GX_ALWAYS; + + /// + /// Compare operand #0 + /// + public byte Ref0 { get; set; } = 0; + + /// + /// Compare operation #1 + /// + public GXCompare Compare1 { get; set; } = GXCompare.GX_ALWAYS; + + /// + /// Compare operand #1 + /// + public byte Ref1 { get; set; } = 0; + + /// + /// Logic operation between comparisons + /// + public GXAlphaOp Op { get; set; } = GXAlphaOp.GX_AOP_AND; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + byte compare01 = reader.ReadU8(); + Compare0 = (GXCompare)(compare01 >> 0 & 0b1111); + Compare1 = (GXCompare)(compare01 >> 4 & 0b1111); + + Op = (GXAlphaOp)reader.ReadU8(); + Ref0 = reader.ReadU8(); + Ref1 = reader.ReadU8(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + byte compare01 = 0; + compare01 |= (byte)(((int)Compare0 & 0b1111) << 0); + compare01 |= (byte)(((int)Compare1 & 0b1111) << 4); + writer.WriteU8(compare01); + + writer.WriteU8((byte)Op); + writer.WriteU8(Ref0); + writer.WriteU8(Ref1); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/BasePosition.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/BasePosition.cs new file mode 100644 index 0000000..93df71a --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/BasePosition.cs @@ -0,0 +1,93 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Utility; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Horizontal position setting + /// + public enum HorizontalPosition + { + /// + /// Position is relative to the left edge + /// + Left, + + /// + /// Position is relative to the center + /// + Center, + + /// + /// Position is relative to the right edge + /// + Right + } + + /// + /// Vertical position setting + /// + public enum VerticalPosition + { + /// + /// Position is relative to the top edge + /// + Top, + + /// + /// Position is relative to the center + /// + Center, + + /// + /// Position is relative to the bottom edge + /// + Bottom + } + + /// + /// Layout base position configuration + /// + public sealed class BasePosition : IUseBinary + { + /// + /// Horizontal position origin + /// + public HorizontalPosition H { get; set; } = HorizontalPosition.Left; + + /// + /// Vertical position origin + /// + public VerticalPosition V { get; set; } = VerticalPosition.Top; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + byte packed = reader.ReadU8(); + + H = (HorizontalPosition) + (packed % Util.EnumCount()); + + V = (VerticalPosition) + (packed / Util.EnumCount()); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + byte packed = 0; + + packed += (byte)((int)V * Util.EnumCount()); + packed += (byte)H; + + writer.WriteU8(packed); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/BlendMode.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/BlendMode.cs new file mode 100644 index 0000000..e861d91 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/BlendMode.cs @@ -0,0 +1,58 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Blend mode configuration + /// + public sealed class BlendMode : IUseBinary + { + /// + /// Blend type + /// + public GXBlendMode Mode { get; set; } = GXBlendMode.GX_BM_BLEND; + + /// + /// Source blend factor + /// + public GXBlendFactor SrcFactor { get; set; } + = GXBlendFactor.GX_BL_SRCALPHA; + + /// + /// Destination blend factor + /// + public GXBlendFactor DstFactor { get; set; } + = GXBlendFactor.GX_BL_INVSRCALPHA; + + /// + /// Logic operation for blending + /// + public GXLogicOp Operation { get; set; } = GXLogicOp.GX_LO_SET; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Mode = (GXBlendMode)reader.ReadU8(); + SrcFactor = (GXBlendFactor)reader.ReadU8(); + DstFactor = (GXBlendFactor)reader.ReadU8(); + Operation = (GXLogicOp)reader.ReadU8(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU8((byte)Mode); + writer.WriteU8((byte)SrcFactor); + writer.WriteU8((byte)DstFactor); + writer.WriteU8((byte)Operation); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/ChanCtrl.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/ChanCtrl.cs new file mode 100644 index 0000000..da60f59 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/ChanCtrl.cs @@ -0,0 +1,44 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Channel control configuration + /// + public sealed class ChanCtrl : IUseBinary + { + /// + /// Channel color source + /// + public GXColorSrc ColorSrc { get; set; } = GXColorSrc.GX_SRC_VTX; + + /// + /// Channel alpha source + /// + public GXColorSrc AlphaSrc { get; set; } = GXColorSrc.GX_SRC_VTX; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + ColorSrc = (GXColorSrc)reader.ReadU8(); + AlphaSrc = (GXColorSrc)reader.ReadU8(); + reader.Align(4); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU8((byte)ColorSrc); + writer.WriteU8((byte)AlphaSrc); + writer.Align(4); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/IndirectStage.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/IndirectStage.cs new file mode 100644 index 0000000..f8be5ed --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/IndirectStage.cs @@ -0,0 +1,57 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Indirect texture stage + /// + public sealed class IndirectStage : IUseBinary + { + /// + /// Texture coordinate generator + /// + public GXTexCoordID TexCoordGen { get; set; } + = GXTexCoordID.GX_TEXCOORD0; + + /// + /// Texture map + /// + public GXTexMapID TexMap { get; set; } = GXTexMapID.GX_TEXMAP0; + + /// + /// Texture scale (S) + /// + public GXIndTexScale ScaleS { get; set; } = GXIndTexScale.GX_ITS_1; + + /// + /// Texture scale (T) + /// + public GXIndTexScale ScaleT { get; set; } = GXIndTexScale.GX_ITS_1; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + TexCoordGen = (GXTexCoordID)reader.ReadU8(); + TexMap = (GXTexMapID)reader.ReadU8(); + ScaleS = (GXIndTexScale)reader.ReadU8(); + ScaleT = (GXIndTexScale)reader.ReadU8(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU8((byte)TexCoordGen); + writer.WriteU8((byte)TexMap); + writer.WriteU8((byte)ScaleS); + writer.WriteU8((byte)ScaleT); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/OriginType.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/OriginType.cs new file mode 100644 index 0000000..bf05b77 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/OriginType.cs @@ -0,0 +1,18 @@ +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Layout position origin type + /// + public enum OriginType + { + /// + /// (0,0) represents the top-left corner of the layout + /// + TopLeft, + + /// + /// (0, 0) represents the center of the layout + /// + Center + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/Size.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/Size.cs new file mode 100644 index 0000000..4842e60 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/Size.cs @@ -0,0 +1,41 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Size with width/height components + /// + public sealed class Size : IUseBinary + { + /// + /// Size width (in pixels) + /// + public float Width { get; set; } = 0.0f; + + /// + /// Size height (in pixels) + /// + public float Height { get; set; } = 0.0f; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Width = reader.ReadF32(); + Height = reader.ReadF32(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteF32(Width); + writer.WriteF32(Height); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevAlphaInput.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevAlphaInput.cs new file mode 100644 index 0000000..5445183 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevAlphaInput.cs @@ -0,0 +1,117 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// TEV alpha combiner inputs + /// + public sealed class TevAlphaInput : IUseBinary + { + /// + /// Component A in the output equation + /// + public GXTevAlphaArg A { get; set; } = GXTevAlphaArg.GX_CA_ZERO; + + /// + /// Component B in the output equation + /// + public GXTevAlphaArg B { get; set; } = GXTevAlphaArg.GX_CA_ZERO; + + /// + /// Component C in the output equation + /// + public GXTevAlphaArg C { get; set; } = GXTevAlphaArg.GX_CA_ZERO; + + /// + /// Component D in the output equation + /// + public GXTevAlphaArg D { get; set; } = GXTevAlphaArg.GX_CA_ZERO; + + /// + /// Operation in the output equation + /// + public GXTevOp Operation { get; set; } = GXTevOp.GX_TEV_ADD; + + /// + /// Bias in the output equation + /// + public GXTevBias Bias { get; set; } = GXTevBias.GX_TB_ZERO; + + /// + /// Scale in the output equation + /// + public GXTevScale Scale { get; set; } = GXTevScale.GX_CS_SCALE_1; + + /// + /// Whether to clamp the output to the range [0, 1] + /// + public bool Clamp { get; set; } = true; + + /// + /// TEV register in which to store the result + /// + public GXTevRegID Output { get; set; } = GXTevRegID.GX_TEVPREV; + + /// + /// Constant alpha available to combiner arguments (GX_CA_KONST) + /// + public GXTevKAlphaSel Constant { get; set; } + = GXTevKAlphaSel.GX_TEV_KASEL_K0_R; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + byte ab = reader.ReadU8(); + byte cd = reader.ReadU8(); + byte op = reader.ReadU8(); + byte cl = reader.ReadU8(); + + A = (GXTevAlphaArg)(ab >> 0 & 0b1111); + B = (GXTevAlphaArg)(ab >> 4 & 0b1111); + C = (GXTevAlphaArg)(cd >> 0 & 0b1111); + D = (GXTevAlphaArg)(cd >> 4 & 0b1111); + + Operation = (GXTevOp)(op >> 0 & 0b1111); + Bias = (GXTevBias)(op >> 4 & 0b11); + Scale = (GXTevScale)(op >> 6 & 0b11); + + Clamp = (cl >> 0 & 0b1) != 0; + Output = (GXTevRegID)(cl >> 1 & 0b11); + Constant = (GXTevKAlphaSel)(cl >> 3 & 0b11111); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + byte ab = 0; + ab |= (byte)(((int)A & 0b1111) << 0); + ab |= (byte)(((int)B & 0b1111) << 4); + writer.WriteU8(ab); + + byte cd = 0; + cd |= (byte)(((int)C & 0b1111) << 0); + cd |= (byte)(((int)D & 0b1111) << 4); + writer.WriteU8(cd); + + byte op = 0; + op |= (byte)(((int)Operation & 0b1111) << 0); + op |= (byte)(((int)Bias & 0b11) << 4); + op |= (byte)(((int)Scale & 0b11) << 6); + writer.WriteU8(op); + + byte cl = 0; + cl |= (byte)((Clamp ? 1 : 0) << 0); + cl |= (byte)(((int)Output & 0b11) << 1); + cl |= (byte)(((int)Constant & 0b11111) << 3); + writer.WriteU8(cl); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevColorInput.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevColorInput.cs new file mode 100644 index 0000000..4f5c72e --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevColorInput.cs @@ -0,0 +1,117 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// TEV color combiner inputs + /// + public sealed class TevColorInput : IUseBinary + { + /// + /// Component A in the output equation + /// + public GXTevColorArg A { get; set; } = GXTevColorArg.GX_CC_ZERO; + + /// + /// Component B in the output equation + /// + public GXTevColorArg B { get; set; } = GXTevColorArg.GX_CC_ZERO; + + /// + /// Component C in the output equation + /// + public GXTevColorArg C { get; set; } = GXTevColorArg.GX_CC_ZERO; + + /// + /// Component D in the output equation + /// + public GXTevColorArg D { get; set; } = GXTevColorArg.GX_CC_ZERO; + + /// + /// Operation in the output equation + /// + public GXTevOp Operation { get; set; } = GXTevOp.GX_TEV_ADD; + + /// + /// Bias in the output equation + /// + public GXTevBias Bias { get; set; } = GXTevBias.GX_TB_ZERO; + + /// + /// Scale in the output equation + /// + public GXTevScale Scale { get; set; } = GXTevScale.GX_CS_SCALE_1; + + /// + /// Whether to clamp the output to the range [0, 1] + /// + public bool Clamp { get; set; } = true; + + /// + /// TEV register in which to store the result + /// + public GXTevRegID Output { get; set; } = GXTevRegID.GX_TEVPREV; + + /// + /// Constant color available to combiner arguments (GX_CC_KONST) + /// + public GXTevKColorSel Constant { get; set; } + = GXTevKColorSel.GX_TEV_KCSEL_K0; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + byte ab = reader.ReadU8(); + byte cd = reader.ReadU8(); + byte op = reader.ReadU8(); + byte cl = reader.ReadU8(); + + A = (GXTevColorArg)(ab >> 0 & 0b1111); + B = (GXTevColorArg)(ab >> 4 & 0b1111); + C = (GXTevColorArg)(cd >> 0 & 0b1111); + D = (GXTevColorArg)(cd >> 4 & 0b1111); + + Operation = (GXTevOp)(op >> 0 & 0b1111); + Bias = (GXTevBias)(op >> 4 & 0b11); + Scale = (GXTevScale)(op >> 6 & 0b11); + + Clamp = (cl >> 0 & 0b1) != 0; + Output = (GXTevRegID)(cl >> 1 & 0b11); + Constant = (GXTevKColorSel)(cl >> 3 & 0b11111); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + byte ab = 0; + ab |= (byte)(((int)A & 0b1111) << 0); + ab |= (byte)(((int)B & 0b1111) << 4); + writer.WriteU8(ab); + + byte cd = 0; + cd |= (byte)(((int)C & 0b1111) << 0); + cd |= (byte)(((int)D & 0b1111) << 4); + writer.WriteU8(cd); + + byte op = 0; + op |= (byte)(((int)Operation & 0b1111) << 0); + op |= (byte)(((int)Bias & 0b11) << 4); + op |= (byte)(((int)Scale & 0b11) << 6); + writer.WriteU8(op); + + byte cl = 0; + cl |= (byte)((Clamp ? 1 : 0) << 0); + cl |= (byte)(((int)Output & 0b11) << 1); + cl |= (byte)(((int)Constant & 0b11111) << 3); + writer.WriteU8(cl); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevColorSet.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevColorSet.cs new file mode 100644 index 0000000..129b263 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevColorSet.cs @@ -0,0 +1,49 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// TEV color set + /// + public sealed class TevColorSet : IUseBinary + { + /// + /// TEV color register 0 (GX_TEVREG0) + /// + public GXColorS10 Reg0 { get; set; } = new(); + + /// + /// TEV color register 1 (GX_TEVREG1) + /// + public GXColorS10 Reg1 { get; set; } = new(); + + /// + /// TEV color register 2 (GX_TEVREG2) + /// + public GXColorS10 Reg2 { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Reg0.Read(reader); + Reg1.Read(reader); + Reg2.Read(reader); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + Reg0.Write(writer); + Reg1.Write(writer); + Reg2.Write(writer); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevKonstColorSet.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevKonstColorSet.cs new file mode 100644 index 0000000..517c22a --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevKonstColorSet.cs @@ -0,0 +1,56 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// TEV constant color (KCOLOR) set + /// + public sealed class TevKonstColorSet : IUseBinary + { + /// + /// TEV constant color register 0 (GX_KCOLOR0) + /// + public GXColor Color0 { get; set; } = new(); + + /// + /// TEV constant color register 1 (GX_KCOLOR1) + /// + public GXColor Color1 { get; set; } = new(); + + /// + /// TEV constant color register 2 (GX_KCOLOR2) + /// + public GXColor Color2 { get; set; } = new(); + + /// + /// TEV constant color register 3 (GX_KCOLOR3) + /// + public GXColor Color3 { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Color0.Read(reader); + Color1.Read(reader); + Color2.Read(reader); + Color3.Read(reader); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + Color0.Write(writer); + Color1.Write(writer); + Color2.Write(writer); + Color3.Write(writer); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevStage.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevStage.cs new file mode 100644 index 0000000..c986931 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevStage.cs @@ -0,0 +1,158 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// TEV stage + /// + public sealed class TevStage : IUseBinary + { + /// + /// Texture coordinate generator + /// + public GXTexCoordID TexCoordGen { get; set; } + = GXTexCoordID.GX_TEXCOORD_NULL; + + /// + /// Color channel ID + /// + public GXChannelID ColorChannel { get; set; } + = GXChannelID.GX_COLOR0A0; + + /// + /// Texture map + /// + public GXTexMapID TexMap { get; set; } = GXTexMapID.GX_TEXMAP_NULL; + + /// + /// TEV swap table slot + /// + public GXTevSwapSel SwapSelect { get; set; } + = GXTevSwapSel.GX_TEV_SWAP0; + + /// + /// TEV color combiner inputs + /// + public TevColorInput ColorInput { get; set; } = new(); + + /// + /// TEV alpha combiner inputs + /// + public TevAlphaInput AlphaInput { get; set; } = new(); + + /// + /// Indirect texture stage + /// + public GXIndTexStageID IndirectStage { get; set; } + = GXIndTexStageID.GX_INDTEXSTAGE0; + + /// + /// Indirect texture bias + /// + public GXIndTexBiasSel IndirectBias { get; set; } + = GXIndTexBiasSel.GX_ITB_NONE; + + /// + /// Indirect texture matrix + /// + public GXIndTexMtxID IndirectMtx { get; set; } + = GXIndTexMtxID.GX_ITM_OFF; + + /// + /// Indirect texture wrap mode (S) + /// + public GXIndTexWrap IndirectWrapS { get; set; } + = GXIndTexWrap.GX_ITW_OFF; + + /// + /// Indirect texture wrap mode (T) + /// + public GXIndTexWrap IndirectWrapT { get; set; } + = GXIndTexWrap.GX_ITW_OFF; + + /// + /// Indirect texture format + /// + public GXIndTexFormat IndirectFormat { get; set; } + = GXIndTexFormat.GX_ITF_8; + + /// + /// Whether to add texture coordinate results from the previous TEV stage + /// + public bool IndirectAddPrev { get; set; } = false; + + /// + /// Whether to use unmodified texture coordinates + /// + public bool IndirectUtcLod { get; set; } = false; + + /// + /// Indirect texture alpha selection + /// + public GXIndTexAlphaSel IndirectAlpha { get; set; } + = GXIndTexAlphaSel.GX_ITBA_OFF; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + TexCoordGen = (GXTexCoordID)reader.ReadU8(); + ColorChannel = (GXChannelID)reader.ReadU8(); + TexMap = (GXTexMapID)reader.ReadU8(); + SwapSelect = (GXTevSwapSel)reader.ReadU8(); + ColorInput.Read(reader); + AlphaInput.Read(reader); + IndirectStage = (GXIndTexStageID)reader.ReadU8(); + + byte indBiMt = reader.ReadU8(); + IndirectBias = (GXIndTexBiasSel)(indBiMt >> 0 & 0b111); + IndirectMtx = (GXIndTexMtxID)(indBiMt >> 3 & 0b1111); + + byte indWrap = reader.ReadU8(); + IndirectWrapS = (GXIndTexWrap)(indWrap >> 0 & 0b111); + IndirectWrapT = (GXIndTexWrap)(indWrap >> 3 & 0b111); + + byte indFoAdUtAl = reader.ReadU8(); + IndirectFormat = (GXIndTexFormat)(indFoAdUtAl >> 0 & 0b11); + IndirectAddPrev = (indFoAdUtAl >> 2 & 0b1) != 0; + IndirectUtcLod = (indFoAdUtAl >> 3 & 0b1) != 0; + IndirectAlpha = (GXIndTexAlphaSel)(indFoAdUtAl >> 4 & 0b11); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU8((byte)TexCoordGen); + writer.WriteU8((byte)ColorChannel); + writer.WriteU8((byte)TexMap); + writer.WriteU8((byte)SwapSelect); + ColorInput.Write(writer); + AlphaInput.Write(writer); + writer.WriteU8((byte)IndirectStage); + + byte indBiMt = 0; + indBiMt |= (byte)(((int)IndirectBias & 0b111) << 0); + indBiMt |= (byte)(((int)IndirectMtx & 0b1111) << 3); + writer.WriteU8(indBiMt); + + byte indWrap = 0; + indWrap |= (byte)(((int)IndirectWrapS & 0b111) << 0); + indWrap |= (byte)(((int)IndirectWrapT & 0b111) << 3); + writer.WriteU8(indWrap); + + byte indFoAdUtAl = 0; + indFoAdUtAl |= (byte)(((int)IndirectFormat & 0b11) << 0); + indFoAdUtAl |= (byte)((IndirectAddPrev ? 1 : 0) << 2); + indFoAdUtAl |= (byte)((IndirectUtcLod ? 1 : 0) << 3); + indFoAdUtAl |= (byte)(((int)IndirectAlpha & 0b11) << 4); + writer.WriteU8(indFoAdUtAl); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevSwapMode.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevSwapMode.cs new file mode 100644 index 0000000..f8dfca3 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevSwapMode.cs @@ -0,0 +1,62 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// TEV color channel swap configuration + /// + public sealed class TevSwapMode : IUseBinary + { + /// + /// Color component to use instead of the red component + /// + public GXTevColorChan R { get; set; } = GXTevColorChan.GX_CH_RED; + + /// + /// Color component to use instead of the green component + /// + public GXTevColorChan G { get; set; } = GXTevColorChan.GX_CH_GREEN; + + /// + /// Color component to use instead of the blue component + /// + public GXTevColorChan B { get; set; } = GXTevColorChan.GX_CH_BLUE; + + /// + /// Color component to use instead of the alpha component + /// + public GXTevColorChan A { get; set; } = GXTevColorChan.GX_CH_ALPHA; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + byte packed = reader.ReadU8(); + + R = (GXTevColorChan)(packed >> 0 & 0b11); + G = (GXTevColorChan)(packed >> 2 & 0b11); + B = (GXTevColorChan)(packed >> 4 & 0b11); + A = (GXTevColorChan)(packed >> 6 & 0b11); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + byte packed = 0; + + packed |= (byte)(((int)R & 0b11) << 0); + packed |= (byte)(((int)G & 0b11) << 2); + packed |= (byte)(((int)B & 0b11) << 4); + packed |= (byte)(((int)A & 0b11) << 6); + + writer.WriteU8(packed); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevSwapTable.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevSwapTable.cs new file mode 100644 index 0000000..b8ce910 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TevSwapTable.cs @@ -0,0 +1,55 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// TEV color channel swap table + /// + public sealed class TevSwapTable : IUseBinary + { + /// + /// Swap select #0 + /// + public TevSwapMode Swap0 { get; set; } = new(); + + /// + /// Swap select #1 + /// + public TevSwapMode Swap1 { get; set; } = new(); + + /// + /// Swap select #2 + /// + public TevSwapMode Swap2 { get; set; } = new(); + + /// + /// Swap select #3 + /// + public TevSwapMode Swap3 { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Swap0.Read(reader); + Swap1.Read(reader); + Swap2.Read(reader); + Swap3.Read(reader); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + Swap0.Write(writer); + Swap1.Write(writer); + Swap2.Write(writer); + Swap3.Write(writer); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TexCoord.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TexCoord.cs new file mode 100644 index 0000000..dc9ae36 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TexCoord.cs @@ -0,0 +1,56 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.SystemLib.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Texture coordinates + /// + public sealed class TexCoord : IUseBinary + { + /// + /// Top-left coordinate + /// + public VEC2 LeftTop { get; set; } = new(); + + /// + /// Top-right coordinate + /// + public VEC2 RightTop { get; set; } = new(); + + /// + /// Bottom-left coordinate + /// + public VEC2 LeftBottom { get; set; } = new(); + + /// + /// Bottom-right coordinate + /// + public VEC2 RightBottom { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + LeftTop.Read(reader); + RightTop.Read(reader); + LeftBottom.Read(reader); + RightBottom.Read(reader); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + LeftTop.Write(writer); + RightTop.Write(writer); + LeftBottom.Write(writer); + RightBottom.Write(writer); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TexCoordGen.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TexCoordGen.cs new file mode 100644 index 0000000..6fabe54 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TexCoordGen.cs @@ -0,0 +1,51 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Texture coordinate generator configuration + /// + public sealed class TexCoordGen : IUseBinary + { + /// + /// Generator type + /// + public GXTexGenType Type { get; set; } = GXTexGenType.GX_TG_MTX2x4; + + /// + /// Generator source + /// + public GXTexGenSrc Src { get; set; } = GXTexGenSrc.GX_TG_TEX0; + + /// + /// Texture matrix + /// + public GXTexMtx Mtx { get; set; } = GXTexMtx.GX_IDENTITY; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Type = (GXTexGenType)reader.ReadU8(); + Src = (GXTexGenSrc)reader.ReadU8(); + Mtx = (GXTexMtx)reader.ReadU8(); + reader.Align(4); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU8((byte)Type); + writer.WriteU8((byte)Src); + writer.WriteU8((byte)Mtx); + writer.Align(4); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TexSrt.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TexSrt.cs new file mode 100644 index 0000000..38149e4 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TexSrt.cs @@ -0,0 +1,49 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.NW4R.SystemLib.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Texture S/R/T transformation + /// + public sealed class TexSrt : IUseBinary + { + /// + /// Texture translation + /// + public VEC2 Translate { get; set; } = new(); + + /// + /// Texture rotation + /// + public float Rotate { get; set; } = 0.0f; + + /// + /// Texture scale + /// + public VEC2 Scale { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Translate.Read(reader); + Rotate = reader.ReadF32(); + Scale.Read(reader); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + Translate.Write(writer); + writer.WriteF32(Rotate); + Scale.Write(writer); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TextAlignment.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TextAlignment.cs new file mode 100644 index 0000000..f56f222 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TextAlignment.cs @@ -0,0 +1,23 @@ +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Text alignment type + /// + public enum TextAlignment + { + /// + /// Text is aligned with the left edge + /// + Left, + + /// + /// Text is aligned with the center + /// + Center, + + /// + /// Text is aligned with the right edge + /// + Right + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TextColorSet.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TextColorSet.cs new file mode 100644 index 0000000..de4db3f --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TextColorSet.cs @@ -0,0 +1,42 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Textbox vertex color set + /// + public sealed class TextColorSet : IUseBinary + { + /// + /// Top-left/top-right vertex color + /// + public GXColor Top { get; set; } = new(); + + /// + /// Bottom-left/bottom-right vertex color + /// + public GXColor Bottom { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Top.Read(reader); + Bottom.Read(reader); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + Top.Write(writer); + Bottom.Write(writer); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TextureFlip.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TextureFlip.cs new file mode 100644 index 0000000..f3d6cd5 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/TextureFlip.cs @@ -0,0 +1,38 @@ +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Window texture flip configuration + /// + public enum TextureFlip + { + /// + /// Frame is not flipped + /// + None, + + /// + /// Frame is mirrored horizontally + /// + FlipH, + + /// + /// Frame is mirrored vertically + /// + FlipV, + + /// + /// Frame is rotated 90 degrees + /// + Flip90, + + /// + /// Frame is rotated 180 degrees + /// + Flip180, + + /// + /// Frame is rotated 270 degrees + /// + Flip270 + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/VertexColorSet.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/VertexColorSet.cs new file mode 100644 index 0000000..0793fa6 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/VertexColorSet.cs @@ -0,0 +1,56 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; +using LibWorkBench.Formats.Revolution.GX.Types; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Vertex color set + /// + public sealed class VertexColorSet : IUseBinary + { + /// + /// Top-left corner vertex + /// + public GXColor LeftTop { get; set; } = new(); + + /// + /// Top-right corner vertex + /// + public GXColor RightTop { get; set; } = new(); + + /// + /// Bottom-left corner vertex + /// + public GXColor LeftBottom { get; set; } = new(); + + /// + /// Bottom-right corner vertex + /// + public GXColor RightBottom { get; set; } = new(); + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + LeftTop.Read(reader); + RightTop.Read(reader); + LeftBottom.Read(reader); + RightBottom.Read(reader); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + LeftTop.Write(writer); + RightTop.Write(writer); + LeftBottom.Write(writer); + RightBottom.Write(writer); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/WindowInflation.cs b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/WindowInflation.cs new file mode 100644 index 0000000..c64d968 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/LayoutLib/Layout/Types/WindowInflation.cs @@ -0,0 +1,55 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.LayoutLib.Layout.Types +{ + /// + /// Window content inflation + /// + public sealed class WindowInflation : IUseBinary + { + /// + /// Inflation from the left edge + /// + public float Left { get; set; } = 0.0f; + + /// + /// Inflation from the right edge + /// + public float Right { get; set; } = 0.0f; + + /// + /// Inflation from the top edge + /// + public float Top { get; set; } = 0.0f; + + /// + /// Inflation from the bottom edge + /// + public float Bottom { get; set; } = 0.0f; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Left = reader.ReadF32(); + Right = reader.ReadF32(); + Top = reader.ReadF32(); + Bottom = reader.ReadF32(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteF32(Left); + writer.WriteF32(Right); + writer.WriteF32(Top); + writer.WriteF32(Bottom); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/NW4RDefine.cs b/tools/workbench/LibWorkBench/Formats/NW4R/NW4RDefine.cs new file mode 100644 index 0000000..d76a3a7 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/NW4RDefine.cs @@ -0,0 +1,23 @@ +namespace LibWorkBench.Formats.NW4R +{ + /// + /// Shared NW4R constants + /// + public static class NW4RDefine + { + /// + /// Maximum length for the Signature field of binary headers + /// + public const int HEADER_SIGNATURE_LENGTH = 4; + + /// + /// Maximum length for the Signature field of binary blocks + /// + public const int BLOCK_SIGNATURE_LENGTH = 4; + + /// + /// Byte alignment for all binary blocks + /// + public const ulong BLOCK_ALIGNMENT = 4; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/SystemLib/Types/MTX33.cs b/tools/workbench/LibWorkBench/Formats/NW4R/SystemLib/Types/MTX33.cs new file mode 100644 index 0000000..95711cd --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/SystemLib/Types/MTX33.cs @@ -0,0 +1,94 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.SystemLib.Types +{ + /// + /// 3x3 matrix + /// + public sealed class MTX33 : IUseBinary + { + /// + /// Underlying matrix data + /// + public float[,] M = new float[3, 3]; + + /// + /// Accesses the specified matrix element + /// + /// Element row index + /// Element column index + /// Matrix element + public float this[int row, int col] + { get => M[row, col]; set => M[row, col] = value; } + + /// + /// Accesses the element at row 0, column 0 + /// + public float M00 { get => M[0, 0]; set => M[0, 0] = value; } + /// + /// Accesses the element at row 0, column 1 + /// + public float M01 { get => M[0, 1]; set => M[0, 1] = value; } + /// + /// Accesses the element at row 0, column 2 + /// + public float M02 { get => M[0, 2]; set => M[0, 2] = value; } + + /// + /// Accesses the element at row 1, column 0 + /// + public float M10 { get => M[1, 0]; set => M[1, 0] = value; } + /// + /// Accesses the element at row 1, column 1 + /// + public float M11 { get => M[1, 1]; set => M[1, 1] = value; } + /// + /// Accesses the element at row 1, column 2 + /// + public float M12 { get => M[1, 2]; set => M[1, 2] = value; } + + /// + /// Accesses the element at row 2, column 0 + /// + public float M20 { get => M[2, 0]; set => M[2, 0] = value; } + /// + /// Accesses the element at row 2, column 1 + /// + public float M21 { get => M[2, 1]; set => M[2, 1] = value; } + /// + /// Accesses the element at row 2, column 2 + /// + public float M22 { get => M[2, 2]; set => M[2, 2] = value; } + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + for (int row = 0; row < M.GetLength(0); row++) + { + for (int col = 0; col < M.GetLength(1); col++) + { + M[row, col] = reader.ReadF32(); + } + } + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + for (int row = 0; row < M.GetLength(0); row++) + { + for (int col = 0; col < M.GetLength(1); col++) + { + writer.WriteF32(M[row, col]); + } + } + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/SystemLib/Types/VEC2.cs b/tools/workbench/LibWorkBench/Formats/NW4R/SystemLib/Types/VEC2.cs new file mode 100644 index 0000000..63f5536 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/SystemLib/Types/VEC2.cs @@ -0,0 +1,41 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.SystemLib.Types +{ + /// + /// 2D vector + /// + public sealed class VEC2 : IUseBinary + { + /// + /// X-axis component + /// + public float X { get; set; } = 0.0f; + + /// + /// Y-axis component + /// + public float Y { get; set; } = 0.0f; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + X = reader.ReadF32(); + Y = reader.ReadF32(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteF32(X); + writer.WriteF32(Y); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/SystemLib/Types/VEC3.cs b/tools/workbench/LibWorkBench/Formats/NW4R/SystemLib/Types/VEC3.cs new file mode 100644 index 0000000..1ea98a3 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/SystemLib/Types/VEC3.cs @@ -0,0 +1,48 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.NW4R.SystemLib.Types +{ + /// + /// 3D vector + /// + public sealed class VEC3 : IUseBinary + { + /// + /// X-axis component + /// + public float X { get; set; } = 0.0f; + + /// + /// Y-axis component + /// + public float Y { get; set; } = 0.0f; + + /// + /// Z-axis component + /// + public float Z { get; set; } = 0.0f; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + X = reader.ReadF32(); + Y = reader.ReadF32(); + Z = reader.ReadF32(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteF32(X); + writer.WriteF32(Y); + writer.WriteF32(Z); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RBinaryBlock.cs b/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RBinaryBlock.cs new file mode 100644 index 0000000..bd3ee0e --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RBinaryBlock.cs @@ -0,0 +1,85 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.Formats.NW4R.Details; +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Streams; +using LibWorkBench.Utility; + +namespace LibWorkBench.Formats.NW4R +{ + /// + /// Base class for NW4R binary-view blocks + /// + /// Parent model class + public abstract class TNW4RBinaryBlock : TBinaryBlock + where TParentModel : NW4RBinaryModel, new() + { + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public override void OnRead(ReadStream reader) + { + DoRead(reader); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public override void OnWrite(WriteStream writer) + { + NW4RBinaryBlockHeader blockHeader = new(); + blockHeader.Signature = Profile.Signature; + + // Work buffer for tracking filesize + WorkMemWriter content = new(new BinaryCharEncoding(), + writer.Endian); + + // Write header to make room, will need to correct it later + blockHeader.Write(content); + + // Derived block contents + DoWrite(content); + + // Reflect accurate block size in the header + blockHeader.Size = Util.RoundUp((uint)content.Length, + Model!.Profile.Alignment); + + // Go back and fix the header + content.Seek(0, SeekOrigin.Begin); + blockHeader.Write(content); + + // Flush data to the real stream + writer.Write(content.Buffer, content.Length); + } + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void OnSync(DataModel dataModel) + { + NW4RDataModel src = (NW4RDataModel)dataModel; + DoSync(src); + } + + /// + /// Deserializes the contents of this object from a file (derived implementation) + /// + /// Binary stream to the file + public abstract void DoRead(ReadStream reader); + + /// + /// Serializes the contents of this object to a file (derived implementation) + /// + /// Binary stream to the file + public abstract void DoWrite(WriteStream writer); + + /// + /// Updates this block to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public abstract void DoSync(NW4RDataModel dataModel); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RBinaryModel.cs new file mode 100644 index 0000000..bc3f758 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RBinaryModel.cs @@ -0,0 +1,30 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Details; +using LibWorkBench.Formats.NW4R.Details; + +namespace LibWorkBench.Formats.NW4R +{ + /// + /// Base class for NW4R binary-view models + /// + /// Parent resource class + /// Block factory class + public abstract class TNW4RBinaryModel : NW4RBinaryModel + where TParentResource : ResourceImpl + where TBlockFactory : BinaryBlockFactory, new() + { + /// + /// Resource that owns this model + /// + public new TParentResource? Resource + => (TParentResource?)base.Resource; + + /// + /// Constructor + /// + public TNW4RBinaryModel() + : base(new TBlockFactory()) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RDataModel.cs b/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RDataModel.cs new file mode 100644 index 0000000..d512fe9 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RDataModel.cs @@ -0,0 +1,20 @@ +using LibWorkBench.Core.Models.Details; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Formats.NW4R +{ + /// + /// Base class for NW4R data-view models + /// + /// Parent resource class + public abstract class TNW4RDataModel : NW4RDataModel + where TParentResource : ResourceImpl + { + /// + /// Resource that owns this model + /// + [JsonIgnore] + public new TParentResource? Resource + => (TParentResource?)base.Resource; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RResource.cs b/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RResource.cs new file mode 100644 index 0000000..a9421b4 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/NW4R/TNW4RResource.cs @@ -0,0 +1,16 @@ +using LibWorkBench.Core.Models; +using LibWorkBench.Formats.NW4R.Details; + +namespace LibWorkBench.Formats.NW4R +{ + /// + /// Base class for NW4R resources + /// + /// Binary-view model class + /// Data-view model class + public abstract class TNW4RResource : TResource + where TBinaryModel : NW4RBinaryModel, new() + where TDataModel : NW4RDataModel, new() + { + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/MapDataBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/MapDataBinaryModel.cs new file mode 100644 index 0000000..64bf4d8 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/MapDataBinaryModel.cs @@ -0,0 +1,121 @@ +using LibWorkBench.API.Pack.Common; +using LibWorkBench.Attributes; +using LibWorkBench.Core.Models.Data; +using LibWorkBench.IO.Streams; +using LibWorkBench.Utility; + +namespace LibWorkBench.Formats.Pack.Common.MapData.Binary +{ + /// + /// Pack map data binary-view model + /// + [BinaryModelProfile(signature: "PMPF")] + public sealed class MapDataBinaryModel : TRawBinaryModel + { + /// + /// Bit flag indices + /// + public enum Flag + { + /// + /// Whether this file has been unpacked at runtime + /// + Unpacked, + } + + /// + /// Bitflags + /// + public BitFlag Flags { get; set; } = new(); + + /// + /// Map objects + /// + public List Objects { get; set; } = new(); + + /// + /// Map paths + /// + public List Paths { get; set; } = new(); + + /// + /// Map path points + /// + public List Points { get; set; } = new(); + + /// + /// Deserializes the contents of this model from a file + /// + /// Binary stream to the file + public override void OnRead(ReadStream reader) + { + // Unknown data + reader.Skip(4); + + Flags.SetDirect(reader.ReadU16()); + reader.Align(4); + + // Header is 16-byte aligned + reader.Align(16); + + ushort objectNum = reader.ReadU16(); + ushort pathNum = reader.ReadU16(); + ushort pointNum = reader.ReadU16(); + + // Why is the section 64-byte aligned? + reader.Align(64); + + uint objectOffset = reader.ReadU32(); + uint pathOffset = reader.ReadU32(); + uint pointOffset = reader.ReadU32(); + + // Why is the section 64-byte aligned? + reader.Align(64); + + // Read object data + reader.Seek(objectOffset, SeekOrigin.Begin); + for (uint i = 0; i < objectNum; i++) + { + ResMapDataObject obj = new(); + obj.Read(reader); + Objects.Add(obj); + } + + // Read path data + reader.Seek(pathOffset, SeekOrigin.Begin); + for (uint i = 0; i < pathNum; i++) + { + ResMapDataPath path = new(); + path.Read(reader); + Paths.Add(path); + } + + // Read point data + reader.Seek(pointOffset, SeekOrigin.Begin); + for (uint i = 0; i < pointNum; i++) + { + ResMapDataPoint point = new(); + point.Read(reader); + Points.Add(point); + } + } + + /// + /// Serializes the contents of this model to a file + /// + /// Binary stream to the file + public override void OnWrite(WriteStream writer) + { + // Unknown data + writer.Skip(4); + } + + /// + /// Updates this model to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void Sync(DataModel dataModel) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/ResMapDataObject.cs b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/ResMapDataObject.cs new file mode 100644 index 0000000..1cb42ca --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/ResMapDataObject.cs @@ -0,0 +1,90 @@ +using LibWorkBench.Core; +using LibWorkBench.Formats.NW4R.SystemLib.Types; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Pack.Common.MapData.Binary +{ + /// + /// Map data object (binary-view) + /// + public sealed class ResMapDataObject : IUseBinary + { + /// + /// Object group ID + /// + public ushort Group { get; set; } = 0; + + /// + /// Object ID + /// + public ushort ID { get; set; } = 0; + + /// + /// Object layer ID + /// + public byte Layer { get; set; } = 0; + + /// + /// Object position + /// + public VEC3 Position { get; set; } = new(); + + /// + /// Object scale + /// + public VEC3 Scale { get; set; } = new(); + + /// + /// Object transformation matrix + /// + public MTX33 Transform { get; set; } = new(); + + /// + /// Index of the path associated with this object + /// + public int PathIndex { get; set; } = -1; + + /// + /// User-specific data + /// + public byte[] UserData { get; set; } = []; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Group = reader.ReadU16(); + ID = reader.ReadU16(); + Layer = reader.ReadU8(); + reader.Align(4); + + Position.Read(reader); + Scale.Read(reader); + Transform.Read(reader); + + PathIndex = reader.ReadS32(); + UserData = reader.Read(MapDataDefine.OBJECT_USERDATA_LEN); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU16(Group); + writer.WriteU16(ID); + writer.WriteU8(Layer); + writer.Align(4); + + Position.Write(writer); + Scale.Write(writer); + Transform.Write(writer); + + writer.WriteS32(PathIndex); + writer.Write(UserData); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/ResMapDataPath.cs b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/ResMapDataPath.cs new file mode 100644 index 0000000..f40315c --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/ResMapDataPath.cs @@ -0,0 +1,27 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Pack.Common.MapData.Binary +{ + /// + /// Map data path (binary-view) + /// + public sealed class ResMapDataPath : IUseBinary + { + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/ResMapDataPoint.cs b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/ResMapDataPoint.cs new file mode 100644 index 0000000..0f8aaf0 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Binary/ResMapDataPoint.cs @@ -0,0 +1,42 @@ +using LibWorkBench.Core; +using LibWorkBench.Formats.NW4R.SystemLib.Types; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Pack.Common.MapData.Binary +{ + /// + /// Map data path point (binary-view) + /// + public sealed class ResMapDataPoint : IUseBinary + { + /// + /// Point position + /// + public VEC3 Position { get; set; } = new(); + + /// + /// User-specific data + /// + public byte[] UserData { get; set; } = []; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Position.Read(reader); + UserData = reader.Read(MapDataDefine.POINT_USERDATA_LEN); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + Position.Write(writer); + writer.Write(UserData); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Data/MapDataDataModel.cs b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Data/MapDataDataModel.cs new file mode 100644 index 0000000..879801a --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/Data/MapDataDataModel.cs @@ -0,0 +1,42 @@ +using LibWorkBench.API.Pack.Common; +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Formats.Pack.Common.MapData.Binary; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Pack.Common.MapData.Data +{ + /// + /// Pack map data data-view model + /// + public sealed class MapDataDataModel : TRawDataModel + { + /// + /// Deserializes the contents of this model from a file + /// + /// Stream to the JSON file + public override void Load(JsonFileReader reader) + { + reader.Deserialize(this); + } + + /// + /// Serializes the contents of this model to a file + /// + /// Stream to the JSON file + public override void Dump(JsonFileWriter writer) + { + writer.Serialize(this); + } + + /// + /// Updates this model to match the contents of the binary-view model (derived implementation) + /// + /// Binary-view model + public override void Sync(BinaryModel binaryModel) + { + MapDataBinaryModel src = (MapDataBinaryModel)binaryModel; + + // . . . + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/MapDataDefine.cs b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/MapDataDefine.cs new file mode 100644 index 0000000..d5d642f --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Common/MapData/MapDataDefine.cs @@ -0,0 +1,18 @@ +namespace LibWorkBench.Formats.Pack.Common.MapData +{ + /// + /// Shared map data constants + /// + public static class MapDataDefine + { + /// + /// Length of the map object userdata field + /// + public const int OBJECT_USERDATA_LEN = 16; + + /// + /// Length of the map point userdata field + /// + public const int POINT_USERDATA_LEN = 8; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Details/ExcelBinBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/Pack/Details/ExcelBinBinaryModel.cs new file mode 100644 index 0000000..3859952 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Details/ExcelBinBinaryModel.cs @@ -0,0 +1,28 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.Pack.Details +{ + /// + /// Base class for ExcelBin binary-view models (implementation details) + /// + public abstract class ExcelBinBinaryModel : BinaryModel + { + /// + /// Updates this model to match the contents of the data-view model + /// + /// Data-view model + public override void Sync(DataModel dataModel) + { + ExcelBinDataModel src = (ExcelBinDataModel)dataModel; + + OnSync(src); + } + + /// + /// Updates this model to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public abstract void OnSync(ExcelBinDataModel dataModel); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Details/ExcelBinDataModel.cs b/tools/workbench/LibWorkBench/Formats/Pack/Details/ExcelBinDataModel.cs new file mode 100644 index 0000000..1fef5bc --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Details/ExcelBinDataModel.cs @@ -0,0 +1,28 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Data; + +namespace LibWorkBench.Formats.Pack.Details +{ + /// + /// Base class for ExcelBin data-view models (implementation details) + /// + public abstract class ExcelBinDataModel : DataModel + { + /// + /// Updates this model to match the contents of the binary-view model + /// + /// Binary-view model + public override void Sync(BinaryModel binaryModel) + { + ExcelBinBinaryModel src = (ExcelBinBinaryModel)binaryModel; + + OnSync(src); + } + + /// + /// Updates this model to match the contents of the binary-view model (derived implementation) + /// + /// Binary-view model + public abstract void OnSync(ExcelBinBinaryModel binaryModel); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/LevelTable/LevelTableBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/LevelTable/LevelTableBinaryModel.cs new file mode 100644 index 0000000..baf388e --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/LevelTable/LevelTableBinaryModel.cs @@ -0,0 +1,55 @@ +using LibWorkBench.API.Pack.Party.Pnp; +using LibWorkBench.Formats.Pack.Details; +using LibWorkBench.Formats.Pack.Party.Pnp.LevelTable.Types; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Pack.Party.Pnp.LevelTable +{ + /// + /// Level table binary-view model + /// + public sealed class LevelTableBinaryModel : TExcelBinBinaryModel + { + /// + /// Level table entries + /// + public List Levels { get; set; } = new(); + + /// + /// Deserializes the contents of this model from a file + /// + /// Binary stream to the file + public override void Read(ReadStream reader) + { + // Level count is dynamically calculated + ulong levelNum = reader.Length / LevelEntry.STRUCT_SIZE; + + for (ulong i = 0; i < levelNum; i++) + { + LevelEntry level = new(); + level.Read(reader); + Levels.Add(level); + } + } + + /// + /// Serializes the contents of this model to a file + /// + /// Binary stream to the file + public override void Write(WriteStream writer) + { + Levels.ForEach(it => it.Write(writer)); + } + + /// + /// Updates this model to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void OnSync(ExcelBinDataModel dataModel) + { + LevelTableDataModel src = (LevelTableDataModel)dataModel; + + Levels = src.Levels; + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/LevelTable/LevelTableDataModel.cs b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/LevelTable/LevelTableDataModel.cs new file mode 100644 index 0000000..e2631dd --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/LevelTable/LevelTableDataModel.cs @@ -0,0 +1,47 @@ +using LibWorkBench.API.Pack.Party.Pnp; +using LibWorkBench.Formats.Pack.Details; +using LibWorkBench.Formats.Pack.Party.Pnp.LevelTable.Types; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Pack.Party.Pnp.LevelTable +{ + /// + /// Level table data-view model + /// + public sealed class LevelTableDataModel : TExcelBinDataModel + { + /// + /// Level table entries + /// + public List Levels { get; set; } = new(); + + /// + /// Deserializes the contents of this model from a file + /// + /// Stream to the JSON file + public override void Load(JsonFileReader reader) + { + reader.Deserialize(this); + } + + /// + /// Serializes the contents of this model to a file + /// + /// Stream to the JSON file + public override void Dump(JsonFileWriter writer) + { + writer.Serialize(this); + } + + /// + /// Updates this model to match the contents of the binary-view model + /// + /// Binary-view model + public override void OnSync(ExcelBinBinaryModel binaryModel) + { + LevelTableBinaryModel src = (LevelTableBinaryModel)binaryModel; + + Levels = src.Levels; + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/LevelTable/Types/LevelEntry.cs b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/LevelTable/Types/LevelEntry.cs new file mode 100644 index 0000000..ad47d75 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/LevelTable/Types/LevelEntry.cs @@ -0,0 +1,53 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Pack.Party.Pnp.LevelTable.Types +{ + /// + /// Level table entry + /// + public sealed class LevelEntry : IUseBinary + { + /// + /// Size of this structure when saved in binary form + /// + public const int STRUCT_SIZE = 12; + + /// + /// Probability of returning the ball in the "easy" difficulty direction + /// + public uint EasyChance { get; set; } = 0; + + /// + /// Probability of returning the ball in the "medium" difficulty direction + /// + public uint MediumChance { get; set; } = 0; + + /// + /// Probability of returning the ball in the "hard" difficulty direction + /// + public uint HardChance { get; set; } = 0; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + EasyChance = reader.ReadU32(); + MediumChance = reader.ReadU32(); + HardChance = reader.ReadU32(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU32(EasyChance); + writer.WriteU32(MediumChance); + writer.WriteU32(HardChance); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/RallyLevelUpTable/RallyLevelUpTableBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/RallyLevelUpTable/RallyLevelUpTableBinaryModel.cs new file mode 100644 index 0000000..c029980 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/RallyLevelUpTable/RallyLevelUpTableBinaryModel.cs @@ -0,0 +1,56 @@ +using LibWorkBench.API.Pack.Party.Pnp; +using LibWorkBench.Formats.Pack.Details; +using LibWorkBench.Formats.Pack.Party.Pnp.RallyLevelUpTable.Types; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Pack.Party.Pnp.RallyLevelUpTable +{ + /// + /// Rally level-up table binary-view model + /// + public sealed class RallyLevelUpTableBinaryModel : TExcelBinBinaryModel + { + /// + /// Level table entries + /// + public List Levels { get; set; } = new(); + + /// + /// Deserializes the contents of this model from a file + /// + /// Binary stream to the file + public override void Read(ReadStream reader) + { + // Level count is dynamically calculated + ulong levelNum = reader.Length / RallyLevelUpEntry.STRUCT_SIZE; + + for (ulong i = 0; i < levelNum; i++) + { + RallyLevelUpEntry level = new(); + level.Read(reader); + Levels.Add(level); + } + } + + /// + /// Serializes the contents of this model to a file + /// + /// Binary stream to the file + public override void Write(WriteStream writer) + { + Levels.ForEach(it => it.Write(writer)); + } + + /// + /// Updates this model to match the contents of the data-view model (derived implementation) + /// + /// Data-view model + public override void OnSync(ExcelBinDataModel dataModel) + { + RallyLevelUpTableDataModel src = + (RallyLevelUpTableDataModel)dataModel; + + Levels = src.Levels; + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/RallyLevelUpTable/RallyLevelUpTableDataModel.cs b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/RallyLevelUpTable/RallyLevelUpTableDataModel.cs new file mode 100644 index 0000000..e676760 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/RallyLevelUpTable/RallyLevelUpTableDataModel.cs @@ -0,0 +1,48 @@ +using LibWorkBench.API.Pack.Party.Pnp; +using LibWorkBench.Formats.Pack.Details; +using LibWorkBench.Formats.Pack.Party.Pnp.RallyLevelUpTable.Types; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Pack.Party.Pnp.RallyLevelUpTable +{ + /// + /// Rally level-up table data-view model + /// + public sealed class RallyLevelUpTableDataModel : TExcelBinDataModel + { + /// + /// Level table entries + /// + public List Levels { get; set; } = new(); + + /// + /// Deserializes the contents of this model from a file + /// + /// Stream to the JSON file + public override void Load(JsonFileReader reader) + { + reader.Deserialize(this); + } + + /// + /// Serializes the contents of this model to a file + /// + /// Stream to the JSON file + public override void Dump(JsonFileWriter writer) + { + writer.Serialize(this); + } + + /// + /// Updates this model to match the contents of the binary-view model + /// + /// Binary-view model + public override void OnSync(ExcelBinBinaryModel binaryModel) + { + RallyLevelUpTableBinaryModel src + = (RallyLevelUpTableBinaryModel)binaryModel; + + Levels = src.Levels; + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/RallyLevelUpTable/Types/RallyLevelUpEntry.cs b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/RallyLevelUpTable/Types/RallyLevelUpEntry.cs new file mode 100644 index 0000000..138a196 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/Party/Pnp/RallyLevelUpTable/Types/RallyLevelUpEntry.cs @@ -0,0 +1,53 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Pack.Party.Pnp.RallyLevelUpTable.Types +{ + /// + /// Rally level-up table entry + /// + public sealed class RallyLevelUpEntry : IUseBinary + { + /// + /// Size of this structure when saved in binary form + /// + public const int STRUCT_SIZE = 12; + + /// + /// Minimum rally count required to reach this level-up + /// + public uint Rally { get; set; } = 0; + + /// + /// AI control level to use (index into the LevelTable) + /// + public uint LevelIndex { get; set; } = 0; + + /// + /// Speed at which the ball will move + /// + public float Power { get; set; } = 0.0f; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + Rally = reader.ReadU32(); + LevelIndex = reader.ReadU32(); + Power = reader.ReadF32(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU32(Rally); + writer.WriteU32(LevelIndex); + writer.WriteF32(Power); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/TExcelBinBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/Pack/TExcelBinBinaryModel.cs new file mode 100644 index 0000000..86faef7 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/TExcelBinBinaryModel.cs @@ -0,0 +1,19 @@ +using LibWorkBench.Core.Models.Details; +using LibWorkBench.Formats.Pack.Details; + +namespace LibWorkBench.Formats.Pack +{ + /// + /// Base class for ExcelBin binary-view models + /// + /// Parent resource class + public abstract class TExcelBinBinaryModel : ExcelBinBinaryModel + where TParentResource : ResourceImpl + { + /// + /// Resource that owns this model + /// + public new TParentResource? Resource + => (TParentResource?)base.Resource; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Pack/TExcelBinDataModel.cs b/tools/workbench/LibWorkBench/Formats/Pack/TExcelBinDataModel.cs new file mode 100644 index 0000000..fcdf1bb --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Pack/TExcelBinDataModel.cs @@ -0,0 +1,21 @@ +using LibWorkBench.Core.Models.Details; +using LibWorkBench.Formats.Pack.Details; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Formats.Pack +{ + /// + /// Base class for ExcelBin data-view models + /// + /// Parent resource class + public abstract class TExcelBinDataModel : ExcelBinDataModel + where TParentResource : ResourceImpl + { + /// + /// Resource that owns this model + /// + [JsonIgnore] + public new TParentResource? Resource + => (TParentResource?)base.Resource; + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Revolution/GX/Types/GXColor.cs b/tools/workbench/LibWorkBench/Formats/Revolution/GX/Types/GXColor.cs new file mode 100644 index 0000000..1dbc373 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Revolution/GX/Types/GXColor.cs @@ -0,0 +1,55 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Revolution.GX.Types +{ + /// + /// 8-bit RGBA color + /// + public sealed class GXColor : IUseBinary + { + /// + /// Red component + /// + public byte R { get; set; } = 0; + + /// + /// Green component + /// + public byte G { get; set; } = 0; + + /// + /// Blue component + /// + public byte B { get; set; } = 0; + + /// + /// Alpha component + /// + public byte A { get; set; } = 0; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + R = reader.ReadU8(); + G = reader.ReadU8(); + B = reader.ReadU8(); + A = reader.ReadU8(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteU8(R); + writer.WriteU8(G); + writer.WriteU8(B); + writer.WriteU8(A); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Revolution/GX/Types/GXColorS10.cs b/tools/workbench/LibWorkBench/Formats/Revolution/GX/Types/GXColorS10.cs new file mode 100644 index 0000000..4797e7d --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Revolution/GX/Types/GXColorS10.cs @@ -0,0 +1,55 @@ +using LibWorkBench.Core; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats.Revolution.GX.Types +{ + /// + /// 16-bit RGBA color + /// + public sealed class GXColorS10 : IUseBinary + { + /// + /// Red component + /// + public short R { get; set; } = 0; + + /// + /// Green component + /// + public short G { get; set; } = 0; + + /// + /// Blue component + /// + public short B { get; set; } = 0; + + /// + /// Alpha component + /// + public short A { get; set; } = 0; + + /// + /// Deserializes the contents of this object from a file + /// + /// Binary stream to the file + public void Read(ReadStream reader) + { + R = reader.ReadS16(); + G = reader.ReadS16(); + B = reader.ReadS16(); + A = reader.ReadS16(); + } + + /// + /// Serializes the contents of this object to a file + /// + /// Binary stream to the file + public void Write(WriteStream writer) + { + writer.WriteS16(R); + writer.WriteS16(G); + writer.WriteS16(B); + writer.WriteS16(A); + } + } +} diff --git a/tools/workbench/LibWorkBench/Formats/Revolution/GX/Types/GXEnum.cs b/tools/workbench/LibWorkBench/Formats/Revolution/GX/Types/GXEnum.cs new file mode 100644 index 0000000..563f891 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/Revolution/GX/Types/GXEnum.cs @@ -0,0 +1,472 @@ +namespace LibWorkBench.Formats.Revolution.GX.Types +{ + public enum GXAlphaOp + { + GX_AOP_AND, + GX_AOP_OR, + GX_AOP_XOR, + GX_AOP_XNOR, + + GX_MAX_ALPHAOP + } + + public enum GXBlendFactor + { + GX_BL_ZERO, + GX_BL_ONE, + GX_BL_SRCCLR, + GX_BL_INVSRCCLR, + GX_BL_SRCALPHA, + GX_BL_INVSRCALPHA, + GX_BL_DSTALPHA, + GX_BL_INVDSTALPHA, + + GX_BL_DSTCLR = GX_BL_SRCCLR, + GX_BL_INVDSTCLR = GX_BL_INVSRCCLR + } + + public enum GXBlendMode + { + GX_BM_NONE, + GX_BM_BLEND, + GX_BM_LOGIC, + GX_BM_SUBTRACT, + + GX_MAX_BLENDMODE + } + + public enum GXChannelID + { + GX_COLOR0, + GX_COLOR1, + GX_ALPHA0, + GX_ALPHA1, + GX_COLOR0A0, + GX_COLOR1A1, + GX_COLOR_ZERO, + GX_ALPHA_BUMP, + GX_ALPHA_BUMPN, + + GX_COLOR_NULL = 255 + } + + public enum GXColorSrc + { + GX_SRC_REG, + GX_SRC_VTX + } + + public enum GXCompare + { + GX_NEVER, + GX_LESS, + GX_EQUAL, + GX_LEQUAL, + GX_GREATER, + GX_NEQUAL, + GX_GEQUAL, + GX_ALWAYS + } + + public enum GXIndTexAlphaSel + { + GX_ITBA_OFF, + GX_ITBA_S, + GX_ITBA_T, + GX_ITBA_U, + + GX_MAX_ITBALPHA + } + + public enum GXIndTexBiasSel + { + GX_ITB_NONE, + GX_ITB_S, + GX_ITB_T, + GX_ITB_ST, + GX_ITB_U, + GX_ITB_SU, + GX_ITB_TU, + GX_ITB_STU, + + GX_MAX_ITBIAS + } + + public enum GXIndTexFormat + { + GX_ITF_8, + GX_ITF_5, + GX_ITF_4, + GX_ITF_3, + + GX_MAX_ITFORMAT + } + + public enum GXIndTexMtxID + { + GX_ITM_OFF, + GX_ITM_0, + GX_ITM_1, + GX_ITM_2, + + GX_ITM_S0 = 5, + GX_ITM_S1, + GX_ITM_S2, + + GX_ITM_T0 = 9, + GX_ITM_T1, + GX_ITM_T2 + } + + public enum GXIndTexScale + { + GX_ITS_1, + GX_ITS_2, + GX_ITS_4, + GX_ITS_8, + GX_ITS_16, + GX_ITS_32, + GX_ITS_64, + GX_ITS_128, + GX_ITS_256, + + GX_MAX_ITSCALE + } + + public enum GXIndTexStageID + { + GX_INDTEXSTAGE0, + GX_INDTEXSTAGE1, + GX_INDTEXSTAGE2, + GX_INDTEXSTAGE3, + + GX_MAX_INDTEXSTAGE + } + + public enum GXIndTexWrap + { + GX_ITW_OFF, + GX_ITW_256, + GX_ITW_128, + GX_ITW_64, + GX_ITW_32, + GX_ITW_16, + GX_ITW_0, + + GX_MAX_ITWRAP + } + + public enum GXLogicOp + { + GX_LO_CLEAR, + GX_LO_AND, + GX_LO_REVAND, + GX_LO_COPY, + GX_LO_INVAND, + GX_LO_NOOP, + GX_LO_XOR, + GX_LO_OR, + GX_LO_NOR, + GX_LO_EQUIV, + GX_LO_INV, + GX_LO_REVOR, + GX_LO_INVCOPY, + GX_LO_INVOR, + GX_LO_NAND, + GX_LO_SET + } + + public enum GXTevAlphaArg + { + GX_CA_APREV, + GX_CA_A0, + GX_CA_A1, + GX_CA_A2, + GX_CA_TEXA, + GX_CA_RASA, + GX_CA_KONST, + GX_CA_ZERO, + GX_CA_ONE + } + + public enum GXTevBias + { + GX_TB_ZERO, + GX_TB_ADDHALF, + GX_TB_SUBHALF, + + GX_MAX_TEVBIAS + } + + public enum GXTevColorArg + { + GX_CC_CPREV, + GX_CC_APREV, + GX_CC_C0, + GX_CC_A0, + GX_CC_C1, + GX_CC_A1, + GX_CC_C2, + GX_CC_A2, + GX_CC_TEXC, + GX_CC_TEXA, + GX_CC_RASC, + GX_CC_RASA, + GX_CC_ONE, + GX_CC_HALF, + GX_CC_KONST, + GX_CC_ZERO, + GX_CC_TEXRRR, + GX_CC_TEXGGG, + GX_CC_TEXBBB, + + GX_CC_QUARTER = GX_CC_KONST + } + + public enum GXTevColorChan + { + GX_CH_RED, + GX_CH_GREEN, + GX_CH_BLUE, + GX_CH_ALPHA + } + + public enum GXTevOp + { + GX_TEV_ADD, + GX_TEV_SUB, + + GX_TEV_COMP_R8_GT = 8, + GX_TEV_COMP_R8_EQ, + GX_TEV_COMP_GR16_GT, + GX_TEV_COMP_GR16_EQ, + GX_TEV_COMP_BGR24_GT, + GX_TEV_COMP_BGR24_EQ, + GX_TEV_COMP_RGB8_GT, + GX_TEV_COMP_RGB8_EQ, + + GX_TEV_COMP_A8_GT = GX_TEV_COMP_RGB8_GT, + GX_TEV_COMP_A8_EQ = GX_TEV_COMP_RGB8_EQ + } + + public enum GXTevRegID + { + GX_TEVPREV, + GX_TEVREG0, + GX_TEVREG1, + GX_TEVREG2, + + GX_MAX_TEVREG + } + + public enum GXTevScale + { + GX_CS_SCALE_1, + GX_CS_SCALE_2, + GX_CS_SCALE_4, + GX_CS_DIVIDE_2, + + GX_MAX_TEVSCALE + } + + public enum GXTevStageID + { + GX_TEVSTAGE0, + GX_TEVSTAGE1, + GX_TEVSTAGE2, + GX_TEVSTAGE3, + GX_TEVSTAGE4, + GX_TEVSTAGE5, + GX_TEVSTAGE6, + GX_TEVSTAGE7, + GX_TEVSTAGE8, + GX_TEVSTAGE9, + GX_TEVSTAGE10, + GX_TEVSTAGE11, + GX_TEVSTAGE12, + GX_TEVSTAGE13, + GX_TEVSTAGE14, + GX_TEVSTAGE15, + + GX_MAX_TEVSTAGE + } + + public enum GXTevSwapSel + { + GX_TEV_SWAP0, + GX_TEV_SWAP1, + GX_TEV_SWAP2, + GX_TEV_SWAP3, + + GX_MAX_TEVSWAP + } + + public enum GXTevKAlphaSel + { + GX_TEV_KASEL_8_8, + GX_TEV_KASEL_7_8, + GX_TEV_KASEL_6_8, + GX_TEV_KASEL_5_8, + GX_TEV_KASEL_4_8, + GX_TEV_KASEL_3_8, + GX_TEV_KASEL_2_8, + GX_TEV_KASEL_1_8, + + GX_TEV_KASEL_1 = 0, + GX_TEV_KASEL_3_4 = 2, + GX_TEV_KASEL_1_2 = 4, + GX_TEV_KASEL_1_4 = 6, + + GX_TEV_KASEL_K0_R = 16, + GX_TEV_KASEL_K1_R, + GX_TEV_KASEL_K2_R, + GX_TEV_KASEL_K3_R, + GX_TEV_KASEL_K0_G, + GX_TEV_KASEL_K1_G, + GX_TEV_KASEL_K2_G, + GX_TEV_KASEL_K3_G, + GX_TEV_KASEL_K0_B, + GX_TEV_KASEL_K1_B, + GX_TEV_KASEL_K2_B, + GX_TEV_KASEL_K3_B, + GX_TEV_KASEL_K0_A, + GX_TEV_KASEL_K1_A, + GX_TEV_KASEL_K2_A, + GX_TEV_KASEL_K3_A + } + + public enum GXTevKColorSel + { + GX_TEV_KCSEL_8_8, + GX_TEV_KCSEL_7_8, + GX_TEV_KCSEL_6_8, + GX_TEV_KCSEL_5_8, + GX_TEV_KCSEL_4_8, + GX_TEV_KCSEL_3_8, + GX_TEV_KCSEL_2_8, + GX_TEV_KCSEL_1_8, + + GX_TEV_KCSEL_1 = 0, + GX_TEV_KCSEL_3_4 = 2, + GX_TEV_KCSEL_1_2 = 4, + GX_TEV_KCSEL_1_4 = 6, + + GX_TEV_KCSEL_K0 = 12, + GX_TEV_KCSEL_K1, + GX_TEV_KCSEL_K2, + GX_TEV_KCSEL_K3, + GX_TEV_KCSEL_K0_R, + GX_TEV_KCSEL_K1_R, + GX_TEV_KCSEL_K2_R, + GX_TEV_KCSEL_K3_R, + GX_TEV_KCSEL_K0_G, + GX_TEV_KCSEL_K1_G, + GX_TEV_KCSEL_K2_G, + GX_TEV_KCSEL_K3_G, + GX_TEV_KCSEL_K0_B, + GX_TEV_KCSEL_K1_B, + GX_TEV_KCSEL_K2_B, + GX_TEV_KCSEL_K3_B, + GX_TEV_KCSEL_K0_A, + GX_TEV_KCSEL_K1_A, + GX_TEV_KCSEL_K2_A, + GX_TEV_KCSEL_K3_A + } + + public enum GXTexCoordID + { + GX_TEXCOORD0, + GX_TEXCOORD1, + GX_TEXCOORD2, + GX_TEXCOORD3, + GX_TEXCOORD4, + GX_TEXCOORD5, + GX_TEXCOORD6, + GX_TEXCOORD7, + + GX_MAX_TEXCOORD, + GX_TEXCOORD_NULL = 255 + } + + public enum GXTexGenSrc + { + GX_TG_POS, + GX_TG_NRM, + GX_TG_BINRM, + GX_TG_TANGENT, + GX_TG_TEX0, + GX_TG_TEX1, + GX_TG_TEX2, + GX_TG_TEX3, + GX_TG_TEX4, + GX_TG_TEX5, + GX_TG_TEX6, + GX_TG_TEX7, + GX_TG_TEXCOORD0, + GX_TG_TEXCOORD1, + GX_TG_TEXCOORD2, + GX_TG_TEXCOORD3, + GX_TG_TEXCOORD4, + GX_TG_TEXCOORD5, + GX_TG_TEXCOORD6, + GX_TG_COLOR0, + GX_TG_COLOR1 + } + + public enum GXTexGenType + { + GX_TG_MTX3x4, + GX_TG_MTX2x4, + GX_TG_BUMP0, + GX_TG_BUMP1, + GX_TG_BUMP2, + GX_TG_BUMP3, + GX_TG_BUMP4, + GX_TG_BUMP5, + GX_TG_BUMP6, + GX_TG_BUMP7, + GX_TG_SRTG + } + + public enum GXTexMapID + { + GX_TEXMAP0, + GX_TEXMAP1, + GX_TEXMAP2, + GX_TEXMAP3, + GX_TEXMAP4, + GX_TEXMAP5, + GX_TEXMAP6, + GX_TEXMAP7, + GX_MAX_TEXMAP, + + GX_TEXMAP_NULL = 255, + GX_TEX_DISABLE + } + + public enum GXTexMtx + { + // Any dimension (in standard XF matrix memory) + // Enum represents base row of matrix + GX_TEXMTX0 = 30, + GX_TEXMTX1 = 33, + GX_TEXMTX2 = 36, + GX_TEXMTX3 = 39, + GX_TEXMTX4 = 42, + GX_TEXMTX5 = 45, + GX_TEXMTX6 = 48, + GX_TEXMTX7 = 51, + GX_TEXMTX8 = 54, + GX_TEXMTX9 = 57, + GX_IDENTITY = 60 + } + + public enum GXTexWrapMode + { + GX_CLAMP, + GX_REPEAT, + GX_MIRROR, + + GX_MAX_TEXWRAPMODE + } +} diff --git a/tools/workbench/LibWorkBench/Formats/TRawBinaryModel.cs b/tools/workbench/LibWorkBench/Formats/TRawBinaryModel.cs new file mode 100644 index 0000000..06e8277 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/TRawBinaryModel.cs @@ -0,0 +1,67 @@ +using LibWorkBench.Core.Models.Binary; +using LibWorkBench.Core.Models.Details; +using LibWorkBench.Exceptions; +using LibWorkBench.IO.Streams; + +namespace LibWorkBench.Formats +{ + /// + /// Base class for simple/"single-block" binary-view models + /// + /// Parent resource class + public abstract class TRawBinaryModel : BinaryModel + where TParentResource : ResourceImpl + { + /// + /// Resource that owns this model + /// + public new TParentResource? Resource + => (TParentResource?)base.Resource; + + /// + /// Deserializes the contents of this model from a file + /// + /// Binary stream to the file + public override void Read(ReadStream reader) + { + string signature = reader.ReadString( + maxlen: Profile.Signature.Length + ); + + if (signature != Profile.Signature) + { + throw new FileSignatureException( + $"File signature does not match " + + $"(expected {Profile.Signature}, got {signature})"); + } + + OnRead(reader); + } + + /// + /// Serializes the contents of this model to a file + /// + /// Binary stream to the file + public override void Write(WriteStream writer) + { + writer.WriteString( + Profile.Signature, + exact: true + ); + + OnWrite(writer); + } + + /// + /// Deserializes the contents of this model from a file (derived implementation) + /// + /// Binary stream to the file + public abstract void OnRead(ReadStream reader); + + /// + /// Serializes the contents of this model to a file (derived implementation) + /// + /// Binary stream to the file + public abstract void OnWrite(WriteStream writer); + } +} diff --git a/tools/workbench/LibWorkBench/Formats/TRawDataModel.cs b/tools/workbench/LibWorkBench/Formats/TRawDataModel.cs new file mode 100644 index 0000000..192d8b4 --- /dev/null +++ b/tools/workbench/LibWorkBench/Formats/TRawDataModel.cs @@ -0,0 +1,21 @@ +using LibWorkBench.Core.Models.Data; +using LibWorkBench.Core.Models.Details; +using System.Text.Json.Serialization; + +namespace LibWorkBench.Formats +{ + /// + /// Base class for simple data-view models + /// + /// Parent resource class + public abstract class TRawDataModel : DataModel + where TParentResource : ResourceImpl + { + /// + /// Resource that owns this model + /// + [JsonIgnore] + public new TParentResource? Resource + => (TParentResource?)base.Resource; + } +} diff --git a/tools/workbench/LibWorkBench/IO/Encodings/BinaryCharEncoding.cs b/tools/workbench/LibWorkBench/IO/Encodings/BinaryCharEncoding.cs new file mode 100644 index 0000000..7332fc3 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Encodings/BinaryCharEncoding.cs @@ -0,0 +1,121 @@ +using LibWorkBench.IO.Encodings.Detail; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; +using System.Text; + +namespace LibWorkBench.IO.Encodings +{ + /// + /// Binary (null-terminated) character encoding strategy + /// + public sealed class BinaryCharEncoding : CharEncodingImpl, ICharEncoding + { + /// + /// Reads an ASCII string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadString(IDataSource source, EndianUtil.Type endian, + int maxlen, bool exact) + { + return ReadStringImpl(source, Encoding.ASCII, maxlen, + terminate: true, exact); + } + + /// + /// Writes an ASCII string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public void WriteString(IDataSource source, EndianUtil.Type endian, + string value, int maxlen, bool terminate, + bool exact) + { + WriteStringImpl(source, Encoding.ASCII, value, maxlen, terminate, exact); + } + + /// + /// Reads a UTF-16 string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadWideString(IDataSource source, + EndianUtil.Type endian, int maxlen, + bool exact) + { + return ReadStringImpl( + source, + endian == EndianUtil.Type.Little + ? Encoding.Unicode : Encoding.BigEndianUnicode, + maxlen, + terminate: true, + exact + ); + } + + /// + /// Writes a UTF-16 string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public void WriteWideString(IDataSource source, EndianUtil.Type endian, + string value, int maxlen, bool terminate, + bool exact) + { + WriteStringImpl( + source, + endian == EndianUtil.Type.Little + ? Encoding.Unicode : Encoding.BigEndianUnicode, + value, + maxlen, + terminate, + exact + ); + } + + /// + /// Reads a Shift-JIS string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadSjisString(IDataSource source, + EndianUtil.Type endian, int maxlen, + bool exact) + { + throw new NotImplementedException("Not yet implemented"); + } + + /// + /// Writes a Shift-JIS string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public void WriteSjisString(IDataSource source, EndianUtil.Type endian, + string value, int maxlen, bool terminate, + bool exact) + { + throw new NotImplementedException("Not yet implemented"); + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Encodings/BinaryPrimEncoding.cs b/tools/workbench/LibWorkBench/IO/Encodings/BinaryPrimEncoding.cs new file mode 100644 index 0000000..0c8ecfd --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Encodings/BinaryPrimEncoding.cs @@ -0,0 +1,261 @@ +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Encodings +{ + /// + /// Binary primitive encoding strategy + /// + public sealed class BinaryPrimEncoding : IPrimEncoding + { + /// + /// Reads an unsigned 8-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 8-bit value + public byte ReadU8(IDataSource source, EndianUtil.Type endian) + { + byte[] buffer = source.Read(sizeof(byte)); + return buffer.First(); + } + + /// + /// Reads an unsigned 16-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 16-bit value + public ushort ReadU16(IDataSource source, EndianUtil.Type endian) + { + byte[] buffer = source.Read(sizeof(ushort)); + return EndianUtil.ToEndian(BitConverter.ToUInt16(buffer), endian); + } + + /// + /// Reads an unsigned 32-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 32-bit value + public uint ReadU32(IDataSource source, EndianUtil.Type endian) + { + byte[] buffer = source.Read(sizeof(uint)); + return EndianUtil.ToEndian(BitConverter.ToUInt32(buffer), endian); + } + + /// + /// Reads an unsigned 64-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 64-bit value + public ulong ReadU64(IDataSource source, EndianUtil.Type endian) + { + byte[] buffer = source.Read(sizeof(ulong)); + return EndianUtil.ToEndian(BitConverter.ToUInt64(buffer), endian); + } + + /// + /// Reads a signed 8-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 8-bit value + public sbyte ReadS8(IDataSource source, EndianUtil.Type endian) + { + byte[] buffer = source.Read(sizeof(sbyte)); + return (sbyte)buffer.First(); + } + + /// + /// Reads a signed 16-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 16-bit value + public short ReadS16(IDataSource source, EndianUtil.Type endian) + { + byte[] buffer = source.Read(sizeof(short)); + return EndianUtil.ToEndian(BitConverter.ToInt16(buffer), endian); + } + + /// + /// Reads a signed 32-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 32-bit value + public int ReadS32(IDataSource source, EndianUtil.Type endian) + { + byte[] buffer = source.Read(sizeof(int)); + return EndianUtil.ToEndian(BitConverter.ToInt32(buffer), endian); + } + + /// + /// Reads a signed 64-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 64-bit value + public long ReadS64(IDataSource source, EndianUtil.Type endian) + { + byte[] buffer = source.Read(sizeof(long)); + return EndianUtil.ToEndian(BitConverter.ToInt64(buffer), endian); + } + + /// + /// Reads a single-precision floating point value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Single-precision floating point value + public float ReadF32(IDataSource source, EndianUtil.Type endian) + { + byte[] buffer = source.Read(sizeof(float)); + return EndianUtil.ToEndian(BitConverter.ToSingle(buffer), endian); + } + + /// + /// Reads a double-precision floating point value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Double-precision floating point value + public double ReadF64(IDataSource source, EndianUtil.Type endian) + { + byte[] buffer = source.Read(sizeof(double)); + return EndianUtil.ToEndian(BitConverter.ToDouble(buffer), endian); + } + + /// + /// Writes an unsigned 8-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 8-bit value + public void WriteU8(IDataSource source, EndianUtil.Type endian, + byte value) + { + byte[] buffer = { value }; + source.Write(buffer); + } + + /// + /// Writes an unsigned 16-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 16-bit value + public void WriteU16(IDataSource source, EndianUtil.Type endian, + ushort value) + { + byte[] buffer = BitConverter.GetBytes(EndianUtil.ToEndian(value, endian)); + source.Write(buffer); + } + + /// + /// Writes an unsigned 32-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 32-bit value + public void WriteU32(IDataSource source, EndianUtil.Type endian, + uint value) + { + byte[] buffer = BitConverter.GetBytes(EndianUtil.ToEndian(value, endian)); + source.Write(buffer); + } + + /// + /// Writes an unsigned 64-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 64-bit value + public void WriteU64(IDataSource source, EndianUtil.Type endian, + ulong value) + { + byte[] buffer = BitConverter.GetBytes(EndianUtil.ToEndian(value, endian)); + source.Write(buffer); + } + + /// + /// Writes a signed 8-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 8-bit value + public void WriteS8(IDataSource source, EndianUtil.Type endian, + sbyte value) + { + byte[] buffer = { (byte)value }; + source.Write(buffer); + } + + /// + /// Writes a signed 16-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 16-bit value + public void WriteS16(IDataSource source, EndianUtil.Type endian, + short value) + { + byte[] buffer = BitConverter.GetBytes(EndianUtil.ToEndian(value, endian)); + source.Write(buffer); + } + + /// + /// Writes a signed 32-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 32-bit value + public void WriteS32(IDataSource source, EndianUtil.Type endian, + int value) + { + byte[] buffer = BitConverter.GetBytes(EndianUtil.ToEndian(value, endian)); + source.Write(buffer); + } + + /// + /// Writes a signed 64-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 64-bit value + public void WriteS64(IDataSource source, EndianUtil.Type endian, + long value) + { + byte[] buffer = BitConverter.GetBytes(EndianUtil.ToEndian(value, endian)); + source.Write(buffer); + } + + /// + /// Writes a single-precision floating point value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Single-precision floating point value + public void WriteF32(IDataSource source, EndianUtil.Type endian, + float value) + { + byte[] buffer = BitConverter.GetBytes(EndianUtil.ToEndian(value, endian)); + source.Write(buffer); + } + + /// + /// Writes a double-precision floating point value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Double-precision floating point value + public void WriteF64(IDataSource source, EndianUtil.Type endian, + double value) + { + byte[] buffer = BitConverter.GetBytes(EndianUtil.ToEndian(value, endian)); + source.Write(buffer); + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Encodings/Detail/CharEncodingImpl.cs b/tools/workbench/LibWorkBench/IO/Encodings/Detail/CharEncodingImpl.cs new file mode 100644 index 0000000..dc5226e --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Encodings/Detail/CharEncodingImpl.cs @@ -0,0 +1,100 @@ +using LibWorkBench.IO.Sources; +using System.Text; + +namespace LibWorkBench.IO.Encodings.Detail +{ + /// + /// Base class for stream character encodings (internal implementation) + /// + public class CharEncodingImpl + { + /// + /// Reads a string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Character encoding + /// Maximum string length + /// Whether to expect a null-terminated string + /// Whether to read exactly `maxlen` bytes + /// String value + protected static string ReadStringImpl(IDataSource source, + Encoding encoding, int maxlen, + bool terminate, bool exact) + { + StringBuilder builder = new StringBuilder(); + ulong stride = (ulong)(encoding.IsSingleByte ? 1 : 2); + + while (!source.EOF && builder.Length < maxlen) + { + byte[] data = source.Read(sizeof(byte) * stride); + + // Null-terminator + if (terminate && data.All(c => c == '\0')) + { + break; + } + + // Newline + if (!terminate && ( + (stride == 1 && data[0] == '\n') || + (stride == 2 && data[0] == '\r' && data[1] == '\n') + )) + { + break; + } + + builder.Append(encoding.GetChars(data)); + } + + // Skip to the end of fixed-size buffers + if (exact && builder.Length < maxlen) + { + source.Seek((maxlen - (builder.Length + 1)) * (int)stride, + SeekOrigin.Current); + } + + return builder.ToString(); + } + + /// + /// Writes a string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Character encoding + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + protected static void WriteStringImpl(IDataSource source, + Encoding encoding, string value, + int maxlen, bool terminate, + bool exact) + { + ulong stride = (ulong)(encoding.IsSingleByte ? 1 : 2); + + byte[] data = encoding.GetBytes(value); + source.Write(data); + + // Determine padding size + ulong fillNum = 0; + if (value.Length < maxlen) + { + // Null terminator (if there is room) + if (terminate) + { + fillNum = 1; + } + // Fill fixed-size buffers + else if (exact) + { + fillNum = (ulong)(maxlen - value.Length); + } + } + + for (ulong i = 0; i < fillNum * stride; i++) + { + source.Write([0x00]); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Encodings/DummyCharEncoding.cs b/tools/workbench/LibWorkBench/IO/Encodings/DummyCharEncoding.cs new file mode 100644 index 0000000..25ef07d --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Encodings/DummyCharEncoding.cs @@ -0,0 +1,109 @@ +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Encodings +{ + /// + /// Null/dummy character encoding strategy + /// + public sealed class DummyCharEncoding : ICharEncoding + { + /// + /// Reads a UTF-8 string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadString(IDataSource source, EndianUtil.Type endian, + int maxlen, bool exact) + { + throw new NotSupportedException( + "Please register a character encoding strategy"); + } + + /// + /// Writes a UTF-8 string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public void WriteString(IDataSource source, EndianUtil.Type endian, + string value, int maxlen, bool terminate, + bool exact) + { + throw new NotSupportedException( + "Please register a character encoding strategy"); + } + + /// + /// Reads a UTF-16 string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadWideString(IDataSource source, + EndianUtil.Type endian, int maxlen, + bool exact) + { + throw new NotSupportedException( + "Please register a character encoding strategy"); + } + + /// + /// Writes a UTF-16 string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public void WriteWideString(IDataSource source, EndianUtil.Type endian, + string value, int maxlen, bool terminate, + bool exact) + { + throw new NotSupportedException( + "Please register a character encoding strategy"); + } + + /// + /// Reads a Shift-JIS string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadSjisString(IDataSource source, + EndianUtil.Type endian, int maxlen, + bool exact) + { + throw new NotSupportedException( + "Please register a character encoding strategy"); + } + + /// + /// Writes a Shift-JIS string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public void WriteSjisString(IDataSource source, EndianUtil.Type endian, + string value, int maxlen, bool terminate, + bool exact) + { + throw new NotSupportedException( + "Please register a character encoding strategy"); + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Encodings/DummyPrimEncoding.cs b/tools/workbench/LibWorkBench/IO/Encodings/DummyPrimEncoding.cs new file mode 100644 index 0000000..5892f22 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Encodings/DummyPrimEncoding.cs @@ -0,0 +1,261 @@ +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Encodings +{ + /// + /// Null/dummy primitive encoding strategy + /// + public sealed class DummyPrimEncoding : IPrimEncoding + { + /// + /// Reads an unsigned 8-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 8-bit value + public byte ReadU8(IDataSource source, EndianUtil.Type endian) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Reads an unsigned 16-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 16-bit value + public ushort ReadU16(IDataSource source, EndianUtil.Type endian) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Reads an unsigned 32-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 32-bit value + public uint ReadU32(IDataSource source, EndianUtil.Type endian) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Reads an unsigned 64-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 64-bit value + public ulong ReadU64(IDataSource source, EndianUtil.Type endian) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Reads a signed 8-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 8-bit value + public sbyte ReadS8(IDataSource source, EndianUtil.Type endian) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Reads a signed 16-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 16-bit value + public short ReadS16(IDataSource source, EndianUtil.Type endian) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Reads a signed 32-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 32-bit value + public int ReadS32(IDataSource source, EndianUtil.Type endian) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Reads a signed 64-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 64-bit value + public long ReadS64(IDataSource source, EndianUtil.Type endian) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Reads a single-precision floating point value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Single-precision floating point value + public float ReadF32(IDataSource source, EndianUtil.Type endian) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Reads a double-precision floating point value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Double-precision floating point value + public double ReadF64(IDataSource source, EndianUtil.Type endian) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Writes an unsigned 8-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 8-bit value + public void WriteU8(IDataSource source, EndianUtil.Type endian, + byte value) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Writes an unsigned 16-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 16-bit value + public void WriteU16(IDataSource source, EndianUtil.Type endian, + ushort value) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Writes an unsigned 32-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 32-bit value + public void WriteU32(IDataSource source, EndianUtil.Type endian, + uint value) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Writes an unsigned 64-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 64-bit value + public void WriteU64(IDataSource source, EndianUtil.Type endian, + ulong value) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Writes a signed 8-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 8-bit value + public void WriteS8(IDataSource source, EndianUtil.Type endian, + sbyte value) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Writes a signed 16-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 16-bit value + public void WriteS16(IDataSource source, EndianUtil.Type endian, + short value) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Writes a signed 32-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 32-bit value + public void WriteS32(IDataSource source, EndianUtil.Type endian, + int value) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Writes a signed 64-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 64-bit value + public void WriteS64(IDataSource source, EndianUtil.Type endian, + long value) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Writes a single-precision floating point value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Single-precision floating point value + public void WriteF32(IDataSource source, EndianUtil.Type endian, + float value) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + + /// + /// Writes a double-precision floating point value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Double-precision floating point value + public void WriteF64(IDataSource source, EndianUtil.Type endian, + double value) + { + throw new NotSupportedException( + "Please register a primitive encoding strategy"); + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Encodings/ICharEncoding.cs b/tools/workbench/LibWorkBench/IO/Encodings/ICharEncoding.cs new file mode 100644 index 0000000..27c6d06 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Encodings/ICharEncoding.cs @@ -0,0 +1,89 @@ +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Encodings +{ + /// + /// Interface for stream character encoding types + /// + public interface ICharEncoding + { + /// + /// Reads an ASCII string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public abstract string ReadString(IDataSource source, + EndianUtil.Type endian, int maxlen, + bool exact); + + /// + /// Writes an ASCII string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public abstract void WriteString(IDataSource source, + EndianUtil.Type endian, string value, + int maxlen, bool terminate, + bool exact); + + /// + /// Reads a UTF-16 string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public abstract string ReadWideString(IDataSource source, + EndianUtil.Type endian, + int maxlen, bool exact); + + /// + /// Writes a UTF-16 string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public abstract void WriteWideString(IDataSource source, + EndianUtil.Type endian, + string value, int maxlen, + bool terminate, bool exact); + + /// + /// Reads a Shift-JIS string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public abstract string ReadSjisString(IDataSource source, + EndianUtil.Type endian, + int maxlen, bool exact); + + /// + /// Writes a Shift-JIS string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public abstract void WriteSjisString(IDataSource source, + EndianUtil.Type endian, + string value, int maxlen, + bool terminate, bool exact); + } +} diff --git a/tools/workbench/LibWorkBench/IO/Encodings/IPrimEncoding.cs b/tools/workbench/LibWorkBench/IO/Encodings/IPrimEncoding.cs new file mode 100644 index 0000000..cac7a70 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Encodings/IPrimEncoding.cs @@ -0,0 +1,191 @@ +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Encodings +{ + /// + /// Interface for stream primitive (numeric) encoding types + /// + public interface IPrimEncoding + { + /// + /// Reads an unsigned 8-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 8-bit value + public abstract byte ReadU8(IDataSource source, + EndianUtil.Type endian); + + /// + /// Reads an unsigned 16-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 16-bit value + public abstract ushort ReadU16(IDataSource source, + EndianUtil.Type endian); + + /// + /// Reads an unsigned 32-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 32-bit value + public abstract uint ReadU32(IDataSource source, + EndianUtil.Type endian); + + /// + /// Reads an unsigned 64-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 64-bit value + public abstract ulong ReadU64(IDataSource source, + EndianUtil.Type endian); + + /// + /// Reads a signed 8-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 8-bit value + public abstract sbyte ReadS8(IDataSource source, + EndianUtil.Type endian); + + /// + /// Reads a signed 16-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 16-bit value + public abstract short ReadS16(IDataSource source, + EndianUtil.Type endian); + + /// + /// Reads a signed 32-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 32-bit value + public abstract int ReadS32(IDataSource source, + EndianUtil.Type endian); + + /// + /// Reads a signed 64-bit value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 64-bit value + public abstract long ReadS64(IDataSource source, + EndianUtil.Type endian); + + /// + /// Reads a single-precision floating point value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Single-precision floating point value + public abstract float ReadF32(IDataSource source, + EndianUtil.Type endian); + + /// + /// Reads a double-precision floating point value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Double-precision floating point value + public abstract double ReadF64(IDataSource source, + EndianUtil.Type endian); + + /// + /// Writes an unsigned 8-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 8-bit value + public abstract void WriteU8(IDataSource source, + EndianUtil.Type endian, byte value); + + /// + /// Writes an unsigned 16-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 16-bit value + public abstract void WriteU16(IDataSource source, + EndianUtil.Type endian, ushort value); + + /// + /// Writes an unsigned 32-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 32-bit value + public abstract void WriteU32(IDataSource source, + EndianUtil.Type endian, uint value); + + /// + /// Writes an unsigned 64-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Unsigned 64-bit value + public abstract void WriteU64(IDataSource source, + EndianUtil.Type endian, ulong value); + + /// + /// Writes a signed 8-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 8-bit value + public abstract void WriteS8(IDataSource source, + EndianUtil.Type endian, sbyte value); + + /// + /// Writes a signed 16-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 16-bit value + public abstract void WriteS16(IDataSource source, + EndianUtil.Type endian, short value); + + /// + /// Writes a signed 32-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 32-bit value + public abstract void WriteS32(IDataSource source, + EndianUtil.Type endian, int value); + + /// + /// Writes a signed 64-bit value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Signed 64-bit value + public abstract void WriteS64(IDataSource source, + EndianUtil.Type endian, long value); + + /// + /// Writes a single-precision floating point value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Single-precision floating point value + public abstract void WriteF32(IDataSource source, + EndianUtil.Type endian, float value); + + /// + /// Writes a double-precision floating point value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Double-precision floating point value + public abstract void WriteF64(IDataSource source, + EndianUtil.Type endian, double value); + } +} diff --git a/tools/workbench/LibWorkBench/IO/Encodings/TextCharEncoding.cs b/tools/workbench/LibWorkBench/IO/Encodings/TextCharEncoding.cs new file mode 100644 index 0000000..94c8016 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Encodings/TextCharEncoding.cs @@ -0,0 +1,122 @@ +using LibWorkBench.IO.Encodings.Detail; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; +using System.Text; + +namespace LibWorkBench.IO.Encodings +{ + /// + /// Textual (non null-terminated) character encoding strategy + /// + public sealed class TextCharEncoding : CharEncodingImpl, ICharEncoding + { + /// + /// Reads an ASCII string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadString(IDataSource source, EndianUtil.Type endian, + int maxlen, bool exact) + { + return ReadStringImpl(source, Encoding.ASCII, maxlen, + terminate: false, exact: false); + } + + /// + /// Writes an ASCII string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public void WriteString(IDataSource source, EndianUtil.Type endian, + string value, int maxlen, bool terminate, + bool exact) + { + WriteStringImpl(source, Encoding.ASCII, value, maxlen, + terminate: false, exact: false); + } + + /// + /// Reads a UTF-16 string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadWideString(IDataSource source, + EndianUtil.Type endian, int maxlen, + bool exact) + { + return ReadStringImpl( + source, + endian == EndianUtil.Type.Little + ? Encoding.Unicode : Encoding.BigEndianUnicode, + maxlen, + terminate: false, + exact: false + ); + } + + /// + /// Writes a UTF-16 string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public void WriteWideString(IDataSource source, EndianUtil.Type endian, + string value, int maxlen, bool terminate, + bool exact) + { + WriteStringImpl( + source, + endian == EndianUtil.Type.Little + ? Encoding.Unicode : Encoding.BigEndianUnicode, + value, + maxlen, + terminate: false, + exact: false + ); + } + + /// + /// Reads a Shift-JIS string value from the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadSjisString(IDataSource source, + EndianUtil.Type endian, int maxlen, + bool exact) + { + throw new NotImplementedException("Not yet implemented"); + } + + /// + /// Writes a Shift-JIS string value to the data source, represented in the specified endianness + /// + /// Stream data source + /// Stream endianness + /// String value + /// Maximum string length + /// Whether to null-terminate the string + /// Whether to write exactly `maxlen` bytes + public void WriteSjisString(IDataSource source, EndianUtil.Type endian, + string value, int maxlen, bool terminate, + bool exact) + { + throw new NotImplementedException("Not yet implemented"); + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Sources/FileDataSource.cs b/tools/workbench/LibWorkBench/IO/Sources/FileDataSource.cs new file mode 100644 index 0000000..2a23370 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Sources/FileDataSource.cs @@ -0,0 +1,121 @@ +namespace LibWorkBench.IO.Sources +{ + /// + /// Stream data source for a physical file + /// + public class FileDataSource : IDataSource + { + /// + /// Whether the Dispose method has been called + /// + protected bool _disposed = false; + + /// + /// Underlying file stream + /// + public FileStream BaseStream { get; } + + /// + /// Constructor + /// + /// File path to open + /// Whether the file is writable + public FileDataSource(string path, bool writable) + { + BaseStream = new FileStream( + path, + writable ? FileMode.Create : FileMode.Open, + writable ? FileAccess.Write : FileAccess.Read + ); + } + + /// + /// Destructor + /// + ~FileDataSource() + { + Dispose(disposing: false); + } + + /// + /// Releases resources + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + /// + /// Reads a specified amount of data from the data source + /// + /// Number of bytes to read + /// Data block as an array of bytes + public byte[] Read(ulong size) + { + byte[] buffer = new byte[size]; + BaseStream.ReadExactly(buffer, 0, buffer.Length); + return buffer; + } + + /// + /// Writes a specified block of data to the data source + /// + /// Data contents to write + /// Number of bytes to write (optional) + public void Write(byte[] data, ulong? size = null) + { + BaseStream.Write(data, 0, size != null ? (int)size : data.Length); + } + + /// + /// Seeks to the specified position in the data source + /// + /// Offset (relative to the origin) + /// Origin position + public void Seek(long offset, SeekOrigin origin) + { + BaseStream.Seek(offset, origin); + } + + /// + /// Flushes the data source contents + /// + public void Close() + { + BaseStream.Close(); + } + + /// + /// Gets the current position in the data source + /// + public ulong Position => (ulong)BaseStream.Position; + /// + /// Gets the length of the data source + /// + public ulong Length => (ulong)BaseStream.Length; + /// + /// Tests whether the data source has hit the end-of-file mark + /// + public bool EOF => Position >= Length; + + /// + /// Releases resources + /// + /// Whether this method has been called from a dispose context + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + BaseStream.Dispose(); + } + + _disposed = true; + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Sources/IDataSource.cs b/tools/workbench/LibWorkBench/IO/Sources/IDataSource.cs new file mode 100644 index 0000000..b4cdfb9 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Sources/IDataSource.cs @@ -0,0 +1,47 @@ +namespace LibWorkBench.IO.Sources +{ + /// + /// Interface for stream data source types + /// + public interface IDataSource : IDisposable + { + /// + /// Reads a specified amount of data from the data source + /// + /// Number of bytes to read + /// Data block as an array of bytes + public abstract byte[] Read(ulong size); + + /// + /// Writes a specified block of data to the data source + /// + /// Data contents to write + /// Number of bytes to write (optional) + public abstract void Write(byte[] data, ulong? size = null); + + /// + /// Seeks to the specified position in the data source + /// + /// Offset (relative to the origin) + /// Origin position + public abstract void Seek(long offset, SeekOrigin origin); + + /// + /// Flushes the data source contents + /// + public abstract void Close(); + + /// + /// Gets the current position in the data source + /// + public abstract ulong Position { get; } + /// + /// Gets the length of the data source + /// + public abstract ulong Length { get; } + /// + /// Tests whether the data source has hit the end-of-file mark + /// + public abstract bool EOF { get; } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Sources/MemoryDataSource.cs b/tools/workbench/LibWorkBench/IO/Sources/MemoryDataSource.cs new file mode 100644 index 0000000..952e135 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Sources/MemoryDataSource.cs @@ -0,0 +1,117 @@ +namespace LibWorkBench.IO.Sources +{ + /// + /// Stream data source for an in-memory buffer + /// + public class MemoryDataSource : IDataSource + { + /// + /// Whether the Dispose method has been called + /// + protected bool _disposed = false; + + /// + /// Underlying buffer stream + /// + public MemoryStream BaseStream { get; } + + /// + /// Constructor + /// + /// Memory buffer to open + /// Whether the buffer is writable + public MemoryDataSource(byte[] buffer, bool writable) + { + BaseStream = new MemoryStream(buffer, writable); + } + + /// + /// Destructor + /// + ~MemoryDataSource() + { + Dispose(disposing: false); + } + + /// + /// Releases resources + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + /// + /// Reads a specified amount of data from the data source + /// + /// Number of bytes to read + /// Data block as an array of bytes + public byte[] Read(ulong size) + { + byte[] buffer = new byte[size]; + BaseStream.ReadExactly(buffer, 0, buffer.Length); + return buffer; + } + + /// + /// Writes a specified block of data to the data source + /// + /// Data contents to write + /// Number of bytes to write (optional) + public void Write(byte[] data, ulong? size = null) + { + BaseStream.Write(data, 0, size != null ? (int)size : data.Length); + } + + /// + /// Seeks to the specified position in the data source + /// + /// Offset (relative to the origin) + /// Origin position + public void Seek(long offset, SeekOrigin origin) + { + BaseStream.Seek(offset, origin); + } + + /// + /// Flushes the data source contents + /// + public void Close() + { + BaseStream.Close(); + } + + /// + /// Gets the current position in the data source + /// + public ulong Position => (ulong)BaseStream.Position; + /// + /// Gets the length of the data source + /// + public ulong Length => (ulong)BaseStream.Length; + /// + /// Tests whether the data source has hit the end-of-file mark + /// + public bool EOF => Position >= Length; + + /// + /// Releases resources + /// + /// Whether this method has been called from a dispose context + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + BaseStream.Dispose(); + } + + _disposed = true; + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Sources/StreamDataSource.cs b/tools/workbench/LibWorkBench/IO/Sources/StreamDataSource.cs new file mode 100644 index 0000000..a4f9bc9 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Sources/StreamDataSource.cs @@ -0,0 +1,114 @@ +namespace LibWorkBench.IO.Sources +{ + /// + /// Stream data source for delegating to another stream + /// + public class StreamDataSource : IDataSource + { + /// + /// Whether the Dispose method has been called + /// + private bool _disposed = false; + + /// + /// Underlying buffer stream + /// + public Streams.Stream BaseStream { get; } + + /// + /// Constructor + /// + /// Delegate stream + public StreamDataSource(Streams.Stream baseStream) + { + BaseStream = baseStream; + } + + /// + /// Destructor + /// + ~StreamDataSource() + { + Dispose(disposing: false); + } + + /// + /// Releases resources + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + /// + /// Reads a specified amount of data from the data source + /// + /// Number of bytes to read + /// Data block as an array of bytes + public byte[] Read(ulong size) + { + return BaseStream.Source.Read(size); + } + + /// + /// Writes a specified block of data to the data source + /// + /// Data contents to write + /// Number of bytes to write (optional) + public void Write(byte[] data, ulong? size = null) + { + BaseStream.Source.Write(data, size); + } + + /// + /// Seeks to the specified position in the data source + /// + /// Offset (relative to the origin) + /// Origin position + public void Seek(long offset, SeekOrigin origin) + { + BaseStream.Seek(offset, origin); + } + + /// + /// Flushes the data source contents + /// + public void Close() + { + BaseStream.Close(); + } + + /// + /// Gets the current position in the data source + /// + public ulong Position => BaseStream.Position; + /// + /// Gets the length of the data source + /// + public ulong Length => BaseStream.Length; + /// + /// Tests whether the data source has hit the end-of-file mark + /// + public bool EOF => BaseStream.EOF; + + /// + /// Releases resources + /// + /// Whether this method has been called from a dispose context + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + BaseStream.Dispose(); + } + + _disposed = true; + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Sources/WorkMemDataSource.cs b/tools/workbench/LibWorkBench/IO/Sources/WorkMemDataSource.cs new file mode 100644 index 0000000..9c13bbc --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Sources/WorkMemDataSource.cs @@ -0,0 +1,120 @@ +namespace LibWorkBench.IO.Sources +{ + /// + /// Stream data source for a resizable work/scratch memory buffer + /// + public class WorkMemDataSource : IDataSource + { + /// + /// Whether the Dispose method has been called + /// + protected bool _disposed = false; + + /// + /// Underlying buffer stream + /// + public MemoryStream BaseStream { get; } + /// + /// Underlying work memory buffer + /// + public byte[] Buffer => BaseStream.GetBuffer(); + + /// + /// Constructor + /// + public WorkMemDataSource() + { + // Provide no buffer to create resizable stream + BaseStream = new MemoryStream(); + } + + /// + /// Destructor + /// + ~WorkMemDataSource() + { + Dispose(disposing: false); + } + + /// + /// Releases resources + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + /// + /// Reads a specified amount of data from the data source + /// + /// Number of bytes to read + /// Data block as an array of bytes + public byte[] Read(ulong size) + { + byte[] buffer = new byte[size]; + BaseStream.ReadExactly(buffer, 0, buffer.Length); + return buffer; + } + + /// + /// Writes a specified block of data to the data source + /// + /// Data contents to write + /// Number of bytes to write (optional) + public void Write(byte[] data, ulong? size = null) + { + BaseStream.Write(data, 0, size != null ? (int)size : data.Length); + } + + /// + /// Seeks to the specified position in the data source + /// + /// Offset (relative to the origin) + /// Origin position + public void Seek(long offset, SeekOrigin origin) + { + BaseStream.Seek(offset, origin); + } + + /// + /// Flushes the data source contents + /// + public void Close() + { + BaseStream.Close(); + } + + /// + /// Gets the current position in the data source + /// + public ulong Position => (ulong)BaseStream.Position; + /// + /// Gets the length of the data source + /// + public ulong Length => (ulong)BaseStream.Length; + /// + /// Tests whether the data source has hit the end-of-file mark + /// + public bool EOF => Position >= Length; + + /// + /// Releases resources + /// + /// Whether this method has been called from a dispose context + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + BaseStream.Dispose(); + } + + _disposed = true; + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/BinaryFileReader.cs b/tools/workbench/LibWorkBench/IO/Streams/BinaryFileReader.cs new file mode 100644 index 0000000..12153d6 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/BinaryFileReader.cs @@ -0,0 +1,24 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Streams +{ + /// + /// Binary file stream with read access + /// + public class BinaryFileReader : FileReader + { + /// + /// Constructor + /// + /// File path to open + /// Stream endianness (byte-order) + public BinaryFileReader(string path, EndianUtil.Type endian) + : base(path, + new BinaryPrimEncoding(), + new BinaryCharEncoding(), + endian) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/BinaryFileWriter.cs b/tools/workbench/LibWorkBench/IO/Streams/BinaryFileWriter.cs new file mode 100644 index 0000000..4f3e910 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/BinaryFileWriter.cs @@ -0,0 +1,24 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Streams +{ + /// + /// Binary file stream with read+write access + /// + public class BinaryFileWriter : FileWriter + { + /// + /// Constructor + /// + /// File path to open + /// Stream endianness (byte-order) + public BinaryFileWriter(string path, EndianUtil.Type endian) + : base(path, + new BinaryPrimEncoding(), + new BinaryCharEncoding(), + endian) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/FileReader.cs b/tools/workbench/LibWorkBench/IO/Streams/FileReader.cs new file mode 100644 index 0000000..42a45e1 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/FileReader.cs @@ -0,0 +1,28 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Streams +{ + /// + /// File stream with read access + /// + public class FileReader : ReadStream + { + /// + /// Constructor + /// + /// File path to open + /// Stream primitive format + /// Stream character format + /// Stream endianness (byte-order) + public FileReader(string path, IPrimEncoding primEncoding, + ICharEncoding charEncoding, EndianUtil.Type endian) + : base(new FileDataSource(path, writable: false), + primEncoding, + charEncoding, + endian) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/FileWriter.cs b/tools/workbench/LibWorkBench/IO/Streams/FileWriter.cs new file mode 100644 index 0000000..58154bb --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/FileWriter.cs @@ -0,0 +1,28 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Streams +{ + /// + /// File stream with read+write access + /// + public class FileWriter : WriteStream + { + /// + /// Constructor + /// + /// File path to open + /// Stream primitive format + /// Stream character format + /// Stream endianness (byte-order) + public FileWriter(string path, IPrimEncoding primEncoding, + ICharEncoding charEncoding, EndianUtil.Type endian) + : base(new FileDataSource(path, writable: true), + primEncoding, + charEncoding, + endian) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/JsonFileReader.cs b/tools/workbench/LibWorkBench/IO/Streams/JsonFileReader.cs new file mode 100644 index 0000000..3464656 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/JsonFileReader.cs @@ -0,0 +1,94 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace LibWorkBench.IO.Streams +{ + /// + /// JSON file stream with read access + /// + public class JsonFileReader : Stream // (don't want prim methods) + { + /// + /// Configuration for the serializer + /// + public JsonSerializerOptions Options { get; } = new(); + + /// + /// Constructor + /// + /// File path to open + public JsonFileReader(string path) + : base(new MemoryDataSource(File.ReadAllBytes(path), + writable: false), + new DummyPrimEncoding(), + new DummyCharEncoding(), + EndianUtil.GetHostEndian()) + { + Options.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower; + + // Default enum serialization is to-string + Options.Converters.Add( + new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseUpper)); + } + + /// + /// Deserializes the contents of this JSON file + /// + /// Object type + /// Deserialized element + /// Deserialization is not possible + public T Deserialize() + { + MemoryStream stream = ((MemoryDataSource)Source).BaseStream; + T? obj = JsonSerializer.Deserialize(stream, Options); + + if (obj == null) + { + throw new JsonException(); + } + + return obj; + } + + /// + /// Deserializes the contents of this JSON file into an existing object + /// + /// Object type + /// Destination object + /// Deserialization is not possible + public void Deserialize(T dst) + { + T obj = Deserialize(); + PopulateObject(dst, obj); + } + + /// + /// Populates a destination object's properties using a specified source object + /// + /// Object type + /// Destination object + /// Source object + private static void PopulateObject(T dst, T src) + { + // Only operate on non-static, public properties + PropertyInfo[] properties = typeof(T).GetProperties( + BindingFlags.Instance | BindingFlags.Public); + + // Copy over from the source object + foreach (var it in properties) + { + // Ignore properties that are not serialized + if (Attribute.IsDefined(it, typeof(JsonIgnoreAttribute))) + { + continue; + } + + it.SetValue(dst, it.GetValue(src)); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/JsonFileWriter.cs b/tools/workbench/LibWorkBench/IO/Streams/JsonFileWriter.cs new file mode 100644 index 0000000..df1bd7d --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/JsonFileWriter.cs @@ -0,0 +1,58 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace LibWorkBench.IO.Streams +{ + /// + /// JSON file stream with write access + /// + public class JsonFileWriter : Stream // (don't want prim methods) + { + /// + /// Configuration for the serializer + /// + public JsonSerializerOptions Options { get; } = new(); + + /// + /// Constructor + /// + /// File path to open + public JsonFileWriter(string path) + : base(new FileDataSource(path, writable: true), + new DummyPrimEncoding(), + new DummyCharEncoding(), + EndianUtil.GetHostEndian()) + { + Options.IndentSize = 2; + Options.WriteIndented = true; + Options.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower; + + // Default enum serialization is to-string + Options.Converters.Add( + new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseUpper)); + } + + /// + /// Serializes the contents of the specified JSON object + /// + /// Object type + /// Source object + /// Serialization is not possible + public void Serialize(T src) + { + FileStream stream = ((FileDataSource)Source).BaseStream; + + try + { + JsonSerializer.Serialize(stream, src, Options); + } + catch (NotSupportedException e) + { + throw new JsonException(e.Message); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/MemoryReader.cs b/tools/workbench/LibWorkBench/IO/Streams/MemoryReader.cs new file mode 100644 index 0000000..dc1ff88 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/MemoryReader.cs @@ -0,0 +1,27 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Streams +{ + /// + /// Memory stream with read access + /// + public class MemoryReader : ReadStream + { + /// + /// Constructor + /// + /// Memory buffer to open + /// Stream character format + /// Stream endianness (byte-order) + public MemoryReader(byte[] buffer, ICharEncoding charEncoding, + EndianUtil.Type endian) + : base(new MemoryDataSource(buffer, writable: false), + new BinaryPrimEncoding(), + charEncoding, + endian) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/MemoryWriter.cs b/tools/workbench/LibWorkBench/IO/Streams/MemoryWriter.cs new file mode 100644 index 0000000..84a91e9 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/MemoryWriter.cs @@ -0,0 +1,27 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Streams +{ + /// + /// Memory stream with read+write access + /// + public class MemoryWriter : WriteStream + { + /// + /// Constructor + /// + /// Memory buffer to open + /// Stream character format + /// Stream endianness (byte-order) + public MemoryWriter(byte[] buffer, ICharEncoding charEncoding, + EndianUtil.Type endian) + : base(new MemoryDataSource(buffer, writable: false), + new BinaryPrimEncoding(), + charEncoding, + endian) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/ReadStream.cs b/tools/workbench/LibWorkBench/IO/Streams/ReadStream.cs new file mode 100644 index 0000000..1add8a5 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/ReadStream.cs @@ -0,0 +1,188 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Streams +{ + /// + /// Base class for streams with read access + /// + public abstract class ReadStream : Stream + { + /// + /// Constructor + /// + /// Stream data source + /// Stream primitive format + /// Stream character format + /// Stream endianness (byte-order) + public ReadStream(IDataSource source, IPrimEncoding primEncoding, + ICharEncoding charEncoding, EndianUtil.Type endian) + : base(source, + primEncoding, + charEncoding, + endian) + { + } + + /// + /// Aligns the stream position to the specified byte-alignment + /// + /// Required byte-alignment + public void Align(ulong alignment) + { + // Number of bytes required to reach alignment + ulong misalign = (alignment - (Position % alignment)) % alignment; + if (misalign == 0) + { + return; + } + + Skip((long)misalign); + } + + /// + /// Reads a specified amount of data from the data source + /// + /// Number of bytes to read + /// Data block as an array of bytes + public byte[] Read(ulong size) + { + return Source.Read(size); + } + + /// + /// Reads an unsigned 8-bit value from the stream + /// + /// Unsigned 8-bit value + public byte ReadU8() + { + return PrimEncoding.ReadU8(Source, Endian); + } + + /// + /// Reads an unsigned 16-bit value from the stream + /// + /// Unsigned 16-bit value + public ushort ReadU16() + { + return PrimEncoding.ReadU16(Source, Endian); + } + + /// + /// Reads an unsigned 32-bit value from the stream + /// + /// Unsigned 32-bit value + public uint ReadU32() + { + return PrimEncoding.ReadU32(Source, Endian); + } + + /// + /// Reads an unsigned 64-bit value from the stream + /// + /// Unsigned 64-bit value + public ulong ReadU64() + { + return PrimEncoding.ReadU64(Source, Endian); + } + + /// + /// Reads a signed 8-bit value from the stream + /// + /// Signed 8-bit value + public sbyte ReadS8() + { + return PrimEncoding.ReadS8(Source, Endian); + } + + /// + /// Reads a signed 16-bit value from the stream + /// + /// Signed 16-bit value + public short ReadS16() + { + return PrimEncoding.ReadS16(Source, Endian); + } + + /// + /// Reads a signed 32-bit value from the stream + /// + /// Signed 32-bit value + public int ReadS32() + { + return PrimEncoding.ReadS32(Source, Endian); + } + + /// + /// Reads a signed 64-bit value from the stream + /// + /// Signed 64-bit value + public long ReadS64() + { + return PrimEncoding.ReadS64(Source, Endian); + } + + /// + /// Reads a single-precision floating point value from the stream + /// + /// Single-precision floating point value + public float ReadF32() + { + return PrimEncoding.ReadF32(Source, Endian); + } + + /// + /// Reads a double-precision floating point value from the stream + /// + /// Double-precision floating point value + public double ReadF64() + { + return PrimEncoding.ReadF64(Source, Endian); + } + + /// + /// Reads a UTF-8 string value from the stream + /// + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadString(int maxlen = int.MaxValue, bool exact = false) + { + return CharEncoding.ReadString(Source, Endian, maxlen, exact); + } + + /// + /// Reads a UTF-16 string value from the stream + /// + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadWideString(int maxlen = int.MaxValue, + bool exact = false) + { + return CharEncoding.ReadWideString(Source, Endian, maxlen, exact); + } + + /// + /// Reads a Shift-JIS string value from the stream + /// + /// Maximum string length + /// Whether to read exactly `maxlen` bytes + /// String value + public string ReadSjisString(int maxlen = int.MaxValue, + bool exact = false) + { + return CharEncoding.ReadSjisString(Source, Endian, maxlen, exact); + } + + /// + /// Reads a boolean value from the stream + /// + /// Boolean value + public bool ReadBool() + { + return ReadU8() != 0; + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/Stream.cs b/tools/workbench/LibWorkBench/IO/Streams/Stream.cs new file mode 100644 index 0000000..b647811 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/Stream.cs @@ -0,0 +1,127 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Streams +{ + /// + /// Base class for stream types + /// + public abstract class Stream : IDisposable + { + /// + /// Whether the Dispose method has been called + /// + private bool _disposed = false; + + /// + /// Data source used by this stream + /// + public IDataSource Source { get; } + /// + /// Primitive format used by this stream + /// + public IPrimEncoding PrimEncoding { get; set; } + /// + /// Character format used by this stream + /// + public ICharEncoding CharEncoding { get; set; } + /// + /// Endianness (byte-order) used by this stream + /// + public EndianUtil.Type Endian { get; set; } + + /// + /// Constructor + /// + /// Stream data source + /// Stream primitive format + /// Stream character format + /// Stream endianness (byte-order) + public Stream(IDataSource source, IPrimEncoding primEncoding, + ICharEncoding charEncoding, EndianUtil.Type endian) + { + Source = source; + PrimEncoding = primEncoding; + CharEncoding = charEncoding; + Endian = endian; + } + + /// + /// Destructor + /// + ~Stream() + { + Dispose(disposing: false); + } + + /// + /// Releases and finalizes resources + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + /// + /// Seeks to the specified position in the stream + /// + /// Offset (relative to the origin) + /// Origin position + public void Seek(long offset, SeekOrigin origin) + { + Source.Seek(offset, origin); + } + + /// + /// Seeks relative to the current stream position + /// + /// Offset (relative to the current position) + public void Skip(long offset) + { + Seek(offset, SeekOrigin.Current); + } + + /// + /// Closes the stream, flushing the data source contents + /// + public void Close() + { + Source.Close(); + } + + /// + /// Gets the stream's current position + /// + public ulong Position => Source.Position; + /// + /// Gets the stream's data length + /// + public ulong Length => Source.Length; + /// + /// Tests whether the stream has hit the end-of-file mark + /// + public bool EOF => Source.EOF; + + /// + /// Releases resources + /// + /// Whether this method has been called from a dispose context + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + Source.Dispose(); + } + + _disposed = true; + Close(); + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/WorkMemWriter.cs b/tools/workbench/LibWorkBench/IO/Streams/WorkMemWriter.cs new file mode 100644 index 0000000..271718e --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/WorkMemWriter.cs @@ -0,0 +1,31 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Streams +{ + /// + /// Work/scratch memory stream with read+write access + /// + public class WorkMemWriter : WriteStream + { + /// + /// Accesses the work memory buffer + /// + public byte[] Buffer => ((WorkMemDataSource)Source).Buffer; + + /// + /// Constructor + /// + /// Stream character format + /// Stream endianness (byte-order) + public WorkMemWriter(ICharEncoding charEncoding, + EndianUtil.Type endian) + : base(new WorkMemDataSource(), + new BinaryPrimEncoding(), + charEncoding, + endian) + { + } + } +} diff --git a/tools/workbench/LibWorkBench/IO/Streams/WriteStream.cs b/tools/workbench/LibWorkBench/IO/Streams/WriteStream.cs new file mode 100644 index 0000000..065d1b9 --- /dev/null +++ b/tools/workbench/LibWorkBench/IO/Streams/WriteStream.cs @@ -0,0 +1,228 @@ +using LibWorkBench.IO.Encodings; +using LibWorkBench.IO.Sources; +using LibWorkBench.Utility; + +namespace LibWorkBench.IO.Streams +{ + /// + /// Base class for streams with read+write access + /// + public abstract class WriteStream : ReadStream + { + /// + /// Constructor + /// + /// Stream data source + /// Stream primitive format + /// Stream character format + /// Stream endianness (byte-order) + public WriteStream(IDataSource source, IPrimEncoding primEncoding, + ICharEncoding charEncoding, EndianUtil.Type endian) + : base(source, + primEncoding, + charEncoding, + endian) + { + } + + /// + /// Aligns the stream position to the specified byte-alignment + /// + /// Required byte-alignment + public new void Align(ulong alignment) + { + // Number of bytes required to reach alignment + ulong misalign = (alignment - (Position % alignment)) % alignment; + if (misalign == 0) + { + return; + } + + if (EOF) + { + WritePadding(misalign); + } + else + { + Skip((long)misalign); + } + } + + /// + /// Writes a specified block of data to the stream + /// + /// Data contents to write + /// Number of bytes to write (optional) + public void Write(byte[] data, ulong? size = null) + { + Source.Write(data, size); + } + + /// + /// Writes an unsigned 8-bit value to the stream + /// + /// Unsigned 8-bit value + public void WriteU8(byte value) + { + PrimEncoding.WriteU8(Source, Endian, value); + } + + /// + /// Writes an unsigned 16-bit value to the stream + /// Unsigned 16-bit value + /// + public void WriteU16(ushort value) + { + PrimEncoding.WriteU16(Source, Endian, value); + } + + /// + /// Writes an unsigned 32-bit value to the stream + /// + /// Unsigned 32-bit value + public void WriteU32(uint value) + { + PrimEncoding.WriteU32(Source, Endian, value); + } + + /// + /// Writes an unsigned 64-bit value to the stream + /// + /// Unsigned 64-bit value + public void WriteU64(ulong value) + { + PrimEncoding.WriteU64(Source, Endian, value); + } + + /// + /// Writes a signed 8-bit value to the stream + /// + /// Signed 8-bit value + public void WriteS8(sbyte value) + { + PrimEncoding.WriteS8(Source, Endian, value); + } + + /// + /// Writes a signed 16-bit value to the stream + /// + /// Signed 16-bit value + public void WriteS16(short value) + { + PrimEncoding.WriteS16(Source, Endian, value); + } + + /// + /// Writes a signed 32-bit value to the stream + /// + /// Signed 32-bit value + public void WriteS32(int value) + { + PrimEncoding.WriteS32(Source, Endian, value); + } + + /// + /// Writes a signed 64-bit value to the stream + /// + /// Signed 64-bit value + public void WriteS64(long value) + { + PrimEncoding.WriteS64(Source, Endian, value); + } + + /// + /// Writes a single-precision floating point value to the stream + /// + /// Single-precision floating point value + public void WriteF32(float value) + { + PrimEncoding.WriteF32(Source, Endian, value); + } + + /// + /// Writes a double-precision floating point value to the stream + /// + /// Double-precision floating point value + public void WriteF64(double value) + { + PrimEncoding.WriteF64(Source, Endian, value); + } + + /// + /// Writes a UTF-8 string value to the stream + /// + /// String value + /// Maximum string length + /// Whether to null-terminate the string (binary modes only) + /// Whether to write exactly `maxlen` bytes + public void WriteString(string value, int maxlen = int.MaxValue, + bool terminate = true, bool exact = false) + { + CharEncoding.WriteString(Source, Endian, value, maxlen, terminate, + exact); + } + + /// + /// Writes a UTF-16 string value to the stream + /// + /// String value + /// Maximum string length + /// Whether to null-terminate the string (binary modes only) + /// Whether to write exactly `maxlen` bytes + public void WriteWideString(string value, int maxlen = int.MaxValue, + bool terminate = true, bool exact = false) + { + CharEncoding.WriteWideString(Source, Endian, value, maxlen, + terminate, exact); + } + + /// + /// Writes a Shift-JIS string value to the stream + /// + /// String value + /// Maximum string length + /// Whether to null-terminate the string (binary modes only) + /// Whether to write exactly `maxlen` bytes + public void WriteSjisString(string value, int maxlen = int.MaxValue, + bool terminate = true, bool exact = false) + { + CharEncoding.WriteSjisString(Source, Endian, value, maxlen, + terminate, exact); + } + + /// + /// Writes a boolean value to the stream + /// + /// Boolean value + public void WriteBool(bool value) + { + PrimEncoding.WriteU8(Source, Endian, (byte)(value ? 1 : 0)); + } + + /// + /// Writes padding (0x00 bytes) to the stream + /// + /// + public void WritePadding(ulong length) + { + for (ulong i = 0; i < length; i++) + { + WriteU8(0x00); + } + } + + /// + /// Writes debug fill data ("CAFEBABE" pattern) to the stream + /// + /// Number of bytes to fill + public void WriteDebugFill(ulong length) + { + byte[] fill = BitConverter.GetBytes(0xCAFEBABE); + + for (ulong i = 0; i < length; i++) + { + WriteU8(fill[i % (ulong)fill.Length]); + } + } + } +} diff --git a/tools/workbench/LibWorkBench/LibWorkBench.csproj b/tools/workbench/LibWorkBench/LibWorkBench.csproj new file mode 100644 index 0000000..efa9353 --- /dev/null +++ b/tools/workbench/LibWorkBench/LibWorkBench.csproj @@ -0,0 +1,13 @@ + + + + net9.0 + enable + enable + + + + + + + diff --git a/tools/workbench/LibWorkBench/Utility/BitFlag.cs b/tools/workbench/LibWorkBench/Utility/BitFlag.cs new file mode 100644 index 0000000..3097e0a --- /dev/null +++ b/tools/workbench/LibWorkBench/Utility/BitFlag.cs @@ -0,0 +1,126 @@ +using System.Numerics; + +namespace LibWorkBench.Utility +{ + /// + /// Bitflag set + /// + /// Bitfield type + /// Enum type + public sealed class BitFlag + where TValue : unmanaged, IEqualityOperators, IBitwiseOperators + where TEnum : Enum + { + /// + /// Bitfield value + /// + private TValue _value; + + /// + /// Constructor + /// + public BitFlag() + { + MakeAllZero(); + } + + /// + /// Constructor + /// + /// Initial value + public BitFlag(TValue value) + { + SetDirect(value); + } + + /// + /// Clears all bits in the bitfield + /// + public void MakeAllZero() + { + SetDirect(default); + } + + /// + /// Sets the bitfield value directly + /// + /// New value + public void SetDirect(TValue value) + { + _value = value; + } + + /// + /// Gets the bitfield value directly + /// + /// + public TValue GetDirect() + { + return _value; + } + + /// + /// Sets the specified bit + /// + /// Bit index + public void SetBit(TEnum idx) + { + _value |= MakeMask(idx); + } + + /// + /// Clears the specified bit + /// + /// Bit index + public void ResetBit(TEnum idx) + { + _value &= ~MakeMask(idx); + } + + /// + /// Toggles the specified bit + /// + /// Bit index + public void ToggleBit(TEnum idx) + { + _value ^= MakeMask(idx); + } + + /// + /// Changes the value of the specified bit + /// + /// Bit index + /// Bit value + public void ChangeBit(TEnum idx, bool value) + { + if (value) + { + SetBit(idx); + } + else + { + ResetBit(idx); + } + } + + /// + /// Tests whether the specified bit is set + /// + /// Bit index + /// Value of the specified bit + public bool GetBit(TEnum idx) + { + return (_value & MakeMask(idx)) != default; + } + + /// + /// Creates a mask to access the specified bit + /// + /// Bit index + /// Bitmask + private static TValue MakeMask(TEnum idx) + { + return (TValue)(dynamic)(1 << (int)(dynamic)idx); + } + } +} diff --git a/tools/workbench/LibWorkBench/Utility/EndianUtil.cs b/tools/workbench/LibWorkBench/Utility/EndianUtil.cs new file mode 100644 index 0000000..6a36c17 --- /dev/null +++ b/tools/workbench/LibWorkBench/Utility/EndianUtil.cs @@ -0,0 +1,177 @@ +using LibWorkBench.Exceptions; +using System.Buffers.Binary; + +namespace LibWorkBench.Utility +{ + /// + /// Endian conversion utilities + /// + public static class EndianUtil + { + /// + /// Byteorder + /// + public enum Type + { + /// + /// Little endian (least significant bits come first) + /// + Little, + + /// + /// Big endian (most significant bits come first) + /// + Big + }; + + /// + /// Gets the host system's endianness + /// + /// Type enum value + public static Type GetHostEndian() + { + return BitConverter.IsLittleEndian ? Type.Little : Type.Big; + } + + /// + /// Converts the input value to little endian + /// + /// Type of value (must be primitive type) + /// Original value + /// Value represented in little endian + public static T ToLittleEndian(T value) + where T : unmanaged + { + return GetHostEndian() == Type.Little ? value : Swap(value); + } + + /// + /// Converts the input value to big endian + /// + /// Type of value (must be primitive type) + /// Original value + /// Value represented in big endian + public static T ToBigEndian(T value) + where T : unmanaged + { + return GetHostEndian() == Type.Big ? value : Swap(value); + } + + /// + /// Converts the input value to the specified endianness + /// + /// Type of value (must be primitive type) + /// Original value + /// Target endianness + /// Value represented in the specified endianness + public static T ToEndian(T value, Type endian) + where T : unmanaged + { + return endian == Type.Little ? ToLittleEndian(value) : ToBigEndian(value); + } + + /// + /// Encodes the specified primitive value into its byte representation + /// + /// Value type + /// Input value + /// Target endianness (optional) + /// Maximum byte size (optional) + /// Byte representation of the value + public static byte[] ToBytes(T value, Type? toEndian = null, + int? size = null) + where T : unmanaged + { + // Least-significant bits come first in little endian + bool takeFirst = GetHostEndian() + == Type.Little; + + // Optional endianness swap + if (toEndian != null) + { + value = ToEndian(value, (Type)toEndian); + } + + byte[] bytes = BitConverter.GetBytes((dynamic)value); + + // Optional truncation + if (size != null) + { + bytes = takeFirst + ? bytes.Take((int)size).ToArray() + : bytes.TakeLast((int)size).ToArray(); + } + + return bytes; + } + + /// + /// Decodes a primitive value from its byte representation + /// + /// Value type + /// Byte representation of the value + /// Source endianness (optional) + /// Primitive value + /// Unknown type was provided + public static T FromBytes(byte[] bytes, Type? fromEndian = null) + where T : unmanaged + { + // Optional endianness swap + if (fromEndian != null && fromEndian != GetHostEndian()) + { + bytes = bytes.Reverse().ToArray(); + } + + switch (typeof(T).FullName) + { + case "System.Int8": + case "System.UInt8": + return (T)(dynamic)bytes[0]; + + case "System.Int16": + return (T)(dynamic)BitConverter.ToInt16(bytes); + case "System.UInt16": + return (T)(dynamic)BitConverter.ToUInt16(bytes); + + case "System.Int32": + return (T)(dynamic)BitConverter.ToInt32(bytes); + case "System.UInt32": + return (T)(dynamic)BitConverter.ToUInt32(bytes); + + case "System.Int64": + return (T)(dynamic)BitConverter.ToInt64(bytes); + case "System.UInt64": + return (T)(dynamic)BitConverter.ToUInt64(bytes); + + case "System.Single": + return (T)(dynamic)BitConverter.ToSingle(bytes); + case "System.Double": + return (T)(dynamic)BitConverter.ToDouble(bytes); + + default: + throw new OperationException( + $"Unsupported type: {typeof(T).FullName}"); + } + } + + /// + /// Performs a byteswap on the specified value + /// + /// Value type + /// Input value + /// Input value represented in the opposite endianness + private static T Swap(T value) + where T : unmanaged + { + // BinaryPrimitives does not support decimal types yet + if (typeof(T) == typeof(float) + || typeof(T) == typeof(double)) + { + return FromBytes(ToBytes(value).Reverse().ToArray()); + } + + // Use the more optimized BinaryPrimitives when possible + return BinaryPrimitives.ReverseEndianness((dynamic)value); + } + } +} diff --git a/tools/workbench/LibWorkBench/Utility/Util.cs b/tools/workbench/LibWorkBench/Utility/Util.cs new file mode 100644 index 0000000..d0bc8ed --- /dev/null +++ b/tools/workbench/LibWorkBench/Utility/Util.cs @@ -0,0 +1,148 @@ +using LibWorkBench.Core; +using System.Text; + +namespace LibWorkBench.Utility +{ + /// + /// Miscellaneous utility functions + /// + public static class Util + { + /// + /// Rounds a value up to the nearest instance of the specified alignment + /// + /// Input value type + /// Input value + /// Alignment + /// Aligned value (rounded up) + public static T RoundUp(T x, ulong alignment) + where T : unmanaged + { + T result = (T)(alignment + (dynamic)x - 1 & ~(alignment - 1)); + return result; + } + + /// + /// Rounds a value down to the nearest instance of the specified alignment + /// + /// Input value type + /// Input value + /// Alignment + /// Aligned value (rounded down) + public static T RoundDown(T x, ulong alignment) + where T : unmanaged + { + T result = (T)((dynamic)x & ~(alignment - 1)); + return result; + } + + /// + /// Counts the number of values in the specified enum + /// + /// Enum type + /// Number of enum values + public static int EnumCount() + { + return Enum.GetValues(typeof(T)).Length; + } + + /// + /// Prints the specified object hierarchy to the console for debugging purposes + /// + /// Root object + /// Text indent level + public static void DumpHierarchy(T root, uint indent = 0) + where T : IUseName, IUseHierarchy + { + for (uint i = 0; i < indent; i++) + { + Console.Write("-"); + } + + Console.WriteLine(root.Name); + + foreach (var it in root.Children) + { + DumpHierarchy(it, ++indent); + } + } + + /// + /// Encodes a byte array into its hexadecimal string representation + /// + /// Input data + /// Whether to delimit bytes by whitespace + /// Whether to include the "0x" prefix + /// String representation of bytes + public static string ToHex(byte[] bytes, bool delimit = true, + bool prefix = false) + { + StringBuilder builder = new(); + + for (int i = 0; i < bytes.Length; i++) + { + string next = $"{bytes[i]:X2}"; + builder.Append(delimit && prefix ? $"0x{next}" : next); + + if (delimit && i != bytes.Length - 1) + { + builder.Append(' '); + } + } + + string hex = builder.ToString(); + return !delimit && prefix ? $"0x{hex}" : hex; + } + + /// + /// Decodes a hexadecimal string into its original bytes + /// + /// Input string + /// Bytes contained within the string + public static byte[] FromHex(string str) + { + // Remove optional prefix + str = str.Replace("0x", ""); + + // Remove optional delimiters + str = str.Replace(" ", ""); + + return Convert.FromHexString(str); + } + + /// + /// Encodes a primitive value into its hexadecimal string representation + /// + /// Value type + /// Input value + /// Target endianness (optional) + /// Maximum byte size (optional) + /// Whether to delimit bytes by whitespace + /// Whether to include the "0x" prefix + /// String representation of value bytes + public static string ToHex(T value, + EndianUtil.Type toEndian = EndianUtil.Type.Big, + int? size = null, bool delimit = true, + bool prefix = false) + where T : unmanaged + { + byte[] bytes = EndianUtil.ToBytes(value, toEndian, size); + return ToHex(bytes, delimit, prefix); + } + + /// + /// Decodes a hexadecimal string into its original value + /// + /// Value type + /// Input string + /// Source endianness (optional) + /// Value contained within the string + public static T FromHex(string str, + EndianUtil.Type fromEndian = EndianUtil.Type.Big) + where T : unmanaged + { + byte[] bytes = FromHex(str); + return EndianUtil.FromBytes(bytes, fromEndian); + } + } +} diff --git a/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/Sports2.json b/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/Sports2.json new file mode 100644 index 0000000..138270e --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/Sports2.json @@ -0,0 +1,23794 @@ +{ + "encoding": "UTF16", + "group_id": 0, + "form": "MAIN", + "form_supplement": "GROUP24", + "messages": [ + { + "group": 1000, + "index": 0, + "text": "Saburo", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 1, + "text": "Hiroshi", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 2, + "text": "Daisuke", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 3, + "text": "Shinnosuke", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 4, + "text": "Akira", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 5, + "text": "Tatsuaki", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 6, + "text": "Shouta", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 7, + "text": "Ren", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 8, + "text": "Kentaro", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 9, + "text": "Takumi", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 10, + "text": "Haru", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 11, + "text": "Yoshi", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 12, + "text": "Fumiko", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 13, + "text": "Keiko", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 14, + "text": "Yoko", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 15, + "text": "Miyu", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 16, + "text": "Ai", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 17, + "text": "Misaki", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 18, + "text": "Rin", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 19, + "text": "Sakura", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 20, + "text": "Andy", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 21, + "text": "Chris", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 22, + "text": "Ryan", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 23, + "text": "Jake", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 24, + "text": "Matt", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 25, + "text": "Mike", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 26, + "text": "Nick", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 27, + "text": "Oscar", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 28, + "text": "Theo", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 29, + "text": "Tyrone", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 30, + "text": "Abby", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 31, + "text": "Ashley", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 32, + "text": "Emily", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 33, + "text": "Hayley", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 34, + "text": "Jackie", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 35, + "text": "Jessie", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 36, + "text": "Maria", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 37, + "text": "Naomi", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 38, + "text": "Rachel", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 39, + "text": "Steph", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 40, + "text": "James", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 41, + "text": "Steve", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 42, + "text": "Michael", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 43, + "text": "Martin", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 44, + "text": "Pierre", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 45, + "text": "Alex", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 46, + "text": "Luca", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 47, + "text": "Marco", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 48, + "text": "David", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 49, + "text": "V\u00EDctor", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 50, + "text": "Sarah", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 51, + "text": "Helen", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 52, + "text": "Kathrin", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 53, + "text": "Silke", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 54, + "text": "Emma", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 55, + "text": "Julie", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 56, + "text": "Anna", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 57, + "text": "Elisa", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 58, + "text": "Eva", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 59, + "text": "Luc\u00EDa", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 60, + "text": "Shohei", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 61, + "text": "Sota", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 62, + "text": "Takashi", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 63, + "text": "Shinta", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 64, + "text": "Hiromasa", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 65, + "text": "Chika", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 66, + "text": "Tomoko", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 67, + "text": "Hiromi", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 68, + "text": "Midori", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 69, + "text": "Asami", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 70, + "text": "Miguel", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 71, + "text": "Abe", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 72, + "text": "Cole", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 73, + "text": "Greg", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 74, + "text": "George", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 75, + "text": "Mia", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 76, + "text": "Megan", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 77, + "text": "Holly", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 78, + "text": "Sandra", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 79, + "text": "Alisha", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 80, + "text": "Tommy", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 81, + "text": "Ian", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 82, + "text": "Fritz", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 83, + "text": "Rainer", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 84, + "text": "Eddy", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 85, + "text": "Patrick", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 86, + "text": "Vincenzo", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 87, + "text": "Gabriele", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 88, + "text": "Eduardo", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 89, + "text": "Pablo", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 90, + "text": "Gwen", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 91, + "text": "Siobh\u00E1n", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 92, + "text": "Ursula", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 93, + "text": "Gabi", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 94, + "text": "St\u00E9phanie", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 95, + "text": "Nelly", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 96, + "text": "Barbara", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 97, + "text": "Giovanna", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 98, + "text": "Susana", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1000, + "index": 99, + "text": "Marisa", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1010, + "index": 0, + "text": "Guest A", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1011, + "index": 0, + "text": "Guest B", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1012, + "index": 0, + "text": "Guest C", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1013, + "index": 0, + "text": "Guest D", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1014, + "index": 0, + "text": "Guest E", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 1015, + "index": 0, + "text": "Guest F", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 10100, + "index": 0, + "text": "{ T0A_0000 00 00 }{ T0A_0001 00 00 }{ T0A_0002 00 00 }{ T0A_0004 02 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10100, + "index": 1, + "text": "The Wii system memory has\nbeen damaged. Refer to the\nWii Operations Manual for\ndetails.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10101, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10101, + "index": 1, + "text": "Could not access Wii system\nmemory. Refer to the\nWii Operations Manual for\ndetails.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10101, + "index": 2, + "text": "Wii Menu", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10102, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10102, + "index": 1, + "text": "Could not access the saved\ndata on the Mii Channel.\nPlease go to the Mii Channel\nto check your data.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10102, + "index": 2, + "text": "Wii Menu", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10103, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10103, + "index": 1, + "text": "The Wii Sports Resort\nsave data is corrupted\nand cannot be used.\n\nThe data will now be\ndeleted.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10103, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10104, + "index": 0, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 10104, + "index": 1, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 10104, + "index": 2, + "text": "", + "attributes": "0x00000032", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 10104, + "index": 3, + "text": "", + "attributes": "0x00000032", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 10105, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10105, + "index": 1, + "text": "There is not enough available \nspace in Wii system memory \nto create save data. Create { VAR_0 } \nblocks of free space by either\nmoving data to an SD Card or \ndeleting data on the Wii console\u0027s\nData Management screen.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10105, + "index": 2, + "text": "Go to the Data Management screen", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10106, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10106, + "index": 1, + "text": "There is not enough available \nspace in Wii system memory\nto create save data. Either \nmove data to an SD Card or \ndelete data on the Wii console\u0027s \nData Management screen.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10106, + "index": 2, + "text": "Go to the Data Management screen", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10107, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10107, + "index": 1, + "text": "New save data has\nbeen created for\nWii Sports Resort.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10108, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10108, + "index": 1, + "text": "The Wii Sports Resort\nsave data was deleted.\n\nNew save data will\nnow be created.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10108, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10109, + "index": 0, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 10109, + "index": 1, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 10109, + "index": 2, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 10109, + "index": 3, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 10110, + "index": 0, + "text": "{ T0A_0000 00 00 }{ T0A_0001 00 00 }{ T0A_0002 00 00 }{ T0A_0004 02 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10110, + "index": 1, + "text": "An error occurred while\naccessing Wii system memory.\nRefer to the Wii Operations\nManual for details.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10300, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 01 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10300, + "index": 1, + "text": "The battery charge is\nrunning low. Please check the\nbattery level on the \uE044 HOME\nMenu.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10500, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10500, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10510, + "index": 0, + "text": "{ T0A_0000 00 00 }{ T0A_0001 00 00 }{ T0A_0002 00 00 }{ T0A_0004 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10510, + "index": 1, + "text": "Communications with\n{ VAR_1 }\u0027s Wii Remote\nhave been interrupted.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10511, + "index": 0, + "text": "{ T0A_0000 00 00 }{ T0A_0001 00 00 }{ T0A_0002 00 00 }{ T0A_0004 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10511, + "index": 1, + "text": "{ VAR_1 }\u0027s Nunchuk controller is\ndisconnected. Please\nreconnect it.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10511, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10512, + "index": 0, + "text": "{ T0A_0000 00 00 }{ T0A_0001 00 00 }{ T0A_0002 00 00 }{ T0A_0004 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10512, + "index": 1, + "text": "{ VAR_1 }\u0027s Wii MotionPlus\naccessory is disconnected.\nPlease reconnect it.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10600, + "index": 0, + "text": "{ T0A_0000 00 00 }{ T0A_0001 00 00 }{ T0A_0002 00 00 }{ T0A_0004 02 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10600, + "index": 1, + "text": "The Wii system memory has\nbeen damaged. Refer to the\nWii Operations Manual for\ndetails.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10601, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10601, + "index": 1, + "text": "There is a problem with\nthe Wii system memory, so\nWiiConnect24 cannot\nbe used. \n\nError code\uFF1A { VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10601, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10602, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10602, + "index": 1, + "text": "To use WiiConnect24,\na system update is required.\nRefer to the Wii Operations\nManual for details.\n\nError code\uFF1A { VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10602, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10603, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10603, + "index": 1, + "text": "WiiConnect24 cannot be\nused because an error\nhas occurred.\nReset and try again.\nError Code\uFF1A { VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10603, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10604, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10604, + "index": 1, + "text": "The WiiConnect24 setting is\nnot turned on. Please check\nthe settings under Wii Options.\nRefer to the Wii Operations\nManual for details.\n\nError code\uFF1A { VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10604, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10605, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10605, + "index": 1, + "text": "An Internet connection\ncould not be established,\nso WiiConnect24 cannot be\nused. Check the Internet\nsettings and connection.\nRefer to the Wii Operations\nManual for details.\nError code\uFF1A { VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10605, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10606, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10606, + "index": 1, + "text": "WiiConnect24 is temporarily\nunavailable.\n\nPlease try again later.\n\nError code\uFF1A { VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10606, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10607, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10607, + "index": 1, + "text": "WiiConnect24 is temporarily\nunavailable. Please try again\nlater.\n\nError code\uFF1A { VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10607, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10608, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10608, + "index": 1, + "text": "WiiConnect24 is temporarily\nunavailable. Please try again\nlater.\n\nError code\uFF1A { VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10608, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10609, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10609, + "index": 1, + "text": "Could not obtain the latest\ninformation.\n\nPlease try again later.\n\nError code\uFF1A { VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10609, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10610, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10610, + "index": 1, + "text": "There is not enough available \nspace in Wii system memory to \nsave Check Mii Out Channel import \ndata. Create { VAR_0 } block of free \nspace by either moving data to\nan SD Card or deleting data on\nthe Wii console\u0027s Data\nManagement screen.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10610, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10611, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 02 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10611, + "index": 1, + "text": "There is not enough available \nspace in Wii system memory \nto save Check Mii Out Channel\nimport data. Either move data\nto an SD Card or delete data on\nthe Wii console\u0027s Data\nManagement screen.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10611, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10700, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10700, + "index": 1, + "text": "\u25A0Check Mii Out Channel\u25A0\nWii Sports Resort can\nautomatically import popular\nuser-created Mii characters\nfrom the Check Mii Out Channel.{ T05_0000 }\nImported Mii characters are\nrandomly selected and will appear\nin the game as opponents and\nspectators.{ T05_0000 }\nPlease note that some\nuser-created Mii characters\nmay not be appropriate for\nviewing by all users.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10700, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10701, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 01 00 }{ T0A_0005 00 00 }{ T0A_0006 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10701, + "index": 1, + "text": "You can stop importing\nMii characters from the\nCheck Mii Out Channel at any\ntime. To do so, select the \nCheck Mii Out Channel from\nthe settings menu, then\nselect Don\u0027t Import.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10701, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10702, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10702, + "index": 1, + "text": "Would you like to import\nMii characters from the\nCheck Mii Out Channel?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10702, + "index": 2, + "text": "Don\u0027t Import", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10702, + "index": 3, + "text": "Import", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10703, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10703, + "index": 1, + "text": "Check Mii Out Channel import\nsettings can be changed\nin the settings screen,\naccessible from the\nmain menu.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10703, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10704, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10704, + "index": 1, + "text": "An error occurred while\nimporting Mii characters.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10705, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10705, + "index": 1, + "text": "An error occurred while\ncanceling the Check Mii Out\nChannel import service.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10706, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10706, + "index": 1, + "text": "An error occurred while\nimporting Mii characters.\n\nWould you like to try again?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10706, + "index": 2, + "text": "Cancel", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10706, + "index": 3, + "text": "Try Again", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10707, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10707, + "index": 1, + "text": "An error occurred while\ncanceling the Check Mii\nOut Channel import service.\n\nWould you like to try again?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10707, + "index": 2, + "text": "Cancel", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10707, + "index": 3, + "text": "Try Again", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10708, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10708, + "index": 1, + "text": "The Check Mii Out Channel\nimport service is no\nlonger available.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10708, + "index": 2, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xC7 0x00 0xFE" + }, + { + "group": 10800, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10800, + "index": 1, + "text": "Watch the Wii MotionPlus\ninstructional video?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10800, + "index": 2, + "text": "Back", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10800, + "index": 3, + "text": "Watch", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10900, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10900, + "index": 1, + "text": "The Wii MotionPlus accessory\nhas not finished calibrating\nand may not function correctly.\nDo you want to cancel\ncalibration?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10900, + "index": 2, + "text": "Try Again", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10900, + "index": 3, + "text": "Cancel", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10901, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10901, + "index": 1, + "text": "The Wii MotionPlus accessory\nhas not finished calibrating.\n\nAre you sure you want to\ncancel calibration?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 10901, + "index": 2, + "text": "Try Again", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 10901, + "index": 3, + "text": "Cancel", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 11000, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11000, + "index": 1, + "text": "This mode requires\n{ VAR_0 } Wii Remotes.\n\nYou can add more Wii Remotes\nfrom the \uE044 HOME Menu.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11001, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11001, + "index": 1, + "text": "{ VAR_0 } Wii Remote will be\nshared by { VAR_0 } players.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11002, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11002, + "index": 1, + "text": "{ VAR_0 } Wii Remotes will be\nshared by { VAR_0 } players.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11010, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11010, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11020, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11020, + "index": 1, + "text": "This sport requires\nmore than one player.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11200, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11200, + "index": 1, + "text": "Unable to find Mii characters.\nPlease go to the Mii Channel\nto create a new Mii.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11200, + "index": 2, + "text": "Back", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 11200, + "index": 3, + "text": "Wii Menu", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 11201, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11201, + "index": 1, + "text": "If you select this Mii, your data\nwill not be saved.\n\nWould you like to continue?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11201, + "index": 2, + "text": "Back", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 11201, + "index": 3, + "text": "Continue", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 11202, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11202, + "index": 1, + "text": "This Mii has been deleted\nfrom the Mii Channel.\nPlease select a different Mii.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11203, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11203, + "index": 1, + "text": "Unable to find any other\nMii characters. Please go to\nthe Mii Channel to create\na new Mii.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11203, + "index": 2, + "text": "Back", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 11203, + "index": 3, + "text": "Wii Menu", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 11204, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11204, + "index": 1, + "text": "Changed registered Mii\nto { VAR_1 }.\n\nAll records will be transferred\nto the new Mii.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11205, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11205, + "index": 1, + "text": "The player list is full. \nYou can make a spot for a new\nMii by removing an unused one.\n\nPlease select a Mii to remove.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11206, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11206, + "index": 1, + "text": "Unused players have\nbeen erased from the\nplayer list.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11207, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11207, + "index": 1, + "text": "{ VAR_1 } has been added\nto the player list.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11208, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11208, + "index": 1, + "text": "If you erase this Mii from the\nMii Channel or move it to the\nMii Parade, it will be deleted\nfrom your player list, but you\ncan transfer its play records\nto a new Mii by selecting\nChange Player List under\nthe Settings menu.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11209, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11209, + "index": 1, + "text": "There are no Mii characters on\nthis Wii console.\n\nSelect the Mii Channel from the\nWii Menu to create a Mii.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11210, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11210, + "index": 1, + "text": "Your records will be transferred\nto another Mii.\n\nYou can even transfer records\nto a Mii that hasn\u0027t been\nregistered in the player list.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11250, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11250, + "index": 1, + "text": "\u25A0 Manual Style\nRelease \uE043 to let go of the ball\nas you swing. Recommended if\nyou\u0027ve played { COMMON_FONT_COLOR 01 00 }Wii Sports{ COMMON_FONT_COLOR 00 00 }.\n\n\u25A0 Automatic Style\nAs you swing, the ball\nis released automatically.\nRecommended for { COMMON_FONT_COLOR 01 00 }new players{ COMMON_FONT_COLOR 00 00 }.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11250, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11251, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 03 00 }{ T0A_0004 00 00 }{ T0A_0005 02 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11251, + "index": 1, + "text": "Select a throwing style.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11251, + "index": 2, + "text": "Manual", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 11251, + "index": 3, + "text": "Automatic", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 11252, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11252, + "index": 1, + "text": "\u25A0 Manual Style\nRelease \uE043 as you throw to let\ngo of the Frisbee. Recommended\nfor { COMMON_FONT_COLOR 01 00 }experienced players{ COMMON_FONT_COLOR 00 00 }.\n\n\u25A0 Automatic Style\nAs you throw, the Frisbee is\nreleased automatically.\nRecommended for { COMMON_FONT_COLOR 01 00 }beginners{ COMMON_FONT_COLOR 00 00 }.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11300, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 11300, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 11301, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 11301, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 11301, + "index": 2, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xDC 0x01 0x00" + }, + { + "group": 11301, + "index": 3, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xDC 0x01 0x00" + }, + { + "group": 11305, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11305, + "index": 1, + "text": "The player list is empty.\n\nTo add a Mii to the player list,\nchoose a sport and start playing.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11310, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11310, + "index": 1, + "text": "This feature uses the Sensor\nBar to improve the accuracy\nof the Wii Remote.\n\nPlease note that this may not\nhave any effect depending on\nyour playing environment.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11311, + "index": 0, + "text": "{ T0A_0000 03 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11311, + "index": 1, + "text": "Do you want to enable\nthe Sensor Bar Assist\nfeature to improve the\naccuracy of the Wii Remote?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 11311, + "index": 2, + "text": "Disable", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 11311, + "index": 3, + "text": "Enable", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 24000, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 24000, + "index": 1, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25000, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25000, + "index": 1, + "text": "After completing a stage,\nselect Next Stage to go\non to the next one.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25001, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25001, + "index": 1, + "text": "You cleared the last stage and\nunlocked a bonus stage!\nSelect Next Stage to go to\nthe bonus stage.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25002, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25002, + "index": 1, + "text": "You beat the last stage!\nWe\u0027d love to give you another\nbonus stage, but you\u0027re obviously\ntoo good. Now use your skills to\nduel your friends!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25200, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25200, + "index": 1, + "text": "\uFF5EBalloon Challenge\uFF5E\n\nPop the balloon with your\nFrisbee and still land it\non target to earn extra points!\nConcentrate on angling the\ndisc to curve your throw.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25201, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25201, + "index": 1, + "text": "\uFF5EBalloon Challenge\uFF5E\n\nPop the balloon and have the dog\ncatch the Frisbee to steal 50\npoints from the opposing team!\n\nConcentrate on angling the disc\nso that it curves the right way.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25203, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25203, + "index": 1, + "text": "Step 2: Balloon Practice\n\nThe next step is to learn how to\naim for a target and angle the\ndisc in different ways to make it\nfly in a curve. See how many\nballoons you can pop in one\nthrow! Press \uE046 to quit\npracticing at any time.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25204, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25204, + "index": 1, + "text": "Step 1: Throwing the Frisbee\n\nThe first step is to learn how to\nthrow the Frisbee. Make sure\nthere are no people or objects\naround that you might bump into.\nPress \uE046 at any time to go on to\nthe next step and practice\npopping balloons.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25205, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25205, + "index": 1, + "text": "\uFF5EQuick Tip\uFF5E\n\nWas your dog able to catch your\nthrows?\n\nIf you think you need to\nwork on your Frisbee skills,\npress \uE046 before the competition\nstarts to practice.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25206, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25206, + "index": 1, + "text": "The Frisbee Dog Tournament is\nstarting!\n\nConcentrate on your timing and\nthe angle of your throw.\n{ COMMON_FONT_COLOR 01 00 }Don\u0027t swing too hard{ COMMON_FONT_COLOR 00 00 }!{ COMMON_FONT_COLOR 02 00 }\n\nJust remember what you\u0027ve\nlearned and have fun!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25300, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25300, + "index": 1, + "text": "\uFF5EGolden Arrow\uFF5E\n\nThe third shot is a Golden\nArrow! Hit the target with this\narrow to double your points!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25500, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25500, + "index": 1, + "text": "\uFF5ENote\uFF5E\n\nIn Speed Challenge, the length\nof the course in each race\nchanges depending on how well\nthe competitors did in the\nprevious race.{ T05_0000 }\nSee how far you can get! { T05_0000 }\nThe goal for the next race\nis { VAR_0 } { VAR_2 }\n\nGood luck!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25501, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25501, + "index": 1, + "text": "The goal for the next race is\n{ VAR_0 } { VAR_2 }\n\nGood luck!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25502, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }{ T0A_0007 00 0F }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25502, + "index": 1, + "text": "\uFF5EAnnouncement\uFF5E\n\nNow that you have your\nBeginner License, the races will\nbe a challenge to see how far you\ncan paddle within the time limit.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25503, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }{ T0A_0007 00 0F }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25503, + "index": 1, + "text": "\uFF5EAnnouncement\uFF5E\n\nNow that you have your\nIntermediate License, races will\nnow be a test to see how far you\ncan get in a limited amount of\ntime.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25504, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }{ T0A_0007 00 0F }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25504, + "index": 1, + "text": "\uFF5EAnnouncement\uFF5E\n\nNow that you have your Expert\nLicense, races will now be a\ntest to see how far you can\nget in a limited amount of time.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25510, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }{ T0A_0007 00 0F }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25510, + "index": 1, + "text": "\uFF5EAnnouncement\uFF5E\n\nRaces will now be a challenge\nto see how far you can paddle\nwithin the time limit.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25800, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }{ T0A_0007 00 78 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25800, + "index": 1, + "text": "\uFF5EQuick Tip\uFF5E\n\nWhen you\u0027re shooting from the\nrough or the bunker, just a small\ntwist of your wrist can cause\nyour shot to curve wildly, so try\nto stay on the fairway if you can.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25801, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }{ T0A_0007 00 78 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25801, + "index": 1, + "text": "\uFF5EQuick Tip\uFF5E\n\nUsing an iron or wedge, { COMMON_FONT_COLOR 01 00 }swing{ COMMON_FONT_COLOR 00 00 }\n{ COMMON_FONT_COLOR 01 00 }with extra wrist snap{ COMMON_FONT_COLOR 02 00 } to\nput backspin on the ball.\nIt can help stop the ball\nfrom rolling off the green.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25802, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }{ T0A_0007 00 78 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25802, + "index": 1, + "text": "\uFF5EQuick Tip\uFF5E\n\nTake some practice swings!\nSwing the Wii Remote without\nholding \uE042 to take a practice\nswing and adjust the strength\nand angle of your stroke.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25803, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }{ T0A_0007 00 78 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25803, + "index": 1, + "text": "\uFF5EQuick Tip\uFF5E\n\nAdjust your stance! { COMMON_FONT_COLOR 02 00 }To get into\nthe basic golf stance, { COMMON_FONT_COLOR 01 00 }face{ COMMON_FONT_COLOR 00 00 }\n{ COMMON_FONT_COLOR 01 00 }downward and press \uE043{ COMMON_FONT_COLOR 02 00 }.\nTry adjusting your position\nbetween each shot to\nimprove your accuracy.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25900, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25900, + "index": 1, + "text": "\uFF5EPractice\uFF5E\n\nLet\u0027s get some practice with\nthe three types of Frisbee.\nEach type flies a different\ndistance. First, make sure there\nare no people or objects around\nyou. Press \uE046 to quit practicing\nat any time.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25901, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 25901, + "index": 1, + "text": "The Frisbee Golf Championships\nare starting.\n\nDon\u0027t forget to use all the\nFrisbee sizes and try different\nangles. { COMMON_FONT_COLOR 01 00 }Don\u0027t throw too hard{ COMMON_FONT_COLOR 02 00 }!\n\nJust remember what you learned\nin practice. Good luck!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26100, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26100, + "index": 1, + "text": "\u25A0White Balloons\u25A0\n\n{ VAR_0 } Left\n\nDaytime: { VAR_0 }\nEvening: { VAR_0 }\nNight: { VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26101, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26101, + "index": 1, + "text": "\uFF5EQuick Tip\uFF5E\n\nYou can control some features\nof your plane with the Nunchuk.\n\n\uE04B Balloon blaster\n\uE04A Cut the engine\n\u3327 Look around", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26200, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26200, + "index": 1, + "text": "\uFF5EQuick Tip\uFF5E\n\nTry to pedal in time with each\nother. When your timing is in\nunison, your Mii\u0027s feet will glow,\nand you will spend less energy.\nThis is also true when sprinting;\nwork together to be more\neffective.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26300, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26300, + "index": 1, + "text": "Let\u0027s take a look at the photos\ntaken during your jump.\n\nYour score depends on how\nmany Mii characters are in\nthe picture.\n\nDid you catch any big grins?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26301, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26301, + "index": 1, + "text": "\uFF5EQuick Tip\uFF5E\n\nYou get bonus points if your\nface is clearly visible, so be\nsure to turn and face the\ncamera when it\u0027s about to snap!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26302, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26302, + "index": 1, + "text": "\uFF5EQuick Tip\uFF5E\n\nIf you link up with all of\nthe skydivers in a group and\nget a Perfect Catch, you\u0027ll\nget an additional picture!\nRemember to turn and look at\nthe photographer free-falling\nwith you!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26303, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }{ T0A_0001 01 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 26303, + "index": 1, + "text": "\uFF5EQuick Tip\uFF5E\n\nDid you have fun on your dive?\n\nIf you had trouble controlling\nyour Mii in free fall, press \uE046\nwhile you\u0027re still in the plane to\ntake a practice dive.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 30000, + "index": 0, + "text": "Wii Sports Resort News\n{ VAR_0 }\n\n{ VAR_0 }\n\nCongratulations!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30010, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 30011, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFF" + }, + { + "group": 30100, + "index": 10, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x00 0x01" + }, + { + "group": 30100, + "index": 11, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x00 0x01" + }, + { + "group": 30100, + "index": 20, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30100, + "index": 21, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30101, + "index": 10, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 30101, + "index": 11, + "text": "{ VAR_1 } played { VAR_0 }!", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 30102, + "index": 10, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 30102, + "index": 11, + "text": "{ VAR_1 } and { VAR_1 } played { VAR_0 } together!", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 30103, + "index": 10, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 30103, + "index": 11, + "text": "{ VAR_1 }, { VAR_1 }, and { VAR_1 } played { VAR_0 } together!", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 30104, + "index": 10, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 30104, + "index": 11, + "text": "{ VAR_1 }, { VAR_1 }, { VAR_1 }, and { VAR_1 } played { VAR_0 } together!", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 30110, + "index": 0, + "text": "Announcement", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 30110, + "index": 1, + "text": "{ VAR_0 }\n{ VAR_0 } mode\nhas been unlocked.", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 30111, + "index": 0, + "text": "Announcement", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 30111, + "index": 1, + "text": "{ VAR_0 }\n{ VAR_0 } has been unlocked.", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 30200, + "index": 0, + "text": "New high score!", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 30200, + "index": 1, + "text": "{ VAR_0 }\n{ VAR_1 }\n{ VAR_0 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 30200, + "index": 10, + "text": "New high score!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 30200, + "index": 11, + "text": "{ VAR_0 }\u3000{ VAR_1 }\u3000{ VAR_0 }\u3000\u21D2\u3000{ VAR_0 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 30200, + "index": 20, + "text": "New high score!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30200, + "index": 21, + "text": "{ VAR_0 }\n{ VAR_1 }\n{ VAR_0 }\u3000\u21D2\u3000{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30201, + "index": 10, + "text": "New record!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 30201, + "index": 11, + "text": "{ VAR_0 }\u3000{ VAR_1 }\u3000{ VAR_0 }\u3000\u21D2\u3000{ VAR_0 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 30201, + "index": 20, + "text": "New record!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30201, + "index": 21, + "text": "{ VAR_0 }\n{ VAR_1 }\n{ VAR_0 }\u3000\u21D2\u3000{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30304, + "index": 0, + "text": "Advanced to Pro class!\nCongratulations!", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 30304, + "index": 1, + "text": "{ VAR_0 } Pro\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 30304, + "index": 10, + "text": "Advanced to Pro class!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 30304, + "index": 11, + "text": "{ VAR_0 } Pro\n{ VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 30304, + "index": 20, + "text": "Advanced to Pro class!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30304, + "index": 21, + "text": "{ VAR_0 }\n{ VAR_1 }\nAdvanced to Pro class!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30306, + "index": 0, + "text": "Advanced to Superstar class!\nCongratulations!", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 30306, + "index": 1, + "text": "{ VAR_0 } Superstar\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 30306, + "index": 10, + "text": "Amazing accomplishment! Advanced to Superstar class!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 30306, + "index": 11, + "text": "{ VAR_0 } Superstar { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 30306, + "index": 20, + "text": "Amazing accomplishment!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30306, + "index": 21, + "text": "{ VAR_0 }\n{ VAR_1 }\nAdvanced to Superstar class!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30500, + "index": 0, + "text": "Pro in every sport!\nCongratulations!", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 30500, + "index": 1, + "text": "{ VAR_1 }\nhas become a Pro in\nevery sport!", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 30500, + "index": 10, + "text": "Pro in every sport!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 30500, + "index": 11, + "text": "{ VAR_1 } has become a Pro in every sport!", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 30500, + "index": 20, + "text": "Pro in every sport!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30500, + "index": 21, + "text": "{ VAR_1 } has become\na Pro in every sport!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30501, + "index": 0, + "text": "Superstar in every sport!\nCongratulations!", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 30501, + "index": 1, + "text": "{ VAR_1 }\nhas become a Superstar\nin every sport!", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 30501, + "index": 10, + "text": "Superstar in every sport!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 30501, + "index": 11, + "text": "{ VAR_1 } has become a Superstar in every sport!", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 30501, + "index": 20, + "text": "Superstar in every sport!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 30501, + "index": 21, + "text": "{ VAR_1 } has become\na Superstar in every sport!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35000, + "index": 0, + "text": "Stamp earned!\nSure Shot", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35000, + "index": 1, + "text": "Archery\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35000, + "index": 10, + "text": "Sure Shot", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35000, + "index": 11, + "text": "Archery: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35000, + "index": 20, + "text": "Sure Shot", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35000, + "index": 21, + "text": "Archery\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35000, + "index": 30, + "text": "Sure Shot", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35000, + "index": 40, + "text": "Sure Shot\n\nHit the target with all 3\narrows in each of the 4 stages.\nIt\u0027s possible to do this on any\ndifficulty level.\n\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35001, + "index": 0, + "text": "Stamp earned!\nBull Stampede", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35001, + "index": 1, + "text": "Archery\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35001, + "index": 10, + "text": "Bull Stampede", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35001, + "index": 11, + "text": "Archery: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35001, + "index": 20, + "text": "Bull Stampede", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35001, + "index": 21, + "text": "Archery\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35001, + "index": 30, + "text": "Bull Stampede", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35001, + "index": 40, + "text": "Bull Stampede\n\nHit the center of the target and\nget 10 points with all three\narrows in one stage. This can be\nin any difficulty level, but not in\nteam play. The easiest way to\npull this off is in Stage 1 of\nthe Beginner level.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35002, + "index": 0, + "text": "Stamp earned!\nA Secret to Everybody", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35002, + "index": 1, + "text": "Archery\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35002, + "index": 10, + "text": "A Secret to Everybody", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35002, + "index": 11, + "text": "Archery: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35002, + "index": 20, + "text": "A Secret to Everybody", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35002, + "index": 21, + "text": "Archery\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35002, + "index": 30, + "text": "A Secret to Everybody", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35002, + "index": 40, + "text": "A Secret to Everybody\n\nThere is a secret target in every\nstage of every difficulty level.\nHit all the secret targets in every\nlevel to get this stamp.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35003, + "index": 0, + "text": "Stamp earned!\nCentury Shot", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35003, + "index": 1, + "text": "Archery\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35003, + "index": 10, + "text": "Century Shot", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35003, + "index": 11, + "text": "Archery: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35003, + "index": 20, + "text": "Century Shot", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35003, + "index": 21, + "text": "Archery\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35003, + "index": 30, + "text": "Century Shot", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35003, + "index": 40, + "text": "Century Shot\n\nShoot 100 arrows into the\ntarget. It doesn\u0027t matter what\nscore you earn with each shot,\nas long as you hit the target.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35004, + "index": 0, + "text": "Stamp earned!\nSharpshooter", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35004, + "index": 1, + "text": "Archery\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35004, + "index": 10, + "text": "Sharpshooter", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35004, + "index": 11, + "text": "Archery: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35004, + "index": 20, + "text": "Sharpshooter", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35004, + "index": 21, + "text": "Archery\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35004, + "index": 30, + "text": "Sharpshooter", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35004, + "index": 40, + "text": "Sharpshooter\n\nScore 10 points with every\narrow in each of the 4 rounds.\nThis can be on any difficulty\nlevel but not in team play.\n\nObviously, it\u0027s easiest to do\non Beginner difficulty.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35004, + "index": 41, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35010, + "index": 0, + "text": "Stamp earned!\nHuge Air", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35010, + "index": 1, + "text": "Wakeboarding\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35010, + "index": 10, + "text": "Huge Air", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35010, + "index": 11, + "text": "Wakeboarding: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35010, + "index": 20, + "text": "Huge Air", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35010, + "index": 21, + "text": "Wakeboarding\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35010, + "index": 30, + "text": "Huge Air", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35010, + "index": 40, + "text": "Huge Air\n\nScore 100 points on a single\njump! Build up your speed and\npull off some massive air.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35011, + "index": 0, + "text": "Stamp earned!\nBag of Tricks", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35011, + "index": 1, + "text": "Wakeboarding\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35011, + "index": 10, + "text": "Bag of Tricks", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35011, + "index": 11, + "text": "Wakeboarding: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35011, + "index": 20, + "text": "Bag of Tricks", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35011, + "index": 21, + "text": "Wakeboarding\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35011, + "index": 30, + "text": "Bag of Tricks", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35011, + "index": 40, + "text": "Bag of Tricks\n\nLand seven or more different\nkinds of jumps on a single run.\nTry changing up your speed\nand length of your approach to\nthe wake to pull off different\njumps.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35012, + "index": 0, + "text": "Stamp earned!\nSmooth Landing", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35012, + "index": 1, + "text": "Wakeboarding\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35012, + "index": 10, + "text": "Smooth Landing", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35012, + "index": 11, + "text": "Wakeboarding: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35012, + "index": 20, + "text": "Smooth Landing", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35012, + "index": 21, + "text": "Wakeboarding\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35012, + "index": 30, + "text": "Smooth Landing", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35012, + "index": 40, + "text": "Smooth Landing\n\nLand 10 times jump in a row.\n\nEven if you pull off an amazing\njump, it won\u0027t mean anything if \nyou don\u0027t land it right. Keep your\nboard flat when landing.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35013, + "index": 0, + "text": "Stamp earned!\nMaster Carver", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35013, + "index": 1, + "text": "Wakeboarding\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35013, + "index": 10, + "text": "Master Carver", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35013, + "index": 11, + "text": "Wakeboarding: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35013, + "index": 20, + "text": "Master Carver", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35013, + "index": 21, + "text": "Wakeboarding\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35013, + "index": 30, + "text": "Master Carver", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35013, + "index": 40, + "text": "Master Carver\n\nScore 1,000 points or more on\nthe Expert level without hitting\nany obstacles.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35014, + "index": 0, + "text": "Stamp earned!\nThe Long Way Home", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35014, + "index": 1, + "text": "Wakeboarding\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35014, + "index": 10, + "text": "The Long Way Home", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35014, + "index": 11, + "text": "Wakeboarding: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35014, + "index": 20, + "text": "The Long Way Home", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35014, + "index": 21, + "text": "Wakeboarding\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35014, + "index": 30, + "text": "The Long Way Home", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35014, + "index": 40, + "text": "The Long Way Home\n\nLand 50 jumps and wakeboard all\nthe way around Wuhu Island in\nFree-Cruising mode.\n\nYou have to complete a course\nafterwards to get the stamp.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35020, + "index": 0, + "text": "Stamp earned!\nBeginner License", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35020, + "index": 1, + "text": "Canoeing\nSpeed Challenge\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35020, + "index": 10, + "text": "Beginner License", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35020, + "index": 11, + "text": "Canoeing - Speed Challenge: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35020, + "index": 12, + "text": "", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35020, + "index": 20, + "text": "Beginner License", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35020, + "index": 21, + "text": "Canoeing\nSpeed Challenge\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35020, + "index": 30, + "text": "Beginner License", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35020, + "index": 40, + "text": "Beginner License\n\nIn single-player mode, get to\n200 yd. in the Beginner level\nof the Speed Challenge.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35021, + "index": 0, + "text": "Stamp earned!\nIntermediate License", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35021, + "index": 1, + "text": "Canoeing\nSpeed Challenge\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35021, + "index": 10, + "text": "Intermediate License", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35021, + "index": 11, + "text": "Canoeing - Speed Challenge: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35021, + "index": 20, + "text": "Intermediate License", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35021, + "index": 21, + "text": "Canoeing\nSpeed Challenge\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35021, + "index": 30, + "text": "Intermediate License", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35021, + "index": 40, + "text": "Intermediate License\n\nPaddle to 300 yd. in the\nIntermediate level of the Speed\nChallenge in single-player mode.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35022, + "index": 0, + "text": "Stamp earned!\nExpert License", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35022, + "index": 1, + "text": "Canoeing\nSpeed Challenge\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35022, + "index": 10, + "text": "Expert License", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35022, + "index": 11, + "text": "Canoeing - Speed Challenge: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35022, + "index": 20, + "text": "Expert License", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35022, + "index": 21, + "text": "Canoeing\nSpeed Challenge\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35022, + "index": 30, + "text": "Expert License", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35022, + "index": 40, + "text": "Expert License\n\nGet to 400 yd. in the Expert\nlevel of the Speed Challenge in\nsingle-player mode.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35023, + "index": 0, + "text": "Stamp earned!\nDucks in a Row", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35023, + "index": 1, + "text": "Canoeing\nSpeed Challenge\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35023, + "index": 10, + "text": "Ducks in a Row", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35023, + "index": 11, + "text": "Canoeing - Speed Challenge: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35023, + "index": 20, + "text": "Ducks in a Row", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35023, + "index": 21, + "text": "Canoeing\nSpeed Challenge\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35023, + "index": 30, + "text": "Ducks in a Row", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35023, + "index": 40, + "text": "Ducks in a Row\n\nIn Free Practice Mode, find all\nthe stray ducklings on the lake\nand lead them back to their\nmother.\nYou have to complete the\nSpeed Challenge afterwards to\nget the stamp.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35024, + "index": 0, + "text": "Stamp earned!\nCut the Red Tape", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35024, + "index": 1, + "text": "Canoeing\nSpeed Challenge\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35024, + "index": 10, + "text": "Cut the Red Tape", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35024, + "index": 11, + "text": "Canoeing - Speed Challenge: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35024, + "index": 20, + "text": "Cut the Red Tape", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35024, + "index": 21, + "text": "Canoeing\nSpeed Challenge\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35024, + "index": 30, + "text": "Cut the Red Tape", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35024, + "index": 40, + "text": "Cut the Red Tape\n\nCut the red tape in all levels.\nHaven\u0027t seen any red tape yet?\nRemember that even after\ngetting your license for each\ndifficulty level, you can still\npaddle farther.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35030, + "index": 0, + "text": "Stamp earned!\nUnder Par", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35030, + "index": 1, + "text": "Golf\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35030, + "index": 10, + "text": "Under Par", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35030, + "index": 11, + "text": "Golf: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35030, + "index": 20, + "text": "Under Par", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35030, + "index": 21, + "text": "Golf\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35030, + "index": 30, + "text": "Under Par", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35030, + "index": 40, + "text": "Under Par\n\nFinish any course under par\n(in less than the set number\nof shots for the course).\nZero is par, and a score of -1 or\nless is under par. You can\u0027t\nget this stamp in team play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35031, + "index": 0, + "text": "Stamp earned!\nChip In", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35031, + "index": 1, + "text": "Golf\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35031, + "index": 10, + "text": "Chip In", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35031, + "index": 11, + "text": "Golf: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35031, + "index": 20, + "text": "Chip In", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35031, + "index": 21, + "text": "Golf\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35031, + "index": 30, + "text": "Chip In", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35031, + "index": 40, + "text": "Chip In\n\nGet a \u0022chip in\u0022 when a chip shot,\na short shot used to get the ball\nonto the green, falls or rolls\nstraight into the hole.\nMost golfers claim they were\naiming for the hole all along...", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35032, + "index": 0, + "text": "Stamp earned!\nKing of Clubs", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35032, + "index": 1, + "text": "Golf\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35032, + "index": 10, + "text": "King of Clubs", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35032, + "index": 11, + "text": "Golf: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35032, + "index": 20, + "text": "King of Clubs", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35032, + "index": 21, + "text": "Golf\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35032, + "index": 30, + "text": "King of Clubs", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35032, + "index": 40, + "text": "King of Clubs\n\nFinish a course at 9 under par,\nor 9 fewer shots than the preset\nnumber of shots for the course.\nOn a nine-hole course, that \nmeans getting a birdie on every\nhole! You can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35033, + "index": 0, + "text": "Stamp earned!\nAce of Clubs", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35033, + "index": 1, + "text": "Golf\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35033, + "index": 10, + "text": "Ace of Clubs", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35033, + "index": 11, + "text": "Golf: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35033, + "index": 20, + "text": "Ace of Clubs", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35033, + "index": 21, + "text": "Golf\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35033, + "index": 30, + "text": "Ace of Clubs", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35033, + "index": 40, + "text": "Ace of Clubs\n\nFinish a course at 18 under par\n(in 18 fewer shots than the set\nnumber of shots for the course).\nIn theory, it\u0027s possible to do this\neven on a nine-hole course.\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35034, + "index": 0, + "text": "Stamp earned!\nHole in One", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35034, + "index": 1, + "text": "Golf\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35034, + "index": 10, + "text": "Hole in One", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35034, + "index": 11, + "text": "Golf: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35034, + "index": 20, + "text": "Hole in One", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35034, + "index": 21, + "text": "Golf\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35034, + "index": 30, + "text": "Hole in One", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35034, + "index": 40, + "text": "Hole in One\n\nHit the ball and sink it into the\ncup in one amazing shot. \n\nIn real golf, getting a hole in one\nis extremely rare, even for\nseasoned pros.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35040, + "index": 0, + "text": "Stamp earned!\nLast Gasp", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35040, + "index": 1, + "text": "Cycling\nRoad Race\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35040, + "index": 10, + "text": "Last Gasp", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35040, + "index": 11, + "text": "Cycling - Road Race: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35040, + "index": 20, + "text": "Last Gasp", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35040, + "index": 21, + "text": "Cycling\nRoad Race\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35040, + "index": 30, + "text": "Last Gasp", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35040, + "index": 40, + "text": "Last Gasp\n\nFinish a race when you\u0027re \nout of breath.\n\nWe\u0027re not sure this really \ndeserves much in the way of \ncongratulations, but oh well...", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35041, + "index": 0, + "text": "Stamp earned!\nFirst of Many", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35041, + "index": 1, + "text": "Cycling\nRoad Race\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35041, + "index": 10, + "text": "First of Many", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35041, + "index": 11, + "text": "Cycling - Road Race: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35041, + "index": 20, + "text": "First of Many", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35041, + "index": 21, + "text": "Cycling\nRoad Race\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35041, + "index": 30, + "text": "First of Many", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35041, + "index": 40, + "text": "First of Many\n\nFinish a race in 1st place for\nthe first time to get this stamp.\n\nIt doesn\u0027t matter which race\nyou do it on.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35042, + "index": 0, + "text": "Stamp earned!\n1-Stage Master", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35042, + "index": 1, + "text": "Cycling\nRoad Race\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35042, + "index": 10, + "text": "1-Stage Master", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35042, + "index": 11, + "text": "Cycling - Road Race: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35042, + "index": 20, + "text": "1-Stage Master", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35042, + "index": 21, + "text": "Cycling\nRoad Race\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35042, + "index": 30, + "text": "1-Stage Master", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35042, + "index": 40, + "text": "1-Stage Master\n\nFinish all 1-stage races in\nfirst place.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35043, + "index": 0, + "text": "Stamp earned!\n3-Stage Master", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35043, + "index": 1, + "text": "Cycling\nRoad Race\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35043, + "index": 10, + "text": "3-Stage Master", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35043, + "index": 11, + "text": "Cycling - Road Race: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35043, + "index": 20, + "text": "3-Stage Master", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35043, + "index": 21, + "text": "Cycling\nRoad Race\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35043, + "index": 30, + "text": "3-Stage Master", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35043, + "index": 40, + "text": "3-Stage Master\n\nFinish both 3-stage races in\nfirst place.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35044, + "index": 0, + "text": "Stamp earned!\n6-Stage Master", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35044, + "index": 1, + "text": "Cycling\nRoad Race\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35044, + "index": 10, + "text": "6-Stage Master", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35044, + "index": 11, + "text": "Cycling - Road Race: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35044, + "index": 20, + "text": "6-Stage Master", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35044, + "index": 21, + "text": "Cycling\nRoad Race\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35044, + "index": 30, + "text": "6-Stage Master", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35044, + "index": 40, + "text": "6-Stage Master\n\nFinish the 6-stage race in\nfirst place.\n\nYou only have to finish first in\nthe last stage, so you can\ngradually work your way to the\nfront of the pack.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35050, + "index": 0, + "text": "Stamp earned!\nHot Streak", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35050, + "index": 1, + "text": "Basketball\n3-Point Contest\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35050, + "index": 10, + "text": "Hot Streak", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35050, + "index": 11, + "text": "Basketball - 3-Point Contest: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35050, + "index": 20, + "text": "Hot Streak", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35050, + "index": 21, + "text": "Basketball\n3-Point Contest\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35050, + "index": 30, + "text": "Hot Streak", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35050, + "index": 40, + "text": "Hot Streak\n\nSink five consecutive shots in\nthe basket.\n\nGet in a good rhythm with the\nfirst five balls, and anything\u0027s\npossible...", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35051, + "index": 0, + "text": "Stamp earned!\nBonus Plumber", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35051, + "index": 1, + "text": "Basketball\n3-Point Contest\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35051, + "index": 10, + "text": "Bonus Plumber", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35051, + "index": 11, + "text": "Basketball - 3-Point Contest: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35051, + "index": 20, + "text": "Bonus Plumber", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35051, + "index": 21, + "text": "Basketball\n3-Point Contest\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35051, + "index": 30, + "text": "Bonus Plumber", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35051, + "index": 40, + "text": "Bonus Plumber\n\nDrain all five bonus balls.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35052, + "index": 0, + "text": "Stamp earned!\nQuick Draw", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35052, + "index": 1, + "text": "Basketball\n3-Point Contest\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35052, + "index": 10, + "text": "Quick Draw", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35052, + "index": 11, + "text": "Basketball - 3-Point Contest: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35052, + "index": 20, + "text": "Quick Draw", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35052, + "index": 21, + "text": "Basketball\n3-Point Contest\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35052, + "index": 30, + "text": "Quick Draw", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35052, + "index": 40, + "text": "Quick Draw\n\nScore 20 points or more with\nat least 10 seconds left on the\nclock. Don\u0027t think--shoot!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35053, + "index": 0, + "text": "Stamp earned!\nHot Hand", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35053, + "index": 1, + "text": "Basketball\n3-Point Contest\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35053, + "index": 10, + "text": "Hot Hand", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35053, + "index": 11, + "text": "Basketball - 3-Point Contest: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35053, + "index": 20, + "text": "Hot Hand", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35053, + "index": 21, + "text": "Basketball\n3-Point Contest\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35053, + "index": 30, + "text": "Hot Hand", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35053, + "index": 40, + "text": "Hot Hand\n\nSink all 25 balls in the basket.\nJust stay focused and get into\nthe groove!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35054, + "index": 0, + "text": "Stamp earned!\nPure Shooter", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35054, + "index": 1, + "text": "Basketball\n3-Point Contest\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35054, + "index": 10, + "text": "Pure Shooter", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35054, + "index": 11, + "text": "Basketball - 3-Point Contest: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35054, + "index": 20, + "text": "Pure Shooter", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35054, + "index": 21, + "text": "Basketball\n3-Point Contest\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35054, + "index": 30, + "text": "Pure Shooter", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35054, + "index": 40, + "text": "Pure Shooter\n\nSink all 25 balls in the basket\nwith at least 15 seconds left on\nthe clock. It takes some serious\nskills!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35060, + "index": 0, + "text": "Stamp earned!\nTriple Dip", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35060, + "index": 1, + "text": "Basketball\nPickup Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35060, + "index": 10, + "text": "Triple Dip", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35060, + "index": 11, + "text": "Basketball - Pickup Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35060, + "index": 20, + "text": "Triple Dip", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35060, + "index": 21, + "text": "Basketball\nPickup Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35060, + "index": 30, + "text": "Triple Dip", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35060, + "index": 40, + "text": "Triple Dip\n\nScore a goal from beyond the\n3-point line in single-player\nmode.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35061, + "index": 0, + "text": "Stamp earned!\nRim Rattler", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35061, + "index": 1, + "text": "Basketball\nPickup Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35061, + "index": 10, + "text": "Rim Rattler", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35061, + "index": 11, + "text": "Basketball - Pickup Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35061, + "index": 20, + "text": "Rim Rattler", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35061, + "index": 21, + "text": "Basketball\nPickup Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35061, + "index": 30, + "text": "Rim Rattler", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35061, + "index": 40, + "text": "Rim Rattler\n\nDunk the ball five times in a\ngame in single-player mode.\nTo dunk, get right up underneath\nthe basket and slam the ball in.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35062, + "index": 0, + "text": "Stamp earned!\nLights Out", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35062, + "index": 1, + "text": "Basketball\nPickup Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35062, + "index": 10, + "text": "Lights Out", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35062, + "index": 11, + "text": "Basketball - Pickup Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35062, + "index": 20, + "text": "Lights Out", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35062, + "index": 21, + "text": "Basketball\nPickup Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35062, + "index": 30, + "text": "Lights Out", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35062, + "index": 40, + "text": "Lights Out\n\nDrain five 3-point baskets in\none game. A 3-point basket is a\nshot from beyond the 3-point\nline.\n\nYou can get this stamp in\nsingle-player mode only.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35063, + "index": 0, + "text": "Stamp earned!\nBuzzer Beater", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35063, + "index": 1, + "text": "Basketball\nPickup Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35063, + "index": 10, + "text": "Buzzer Beater", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35063, + "index": 11, + "text": "Basketball - Pickup Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35063, + "index": 20, + "text": "Buzzer Beater", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35063, + "index": 21, + "text": "Basketball\nPickup Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35063, + "index": 30, + "text": "Buzzer Beater", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35063, + "index": 40, + "text": "Buzzer Beater\n\nMake a last-second shot\nwith a \u0022buzzer beater,\u0022\na basket scored just before the\nbuzzer signals the end of\nthe game. You can get this stamp\nin single-player mode only.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35064, + "index": 0, + "text": "Stamp earned!\nHoop Hero", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35064, + "index": 1, + "text": "Basketball\nPickup Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35064, + "index": 10, + "text": "Hoop Hero", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35064, + "index": 11, + "text": "Basketball - Pickup Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35064, + "index": 20, + "text": "Hoop Hero", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35064, + "index": 21, + "text": "Basketball\nPickup Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35064, + "index": 30, + "text": "Hoop Hero", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35064, + "index": 40, + "text": "Hoop Hero\n\nTake down the champions in\na pickup game! The reigning\nWuhu champions are faster, \njump higher, and shoot better\nthan any other team. \nBetter drain some 3-pointers!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35070, + "index": 0, + "text": "Stamp earned!\nCliff-hanger", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35070, + "index": 1, + "text": "Swordplay\nDuel\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35070, + "index": 10, + "text": "Cliff-hanger", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35070, + "index": 11, + "text": "Swordplay - Duel: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35070, + "index": 20, + "text": "Cliff-hanger", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35070, + "index": 21, + "text": "Swordplay\nDuel\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35070, + "index": 30, + "text": "Cliff-hanger", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35070, + "index": 40, + "text": "Cliff-hanger\n\nThe final battle ring appears if\nthe two opponents are still\nlocked in a draw after three \nrounds. It doesn\u0027t matter \nwhether you win or lose. \nYou can get this stamp\nin single-player mode only.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35071, + "index": 0, + "text": "Stamp earned!\nStraight to the Point", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35071, + "index": 1, + "text": "Swordplay\nDuel\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35071, + "index": 10, + "text": "Straight to the Point", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35071, + "index": 11, + "text": "Swordplay - Duel: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35071, + "index": 20, + "text": "Straight to the Point", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35071, + "index": 21, + "text": "Swordplay\nDuel\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35071, + "index": 30, + "text": "Straight to the Point", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35071, + "index": 40, + "text": "Straight to the Point\n\nPush your opponent out of the\nring with a lunge in single-player\nmode.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35072, + "index": 0, + "text": "Stamp earned!\nMet Your Match", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35072, + "index": 1, + "text": "Swordplay\nDuel\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35072, + "index": 10, + "text": "Met Your Match", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35072, + "index": 11, + "text": "Swordplay - Duel: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35072, + "index": 20, + "text": "Met Your Match", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35072, + "index": 21, + "text": "Swordplay\nDuel\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35072, + "index": 30, + "text": "Met Your Match", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35072, + "index": 40, + "text": "Met Your Match\n\nDraw three rounds in a row to\nget to the final battle ring, then\ndraw again for a completely even\nmatch in single-player mode.\n\nYou may not have won, but it\u0027s\nno easy feat!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35073, + "index": 0, + "text": "Stamp earned!\nOne-Hit Wonder", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35073, + "index": 1, + "text": "Swordplay\nDuel\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35073, + "index": 10, + "text": "One-Hit Wonder", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35073, + "index": 11, + "text": "Swordplay - Duel: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35073, + "index": 20, + "text": "One-Hit Wonder", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35073, + "index": 21, + "text": "Swordplay\nDuel\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35073, + "index": 30, + "text": "One-Hit Wonder", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35073, + "index": 40, + "text": "One-Hit Wonder\n\nPush your opponent out of the\nring with only one strike in\nsingle-player mode.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35074, + "index": 0, + "text": "Stamp earned!\nLast Mii Standing", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35074, + "index": 1, + "text": "Swordplay\nDuel\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35074, + "index": 10, + "text": "Last Mii Standing", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35074, + "index": 11, + "text": "Swordplay - Duel: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35074, + "index": 20, + "text": "Last Mii Standing", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35074, + "index": 21, + "text": "Swordplay\nDuel\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35074, + "index": 30, + "text": "Last Mii Standing", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35074, + "index": 40, + "text": "Last Mii Standing\n\nDefeat the champion in a duel.\n\nThe key is to never let your\ndefenses down and attack\nany gaps you see. There may\nbe some sort of reward if you\nwin this...", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35080, + "index": 0, + "text": "Stamp earned!\nNot a Scratch", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35080, + "index": 1, + "text": "Swordplay\nShowdown\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35080, + "index": 10, + "text": "Not a Scratch", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35080, + "index": 11, + "text": "Swordplay - Showdown: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35080, + "index": 20, + "text": "Not a Scratch", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35080, + "index": 21, + "text": "Swordplay\nShowdown\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35080, + "index": 30, + "text": "Not a Scratch", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35080, + "index": 40, + "text": "Not a Scratch\n\nClear any stage without\ntaking a hit and losing a\nheart.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35081, + "index": 0, + "text": "Stamp earned!\nSwordmaster", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35081, + "index": 1, + "text": "Swordplay\nShowdown\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35081, + "index": 10, + "text": "Swordmaster", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35081, + "index": 11, + "text": "Swordplay - Showdown: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35081, + "index": 20, + "text": "Swordmaster", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35081, + "index": 21, + "text": "Swordplay\nShowdown\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35081, + "index": 30, + "text": "Swordmaster", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35081, + "index": 40, + "text": "Swordmaster\n\nFight through the final\nShowdown stage.\n\nYou must master the art\nof parrying.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35082, + "index": 0, + "text": "Stamp earned!\nUntouchable", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35082, + "index": 1, + "text": "Swordplay\nShowdown\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35082, + "index": 10, + "text": "Untouchable", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35082, + "index": 11, + "text": "Swordplay - Showdown: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35082, + "index": 20, + "text": "Untouchable", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35082, + "index": 21, + "text": "Swordplay\nShowdown\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35082, + "index": 30, + "text": "Untouchable", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35082, + "index": 40, + "text": "Untouchable\n\nFight through the final\nShowdown stage without\ntaking a single hit and\nlosing a heart.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35083, + "index": 0, + "text": "Stamp earned!\nSword Fighter", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35083, + "index": 1, + "text": "Swordplay\nShowdown\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35083, + "index": 10, + "text": "Sword Fighter", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35083, + "index": 11, + "text": "Swordplay - Showdown: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35083, + "index": 20, + "text": "Sword Fighter", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35083, + "index": 21, + "text": "Swordplay\nShowdown\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35083, + "index": 30, + "text": "Sword Fighter", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35083, + "index": 40, + "text": "Sword Fighter\n\nDefeat all of your foes to\nclear the first 10 stages.\nYou can\u0027t just swing wildly\nand hope for the best--\nit takes finesse.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35084, + "index": 0, + "text": "Stamp earned!\nPerfect 10", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35084, + "index": 1, + "text": "Swordplay\nShowdown\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35084, + "index": 10, + "text": "Perfect 10", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35084, + "index": 11, + "text": "Swordplay - Showdown: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35084, + "index": 20, + "text": "Perfect 10", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35084, + "index": 21, + "text": "Swordplay\nShowdown\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35084, + "index": 30, + "text": "Perfect 10", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35084, + "index": 40, + "text": "Perfect 10\n\nClear Stage 10 without taking\na single hit and losing a heart.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35090, + "index": 0, + "text": "Stamp earned!\nSlice and Dice", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35090, + "index": 1, + "text": "Swordplay\nSpeed Slice\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35090, + "index": 10, + "text": "Slice and Dice", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35090, + "index": 11, + "text": "Swordplay - Speed Slice: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35090, + "index": 20, + "text": "Slice and Dice", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35090, + "index": 21, + "text": "Swordplay\nSpeed Slice\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35090, + "index": 30, + "text": "Slice and Dice", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35090, + "index": 40, + "text": "Slice and Dice\n\nWin the contest without missing\na single object by slicing the\nwrong way or failing to slice\nwithin the time limit.\n\nYou can only get this stamp in\nsingle-player mode.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35090, + "index": 41, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35091, + "index": 0, + "text": "Stamp earned!\nSlicing Machine", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35091, + "index": 1, + "text": "Swordplay\nSpeed Slice\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35091, + "index": 10, + "text": "Slicing Machine", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35091, + "index": 11, + "text": "Swordplay - Speed Slice: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35091, + "index": 20, + "text": "Slicing Machine", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35091, + "index": 21, + "text": "Swordplay\nSpeed Slice\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35091, + "index": 30, + "text": "Slicing Machine", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35091, + "index": 40, + "text": "Slicing Machine\n\nCorrectly slice at least one of\neach of the 18 types of objects\nin single-player mode. Different\ncolors count as different types.\n\nYou\u0027ll need to play several\nrounds to get them all!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35092, + "index": 0, + "text": "Stamp earned!\nPsychic Slice", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35092, + "index": 1, + "text": "Swordplay\nSpeed Slice\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35092, + "index": 10, + "text": "Psychic Slice", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35092, + "index": 11, + "text": "Swordplay - Speed Slice: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35092, + "index": 20, + "text": "Psychic Slice", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35092, + "index": 21, + "text": "Swordplay\nSpeed Slice\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35092, + "index": 30, + "text": "Psychic Slice", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35092, + "index": 40, + "text": "Psychic Slice\n\nCut an object correctly\nbefore it even hits the ground\nin single-player mode.\n\nYou have to be psychic--or\nlucky--to pull this off.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35093, + "index": 0, + "text": "Stamp earned!\nDouble Time", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35093, + "index": 1, + "text": "Swordplay\nSpeed Slice\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35093, + "index": 10, + "text": "Double Time", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35093, + "index": 11, + "text": "Swordplay - Speed Slice: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35093, + "index": 20, + "text": "Double Time", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35093, + "index": 21, + "text": "Swordplay\nSpeed Slice\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35093, + "index": 30, + "text": "Double Time", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35093, + "index": 40, + "text": "Double Time\n\nSlice the alarm clock when\nthe two digits on the display\nare the same, such as 8.8,\n7.7, or 6.6.\n\nYou can only get this stamp in\nsingle-player mode.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35094, + "index": 0, + "text": "Stamp earned!\nA Cut Above", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35094, + "index": 1, + "text": "Swordplay\nSpeed Slice\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35094, + "index": 10, + "text": "A Cut Above", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35094, + "index": 11, + "text": "Swordplay - Speed Slice: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35094, + "index": 20, + "text": "A Cut Above", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35094, + "index": 21, + "text": "Swordplay\nSpeed Slice\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35094, + "index": 30, + "text": "A Cut Above", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35094, + "index": 40, + "text": "A Cut Above\n\nBeat the Speed Slice champion.\n\nEmpty your mind and slice with\nyour instincts!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35100, + "index": 0, + "text": "Stamp earned!\nIn Your Face", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35100, + "index": 1, + "text": "Table Tennis\nMatch\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35100, + "index": 10, + "text": "In Your Face", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35100, + "index": 11, + "text": "Table Tennis - Match: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35100, + "index": 20, + "text": "In Your Face", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35100, + "index": 21, + "text": "Table Tennis\nMatch\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35100, + "index": 30, + "text": "In Your Face", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35100, + "index": 40, + "text": "In Your Face\n\nFor some reason, you get a\nstamp for hitting your\nopponent\u0027s face with the ball\nin single-player mode.\n\nOf course, you would never hit\nthem in the face on purpose...", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35101, + "index": 0, + "text": "Stamp earned!\nBack From the Brink", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35101, + "index": 1, + "text": "Table Tennis\nMatch\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35101, + "index": 10, + "text": "Back From the Brink", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35101, + "index": 11, + "text": "Table Tennis - Match: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35101, + "index": 20, + "text": "Back From the Brink", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35101, + "index": 21, + "text": "Table Tennis\nMatch\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35101, + "index": 30, + "text": "Back From the Brink", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35101, + "index": 40, + "text": "Back From the Brink\n\nSuccessfully return a ball that\nhits the edge of the table and\nbounces at an unpredictable\nangle, making it harder to hit.\n\nYou can only get this stamp in\nsingle-player mode.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35101, + "index": 41, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35102, + "index": 0, + "text": "Stamp earned!\nEpic Rally", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35102, + "index": 1, + "text": "Table Tennis\nMatch\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35102, + "index": 10, + "text": "Epic Rally", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35102, + "index": 11, + "text": "Table Tennis - Match: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35102, + "index": 20, + "text": "Epic Rally", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35102, + "index": 21, + "text": "Table Tennis\nMatch\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35102, + "index": 30, + "text": "Epic Rally", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35102, + "index": 40, + "text": "Epic Rally\n\nKeep up a rally (hitting the ball\nback and forth without\nstopping) for 30 hits or more\nin single-player mode.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35103, + "index": 0, + "text": "Stamp earned!\nPerfectly Matched", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35103, + "index": 1, + "text": "Table Tennis\nMatch\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35103, + "index": 10, + "text": "Perfectly Matched", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35103, + "index": 11, + "text": "Table Tennis - Match: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35103, + "index": 20, + "text": "Perfectly Matched", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35103, + "index": 21, + "text": "Table Tennis\nMatch\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35103, + "index": 30, + "text": "Perfectly Matched", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35103, + "index": 40, + "text": "Perfectly Matched\n\nDraw with your opponent in\nsingle-player mode.\nAccording to the house rules,\na match is declared a draw if\nneither player can get two points\nahead and the score reaches\n20-20.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35104, + "index": 0, + "text": "Stamp earned!\nTable Titan", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35104, + "index": 1, + "text": "Table Tennis\nMatch\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35104, + "index": 10, + "text": "Table Titan", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35104, + "index": 11, + "text": "Table Tennis - Match: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35104, + "index": 20, + "text": "Table Titan", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35104, + "index": 21, + "text": "Table Tennis\nMatch\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35104, + "index": 30, + "text": "Table Titan", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35104, + "index": 40, + "text": "Table Titan\n\nBeat the table-tennis champion\nin a match.\n\nThe current champion quickly\nsurpassed her teacher and has\nsince gone undefeated.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35105, + "index": 0, + "text": "Stamp earned!\n50-pointer", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35105, + "index": 1, + "text": "Table Tennis\nReturn Challenge\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35105, + "index": 10, + "text": "50-pointer", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35105, + "index": 11, + "text": "Table Tennis - Return Challenge: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35105, + "index": 20, + "text": "50-pointer", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35105, + "index": 21, + "text": "Table Tennis\nReturn Challenge\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35105, + "index": 30, + "text": "50-pointer", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35105, + "index": 40, + "text": "50-pointer\n\nGet a score of 50 points or more.\n\nOnce you can do this, you\u0027re\nwell on your way to mastering\nthe art of returns.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35106, + "index": 0, + "text": "Stamp earned!\n100-pointer", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35106, + "index": 1, + "text": "Table Tennis\nReturn Challenge\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35106, + "index": 10, + "text": "100-pointer", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35106, + "index": 11, + "text": "Table Tennis - Return Challenge: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35106, + "index": 20, + "text": "100-pointer", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35106, + "index": 21, + "text": "Table Tennis\nReturn Challenge\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35106, + "index": 30, + "text": "100-pointer", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35106, + "index": 40, + "text": "100-pointer\n\nRack up a score of 100 points\nor more.\n\nIt takes a little effort to get\nthis stamp, so get in a good\nrhythm and think fast!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35107, + "index": 0, + "text": "Stamp earned!\n200-pointer", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35107, + "index": 1, + "text": "Table Tennis\nReturn Challenge\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35107, + "index": 10, + "text": "200-pointer", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35107, + "index": 11, + "text": "Table Tennis - Return Challenge: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35107, + "index": 20, + "text": "200-pointer", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35107, + "index": 21, + "text": "Table Tennis\nReturn Challenge\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35107, + "index": 30, + "text": "200-pointer", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35107, + "index": 40, + "text": "200-pointer\n\nRack up 200 points or more.\n\nThe mark of a true pro!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35108, + "index": 0, + "text": "Stamp earned!\nRecycler", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35108, + "index": 1, + "text": "Table Tennis\nReturn Challenge\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35108, + "index": 10, + "text": "Recycler", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35108, + "index": 11, + "text": "Table Tennis - Return Challenge: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35108, + "index": 20, + "text": "Recycler", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35108, + "index": 21, + "text": "Table Tennis\nReturn Challenge\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35108, + "index": 30, + "text": "Recycler", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35108, + "index": 40, + "text": "Recycler\n\nKnock the can off the table\nwith a ball 30 times in one\ngame.\n\nYou have to really focus!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35109, + "index": 0, + "text": "Stamp earned!\nSave Face", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35109, + "index": 1, + "text": "Table Tennis\nReturn Challenge\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35109, + "index": 10, + "text": "Save Face", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35109, + "index": 11, + "text": "Table Tennis - Return Challenge: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35109, + "index": 20, + "text": "Save Face", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35109, + "index": 21, + "text": "Table Tennis\nReturn Challenge\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35109, + "index": 30, + "text": "Save Face", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35109, + "index": 40, + "text": "Save Face\n\nGet a score of 100 points or\nmore without the ball ever hitting\nthe server\u0027s face, even if it just \ntakes a bad bounce off of a can.\n\nYour opponent will appreciate\nthe effort!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35110, + "index": 0, + "text": "Stamp earned!\nUnder Par", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35110, + "index": 1, + "text": "Frisbee\u00AE\nFrisbee Golf\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35110, + "index": 10, + "text": "Under Par", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35110, + "index": 11, + "text": "Frisbee\u00AE - Frisbee Golf: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35110, + "index": 20, + "text": "Under Par", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35110, + "index": 21, + "text": "Frisbee\u00AE\nFrisbee Golf\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35110, + "index": 30, + "text": "Under Par", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35110, + "index": 40, + "text": "Under Par\n\nFinish any 3-, 9-, or 18-hole\ncourse under par. A score of 0 is\npar. A score of -1 or less is\nunder par.\n\nYou can\u0027t earn this stamp\nin a team-play match.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35111, + "index": 0, + "text": "Stamp earned!\nLucky Skip", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35111, + "index": 1, + "text": "Frisbee\u00AE\nFrisbee Golf\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35111, + "index": 10, + "text": "Lucky Skip", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35111, + "index": 11, + "text": "Frisbee\u00AE - Frisbee Golf: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35111, + "index": 20, + "text": "Lucky Skip", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35111, + "index": 21, + "text": "Frisbee\u00AE\nFrisbee Golf\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35111, + "index": 30, + "text": "Lucky Skip", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35111, + "index": 40, + "text": "Lucky Skip\n\nGet this stamp when a Frisbee\nbound for a water hazard skips\nacross the surface of the water\nand lands safely on the\nother side.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35112, + "index": 0, + "text": "Stamp earned!\nOn a Roll", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35112, + "index": 1, + "text": "Frisbee\u00AE\nFrisbee Golf\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35112, + "index": 10, + "text": "On a Roll", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35112, + "index": 11, + "text": "Frisbee\u00AE - Frisbee Golf: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35112, + "index": 20, + "text": "On a Roll", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35112, + "index": 21, + "text": "Frisbee\u00AE\nFrisbee Golf\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35112, + "index": 30, + "text": "On a Roll", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35112, + "index": 40, + "text": "On a Roll\n\nTo pull off a \u0022roll-in,\u0022 throw your\nFrisbee from outside the green,\nhit the ground, and roll it into\nthe goal.\n\nIt sounds tough, and it\u0027s even\ntougher than you think.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35112, + "index": 41, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35113, + "index": 0, + "text": "Stamp earned!\nStraight and Narrow", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35113, + "index": 1, + "text": "Frisbee\u00AE\nFrisbee Golf\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35113, + "index": 10, + "text": "Straight and Narrow", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35113, + "index": 11, + "text": "Frisbee\u00AE - Frisbee Golf: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35113, + "index": 20, + "text": "Straight and Narrow", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35113, + "index": 21, + "text": "Frisbee\u00AE\nFrisbee Golf\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35113, + "index": 30, + "text": "Straight and Narrow", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35113, + "index": 40, + "text": "Straight and Narrow\n\nPlay an 18-hole round of Frisbee\nGolf without throwing any\ndiscs out of bounds or into\na water hazard.\n\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35114, + "index": 0, + "text": "Stamp earned!\nHole in One", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35114, + "index": 1, + "text": "Frisbee\u00AE\nFrisbee Golf\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35114, + "index": 10, + "text": "Hole in One", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35114, + "index": 11, + "text": "Frisbee\u00AE - Frisbee Golf: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35114, + "index": 20, + "text": "Hole in One", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35114, + "index": 21, + "text": "Frisbee\u00AE\nFrisbee Golf\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35114, + "index": 30, + "text": "Hole in One", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35114, + "index": 40, + "text": "Hole in One\n\nThrow the Frisbee into the target\narea in just one throw.\n\nThe target is a tower of light\nrather than a tiny hole, so it\u0027s\na lot easier to do than in classic\ngolf...but still not easy!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35120, + "index": 0, + "text": "Stamp earned!\nGood Dog", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35120, + "index": 1, + "text": "Frisbee\u00AE\nFrisbee Dog\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35120, + "index": 10, + "text": "Good Dog", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35120, + "index": 11, + "text": "Frisbee\u00AE - Frisbee Dog: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35120, + "index": 20, + "text": "Good Dog", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35120, + "index": 21, + "text": "Frisbee\u00AE\nFrisbee Dog\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35120, + "index": 30, + "text": "Good Dog", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35120, + "index": 40, + "text": "Good Dog\n\nThrow the Frisbee right into\nthe center of the target area\nto make the dog jump up and\ngrab it out of the air. This is\nmore of an accomplishment for\nthe dog, really...", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35121, + "index": 0, + "text": "Stamp earned!\nBalloon Animal", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35121, + "index": 1, + "text": "Frisbee\u00AE\nFrisbee Dog\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35121, + "index": 10, + "text": "Balloon Animal", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35121, + "index": 11, + "text": "Frisbee\u00AE - Frisbee Dog: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35121, + "index": 20, + "text": "Balloon Animal", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35121, + "index": 21, + "text": "Frisbee\u00AE\nFrisbee Dog\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35121, + "index": 30, + "text": "Balloon Animal", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35121, + "index": 40, + "text": "Balloon Animal\n\nDuring practice, pop all 9\nballoons in ten throws or less.\nAfter ten throws, any remaining\nballoons are replaced with nine\nnew ones. You have to complete\na match to get the stamp.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35122, + "index": 0, + "text": "Stamp earned!\nA for Effort", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35122, + "index": 1, + "text": "Frisbee\u00AE\nFrisbee Dog\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35122, + "index": 10, + "text": "A for Effort", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35122, + "index": 11, + "text": "Frisbee\u00AE - Frisbee Dog: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35122, + "index": 20, + "text": "A for Effort", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35122, + "index": 21, + "text": "Frisbee\u00AE\nFrisbee Dog\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35122, + "index": 30, + "text": "A for Effort", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35122, + "index": 40, + "text": "A for Effort\n\nScore 10 points with each of\nyour 10 throws to get this \nstamp. That means hitting the \ngreen 10-point zone every time.\nIt\u0027s at least as hard as aiming \nfor the bull\u0027s-eye! You can\u0027t \nget this stamp in team play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35123, + "index": 0, + "text": "Stamp earned!\nPerfect Target", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35123, + "index": 1, + "text": "Frisbee\u00AE\nFrisbee Dog\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35123, + "index": 10, + "text": "Perfect Target", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35123, + "index": 11, + "text": "Frisbee\u00AE - Frisbee Dog: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35123, + "index": 20, + "text": "Perfect Target", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35123, + "index": 21, + "text": "Frisbee\u00AE\nFrisbee Dog\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35123, + "index": 30, + "text": "Perfect Target", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35123, + "index": 40, + "text": "Perfect Target\n\nHit the center of the target area\nand score 100 points with all ten\nof your throws. Extra points\nscored by popping balloons don\u0027t\ncount. You can\u0027t get this stamp\nin team play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35124, + "index": 0, + "text": "Stamp earned!\nGolden Arm", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35124, + "index": 1, + "text": "Frisbee\u00AE\nFrisbee Dog\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35124, + "index": 10, + "text": "Golden Arm", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35124, + "index": 11, + "text": "Frisbee\u00AE - Frisbee Dog: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35124, + "index": 20, + "text": "Golden Arm", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35124, + "index": 21, + "text": "Frisbee\u00AE\nFrisbee Dog\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35124, + "index": 30, + "text": "Golden Arm", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35124, + "index": 40, + "text": "Golden Arm\n\nScore 100 points with every\nthrow and pop every balloon.\nThat\u0027ll get you an astonishing\n1,500 points.\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35130, + "index": 0, + "text": "Stamp earned!\nGobble Gobble", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35130, + "index": 1, + "text": "Bowling\nStandard Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35130, + "index": 10, + "text": "Gobble Gobble", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35130, + "index": 11, + "text": "Bowling - Standard Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35130, + "index": 20, + "text": "Gobble Gobble", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35130, + "index": 21, + "text": "Bowling\nStandard Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35130, + "index": 30, + "text": "Gobble Gobble", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35130, + "index": 40, + "text": "Gobble Gobble\n\nBowl three strikes in a row to\nget a turkey. Apparently, the \nterm comes from an old custom\nof giving a turkey to any player\nwho could bowl three strikes \nin a row. You can\u0027t get this\nstamp in team play. ", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35131, + "index": 0, + "text": "Stamp earned!\nSplit Spare", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35131, + "index": 1, + "text": "Bowling\nStandard Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35131, + "index": 10, + "text": "Split Spare", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35131, + "index": 11, + "text": "Bowling - Standard Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35131, + "index": 20, + "text": "Split Spare", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35131, + "index": 21, + "text": "Bowling\nStandard Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35131, + "index": 30, + "text": "Split Spare", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35131, + "index": 40, + "text": "Split Spare\n\nComplete a spare after getting\na split on your first throw.\n\nA split is when you knock over\nthe headpin but leave other pins\nside by side or standing with an\nopening, or split, between them.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35132, + "index": 0, + "text": "Stamp earned!\nHigh Roller", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35132, + "index": 1, + "text": "Bowling\nStandard Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35132, + "index": 10, + "text": "High Roller", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35132, + "index": 11, + "text": "Bowling - Standard Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35132, + "index": 20, + "text": "High Roller", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35132, + "index": 21, + "text": "Bowling\nStandard Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35132, + "index": 30, + "text": "High Roller", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35132, + "index": 40, + "text": "High Roller\n\nGet a score of 200 points\nor more to receive this stamp.\nThat means, for example, getting\nall strikes and spares, with at\nleast one double. Very little\nmargin for error! You can\u0027t \nget this stamp in team play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35133, + "index": 0, + "text": "Stamp earned!\nPin Dropper", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35133, + "index": 1, + "text": "Bowling\nStandard Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35133, + "index": 10, + "text": "Pin Dropper", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35133, + "index": 11, + "text": "Bowling - Standard Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35133, + "index": 20, + "text": "Pin Dropper", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35133, + "index": 21, + "text": "Bowling\nStandard Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35133, + "index": 30, + "text": "Pin Dropper", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35133, + "index": 40, + "text": "Pin Dropper\n\nScore a strike or a spare on\nevery frame (except the third\nthrow of the 10th frame, which\ndoesn\u0027t count).\n\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35134, + "index": 0, + "text": "Stamp earned!\nPerfect Game", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35134, + "index": 1, + "text": "Bowling\nStandard Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35134, + "index": 10, + "text": "Perfect Game", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35134, + "index": 11, + "text": "Bowling - Standard Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35134, + "index": 20, + "text": "Perfect Game", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35134, + "index": 21, + "text": "Bowling\nStandard Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35134, + "index": 30, + "text": "Perfect Game", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35134, + "index": 40, + "text": "Perfect Game\n\nBowl 12 strikes in a row!\n\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35140, + "index": 0, + "text": "Stamp earned!\nSuper Strike", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35140, + "index": 1, + "text": "Bowling\n100-Pin Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35140, + "index": 10, + "text": "Super Strike", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35140, + "index": 11, + "text": "Bowling - 100-Pin Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35140, + "index": 20, + "text": "Super Strike", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35140, + "index": 21, + "text": "Bowling\n100-Pin Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35140, + "index": 30, + "text": "Super Strike", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35140, + "index": 40, + "text": "Super Strike\n\nKnock all 100 pins down with\none huge strike.\n\nThat domino effect is so\nsatisfying to watch!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35141, + "index": 0, + "text": "Stamp earned!\nSplit Spare", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35141, + "index": 1, + "text": "Bowling\n100-Pin Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35141, + "index": 10, + "text": "Split Spare", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35141, + "index": 11, + "text": "Bowling - 100-Pin Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35141, + "index": 20, + "text": "Split Spare", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35141, + "index": 21, + "text": "Bowling\n100-Pin Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35141, + "index": 30, + "text": "Split Spare", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35141, + "index": 40, + "text": "Split Spare\n\nComplete a spare after getting\na split on your first throw.\n\nA split is when you knock over\nthe headpin but leave other pins\nside by side or standing with an\nopening, or split, between them.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35142, + "index": 0, + "text": "Stamp earned!\nSecret Strike", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35142, + "index": 1, + "text": "Bowling\n100-Pin Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35142, + "index": 10, + "text": "Secret Strike", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35142, + "index": 11, + "text": "Bowling - 100-Pin Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35142, + "index": 20, + "text": "Secret Strike", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35142, + "index": 21, + "text": "Bowling\n100-Pin Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35142, + "index": 30, + "text": "Secret Strike", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35142, + "index": 40, + "text": "Secret Strike\n\nWord is, there\u0027s a somewhat\nunusual way to get a strike.\nThey say it has something to do\nwith the gutter guards...", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35143, + "index": 0, + "text": "Stamp earned!\nPin Dropper", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35143, + "index": 1, + "text": "Bowling\n100-Pin Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35143, + "index": 10, + "text": "Pin Dropper", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35143, + "index": 11, + "text": "Bowling - 100-Pin Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35143, + "index": 20, + "text": "Pin Dropper", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35143, + "index": 21, + "text": "Bowling\n100-Pin Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35143, + "index": 30, + "text": "Pin Dropper", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35143, + "index": 31, + "text": "", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35143, + "index": 40, + "text": "Pin Dropper\n\nScore a strike or a spare on\nevery frame (except the third\nthrow of the 10th frame, which\ndoesn\u0027t count).\n\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35143, + "index": 41, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35144, + "index": 0, + "text": "Stamp earned!\nOff the Wall", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35144, + "index": 1, + "text": "Bowling\n100-Pin Game\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35144, + "index": 10, + "text": "Off the Wall", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35144, + "index": 11, + "text": "Bowling - 100-Pin Game: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35144, + "index": 20, + "text": "Off the Wall", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35144, + "index": 21, + "text": "Bowling\n100-Pin Game\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35144, + "index": 30, + "text": "Off the Wall", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35144, + "index": 40, + "text": "Off the Wall\n\nHit the gutter guard once\nand then get a strike.\n\nBring your skill...or luck!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35150, + "index": 0, + "text": "Stamp earned!\nHead First", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35150, + "index": 1, + "text": "Bowling\nSpin Control\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35150, + "index": 10, + "text": "Head First", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35150, + "index": 11, + "text": "Bowling - Spin Control: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35150, + "index": 20, + "text": "Head First", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35150, + "index": 21, + "text": "Bowling\nSpin Control\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35150, + "index": 30, + "text": "Head First", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35150, + "index": 40, + "text": "Head First\n\nKnock down the headpin in every\nframe.\n\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35151, + "index": 0, + "text": "Stamp earned!\nSplit Spare", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35151, + "index": 1, + "text": "Bowling\nSpin Control\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35151, + "index": 10, + "text": "Split Spare", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35151, + "index": 11, + "text": "Bowling - Spin Control: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35151, + "index": 20, + "text": "Split Spare", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35151, + "index": 21, + "text": "Bowling\nSpin Control\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35151, + "index": 30, + "text": "Split Spare", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35151, + "index": 40, + "text": "Split Spare\n\nComplete a spare after getting\na split on your first throw.\n\nA split is when you knock over\nthe headpin but leave other pins\nside by side or standing with an\nopening, or split, between them.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35152, + "index": 0, + "text": "Stamp earned!\nEnglish Major", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35152, + "index": 1, + "text": "Bowling\nSpin Control\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35152, + "index": 10, + "text": "English Major", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35152, + "index": 11, + "text": "Bowling - Spin Control: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35152, + "index": 20, + "text": "English Major", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35152, + "index": 21, + "text": "Bowling\nSpin Control\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35152, + "index": 30, + "text": "English Major", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35152, + "index": 40, + "text": "English Major\n\nScore 170 points or more\nwithout hitting a single barrier.\nYou have to put English (spin)\non the ball to pull it off! \n\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35153, + "index": 0, + "text": "Stamp earned!\nPin Dropper", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35153, + "index": 1, + "text": "Bowling\nSpin Control\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35153, + "index": 10, + "text": "Pin Dropper", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35153, + "index": 11, + "text": "Bowling - Spin Control: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35153, + "index": 20, + "text": "Pin Dropper", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35153, + "index": 21, + "text": "Bowling\nSpin Control\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35153, + "index": 30, + "text": "Pin Dropper", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35153, + "index": 40, + "text": "Pin Dropper\n\nScore a strike or a spare on\nevery frame (except the third\nthrow of the 10th frame, which\ndoesn\u0027t count).\n\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35154, + "index": 0, + "text": "Stamp earned!\nOne for All", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35154, + "index": 1, + "text": "Bowling\nSpin Control\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35154, + "index": 10, + "text": "One for All", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35154, + "index": 11, + "text": "Bowling - Spin Control: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35154, + "index": 20, + "text": "One for All", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35154, + "index": 21, + "text": "Bowling\nSpin Control\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35154, + "index": 30, + "text": "One for All", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35154, + "index": 40, + "text": "One for All\n\nKnock down at least one pin in\nevery frame.\n\nYou can\u0027t get this stamp in\nteam play.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35160, + "index": 0, + "text": "Stamp earned!\nRingmaster", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35160, + "index": 1, + "text": "Power Cruising\nSlalom Course\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35160, + "index": 10, + "text": "Ringmaster", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35160, + "index": 11, + "text": "Power Cruising - Slalom Course: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35160, + "index": 20, + "text": "Ringmaster", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35160, + "index": 21, + "text": "Power Cruising\nSlalom Course\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35160, + "index": 30, + "text": "Ringmaster", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35160, + "index": 40, + "text": "Ringmaster\n\nGo through every single bonus\nring on one course.\n\nIt doesn\u0027t matter which course\nyou do it on.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35161, + "index": 0, + "text": "Stamp earned!\n5,000-pointer", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35161, + "index": 1, + "text": "Power Cruising\nSlalom Course\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35161, + "index": 10, + "text": "5,000-pointer", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35161, + "index": 11, + "text": "Power Cruising - Slalom Course: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35161, + "index": 20, + "text": "5,000-pointer", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35161, + "index": 21, + "text": "Power Cruising\nSlalom Course\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35161, + "index": 30, + "text": "5,000-pointer", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35161, + "index": 40, + "text": "5,000-pointer\n\nGet a cumulative score of\n5,000 points or more overall.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35162, + "index": 0, + "text": "Stamp earned!\nPower Cruiser", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35162, + "index": 1, + "text": "Power Cruising\nSlalom Course\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35162, + "index": 10, + "text": "Power Cruiser", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35162, + "index": 11, + "text": "Power Cruising - Slalom Course: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35162, + "index": 20, + "text": "Power Cruiser", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35162, + "index": 21, + "text": "Power Cruising\nSlalom Course\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35162, + "index": 30, + "text": "Power Cruiser", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35162, + "index": 40, + "text": "Power Cruiser\n\nScore 170 points or\nmore on all courses.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35163, + "index": 0, + "text": "Stamp earned!\nPower Jumper", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35163, + "index": 1, + "text": "Power Cruising\nSlalom Course\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35163, + "index": 10, + "text": "Power Jumper", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35163, + "index": 11, + "text": "Power Cruising - Slalom Course: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35163, + "index": 20, + "text": "Power Jumper", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35163, + "index": 21, + "text": "Power Cruising\nSlalom Course\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35163, + "index": 30, + "text": "Power Jumper", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35163, + "index": 40, + "text": "Power Jumper\n\nGo through all the bonus rings\nin the final course.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35164, + "index": 0, + "text": "Stamp earned!\nLeisure Cruiser", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35164, + "index": 1, + "text": "Power Cruising\nSlalom Course\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35164, + "index": 10, + "text": "Leisure Cruiser", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35164, + "index": 11, + "text": "Power Cruising - Slalom Course: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35164, + "index": 20, + "text": "Leisure Cruiser", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35164, + "index": 21, + "text": "Power Cruising\nSlalom Course\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35164, + "index": 30, + "text": "Leisure Cruiser", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35164, + "index": 40, + "text": "Leisure Cruiser\n\nFind all the time balloons in one\nrun in single-player Free-Cruising\nmode. You have to complete the\nSlalom Course afterwards to\nget the stamp.\n\nNot available in multiplayer mode.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35170, + "index": 0, + "text": "Stamp earned!\nIsland Hopper", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35170, + "index": 1, + "text": "Air Sports\nIsland Flyover\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35170, + "index": 10, + "text": "Island Hopper", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35170, + "index": 11, + "text": "Air Sports - Island Flyover: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35170, + "index": 20, + "text": "Island Hopper", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35170, + "index": 21, + "text": "Air Sports\nIsland Flyover\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35170, + "index": 30, + "text": "Island Hopper", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35170, + "index": 40, + "text": "Island Hopper\n\nVisit any \u332B point on Wedge\nIsland.\n\nWedge Island is the large island\na little way away from the main\nisland, where the golf courses\nare located.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35171, + "index": 0, + "text": "Stamp earned!\nPop Frenzy", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35171, + "index": 1, + "text": "Air Sports\nIsland Flyover\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35171, + "index": 10, + "text": "Pop Frenzy", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35171, + "index": 11, + "text": "Air Sports - Island Flyover: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35171, + "index": 20, + "text": "Pop Frenzy", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35171, + "index": 21, + "text": "Air Sports\nIsland Flyover\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35171, + "index": 30, + "text": "Pop Frenzy", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35171, + "index": 40, + "text": "Pop Frenzy\n\nPop 150 balloons in the course\nof one flight.\n\nThis includes balloons on planes\nor vehicles and small balloons\nreleased from larger ones.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35172, + "index": 0, + "text": "Stamp earned!\nFollow That Plane", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35172, + "index": 1, + "text": "Air Sports\nIsland Flyover\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35172, + "index": 10, + "text": "Follow That Plane", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35172, + "index": 11, + "text": "Air Sports - Island Flyover: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35172, + "index": 20, + "text": "Follow That Plane", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35172, + "index": 21, + "text": "Air Sports\nIsland Flyover\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35172, + "index": 30, + "text": "Follow That Plane", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35172, + "index": 40, + "text": "Follow That Plane\n\nFollow Miguel\u0027s guide plane\naround the island for at least\nthree minutes. Watch the smoke\ntrail left by Miguel\u0027s plane.\nIt changes color while you are\nfollowing him. If you can\u0027t find\nhim, try firing a flare.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35173, + "index": 0, + "text": "Stamp earned!\nWuhu Tour Guide", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35173, + "index": 1, + "text": "Air Sports\nIsland Flyover\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35173, + "index": 10, + "text": "Wuhu Tour Guide", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35173, + "index": 11, + "text": "Air Sports - Island Flyover: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35173, + "index": 20, + "text": "Wuhu Tour Guide", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35173, + "index": 21, + "text": "Air Sports\nIsland Flyover\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35173, + "index": 30, + "text": "Wuhu Tour Guide", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35173, + "index": 40, + "text": "Wuhu Tour Guide\n\nCollect all the \u332B points in the\ndaytime, evening, and night.\n\nThere are 80 locations, with new\ninformation for each time of day.\nThat\u0027s 240 \u332B points in total!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35174, + "index": 0, + "text": "Stamp earned!\nBalloonatic", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35174, + "index": 1, + "text": "Air Sports\nIsland Flyover\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35174, + "index": 10, + "text": "Balloonatic", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35174, + "index": 11, + "text": "Air Sports - Island Flyover: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35174, + "index": 20, + "text": "Balloonatic", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35174, + "index": 21, + "text": "Air Sports\nIsland Flyover\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35174, + "index": 30, + "text": "Balloonatic", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35174, + "index": 40, + "text": "Balloonatic\n\nPop every white balloon at all\ntimes of day. Once popped, white\nballoons will be a different color\nthe next time you play. Balloons\non planes or vehicles and small\nballoons released from larger\nones don\u0027t count for this stamp.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35180, + "index": 0, + "text": "Stamp earned!\nHigh Five", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35180, + "index": 1, + "text": "Air Sports\nSkydiving\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35180, + "index": 10, + "text": "High Five", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35180, + "index": 11, + "text": "Air Sports - Skydiving: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35180, + "index": 20, + "text": "High Five", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35180, + "index": 21, + "text": "Air Sports\nSkydiving\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35180, + "index": 30, + "text": "High Five", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35180, + "index": 40, + "text": "High Five\n\nCatch and link up with 4 other\nMii characters and make sure\neveryone\u0027s face is visible when\nthe camera snaps.\nTwist the Wii Remote around\nto get everyone to face\nthe camera.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35181, + "index": 0, + "text": "Stamp earned!\nCamera Shy", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35181, + "index": 1, + "text": "Air Sports\nSkydiving\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35181, + "index": 10, + "text": "Camera Shy", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35181, + "index": 11, + "text": "Air Sports - Skydiving: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35181, + "index": 20, + "text": "Camera Shy", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35181, + "index": 21, + "text": "Air Sports\nSkydiving\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35181, + "index": 30, + "text": "Camera Shy", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35181, + "index": 40, + "text": "Camera Shy\n\nApparently, if you don\u0027t manage\nto catch anybody on your dive,\nthe photographer will come out\nfrom behind the camera for a\nspecial shot!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35182, + "index": 0, + "text": "Stamp earned!\nFriends in High Places", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35182, + "index": 1, + "text": "Air Sports\nSkydiving\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35182, + "index": 10, + "text": "Friends in High Places", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35182, + "index": 11, + "text": "Air Sports - Skydiving: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35182, + "index": 20, + "text": "Friends in High Places", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35182, + "index": 21, + "text": "Air Sports\nSkydiving\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35182, + "index": 30, + "text": "Friends in High Places", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35182, + "index": 40, + "text": "Friends in High Places\n\nCatch at least 29 Mii characters\nduring your dive, then join them\nfor the final formation and have\na picture taken.\nEven if you catch more than 29\nMii characters, 30 people is the\nbiggest formation you can get.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35183, + "index": 0, + "text": "Stamp earned!\nFor the Birds", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35183, + "index": 1, + "text": "Air Sports\nSkydiving\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35183, + "index": 10, + "text": "For the Birds", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35183, + "index": 11, + "text": "Air Sports - Skydiving: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35183, + "index": 20, + "text": "For the Birds", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35183, + "index": 21, + "text": "Air Sports\nSkydiving\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35183, + "index": 30, + "text": "For the Birds", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35183, + "index": 40, + "text": "For the Birds\n\nTake a photo with a bird in it.\n\nHawks are often seen flying\njust above formation altitude.\nIf you\u0027re lucky, a hawk might fly\nby just as the camera snaps!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 35184, + "index": 0, + "text": "Stamp earned!\n200-point Dive", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 35184, + "index": 1, + "text": "Air Sports\nSkydiving\n{ VAR_1 }", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 35184, + "index": 10, + "text": "200-point Dive", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 35184, + "index": 11, + "text": "Air Sports - Skydiving: { VAR_1 }", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 35184, + "index": 20, + "text": "200-point Dive", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35184, + "index": 21, + "text": "Air Sports\nSkydiving\n{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 35184, + "index": 30, + "text": "200-point Dive", + "attributes": "0x00000032", + "ex_attributes": "0x01 0x40 0x01 0xFE" + }, + { + "group": 35184, + "index": 40, + "text": "200-point Dive\n\nGet a score of 200 points\nor more.\n\nYou\u0027ll need to make sure\neveryone\u0027s face is visible to\nget the most bonus points.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 39999, + "index": 0, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 39999, + "index": 1, + "text": "", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 39999, + "index": 10, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 39999, + "index": 11, + "text": "", + "attributes": "0x0000006D", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 39999, + "index": 20, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 39999, + "index": 21, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 39999, + "index": 30, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x02 0x01" + }, + { + "group": 45000, + "index": 50, + "text": "Hold the Wii Remote\nin both hands with \uE041\nfacing you.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45000, + "index": 51, + "text": "Swing your sword by moving\nthe Wii Remote up, down, left,\nor right.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45000, + "index": 52, + "text": "The bigger your swing, the\nmore powerful your attack\nwill be.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45000, + "index": 53, + "text": "Swing your sword to slice\nand chop!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45000, + "index": 54, + "text": "Hold down \uE043 to get in\na defensive stance.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45000, + "index": 55, + "text": "Hold down \uE043 and move\nthe Wii Remote to block\nyour opponent\u0027s attacks.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45000, + "index": 56, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45000, + "index": 57, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45001, + "index": 50, + "text": "Slice in the direction\nshown by the arrow.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45001, + "index": 51, + "text": "Slice faster than your\nopponent to score a point.\nFirst to 10 points wins!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45001, + "index": 52, + "text": "Let the slicing begin!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45100, + "index": 50, + "text": "Let\u0027s start with some\nbasic pointers.{ T05_0000 }\nHold the Wii Remote in your\nright hand and the Nunchuk\nin your left hand. { T05_0000 }\nHold \uE041 and \u3327 sideways,\nfacing you.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45100, + "index": 51, + "text": "Tilt the Wii Remote and\nNunchuk left or right to\nlean and turn.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45100, + "index": 52, + "text": "Press \uE043 to go forward.\nTwist the Wii Remote and\nhold \uE043 for a speed boost.{ T05_0000 }\nIf you find it difficult\nto press \uE043, try pressing\n\uE042 instead.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45100, + "index": 53, + "text": "The speed of your boost is\ndetermined by the level of\nthe Boost Meter.{ T05_0000 }\nTime your speed boosts\nwell for maximum speed!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45100, + "index": 54, + "text": "Hold the Wii Remote and\nNunchuk as though they were\nthe handlebars of a bike.{ T05_0000 }\nJust relax and enjoy the ride!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45100, + "index": 55, + "text": "Go ahead--give it a try!\nPress \uE046 at any time\nto quit practice.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45100, + "index": 60, + "text": "\uE042/\uE043\uFF1A Accelerate\nTwist\uFF1A Boost", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45100, + "index": 61, + "text": "Give the Wii Remote\na { COMMON_FONT_COLOR 01 00 }strong twist{ COMMON_FONT_COLOR 00 00 }\nfor a speed boost.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45100, + "index": 62, + "text": "Press \uE046 to quit practice.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 50, + "text": "{ VAR_0 } Keep a secure grip on the\nWii Remote.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 51, + "text": "{ VAR_0 } Hold the Wii Remote\nhorizontally and draw your \narm back to take aim.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 52, + "text": "{ VAR_0 } The direction the Frisbee flies\ndepends on when you snap\nyour wrist during your throw.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 53, + "text": "{ VAR_0 } Swing the Wii Remote toward\nthe target area and give your\nwrist a flick to send it flying.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 54, + "text": "Change the angle of the\nFrisbee to throw it in a { COMMON_FONT_COLOR 01 00 }curve{ COMMON_FONT_COLOR 00 00 }.\nTry experimenting a little!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 55, + "text": "If you can pop balloons and hit\nyour target, you\u0027ve got it down.\nPress \uE046 to stop practicing.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 56, + "text": "To improve your throwing\naccuracy, try { COMMON_FONT_COLOR 01 00 }turning your{ COMMON_FONT_COLOR 00 00 }\n{ COMMON_FONT_COLOR 01 00 }body{ COMMON_FONT_COLOR 00 00 } toward your target.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 57, + "text": "Tilt the disc { COMMON_FONT_COLOR 01 00 }up a little { COMMON_FONT_COLOR 00 00 }when\nyou throw to make it float\nhigher and travel farther.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 58, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 59, + "text": "Once you\u0027ve gotten the knack\nfor throwing the Frisbee, press\n\uE046 to move on to the next step.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 60, + "text": "{ VAR_0 } Hold the Wii Remote securely\nwhile pressing \uE043 to get in a\nthrowing stance.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 61, + "text": "{ VAR_0 } Hold the Wii Remote\nhorizontally and swing your\narm back to take aim.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 62, + "text": "{ VAR_0 } The direction the Frisbee\nflies depends on when you\nrelease \uE043 during your throw.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 63, + "text": "{ VAR_0 } Swing the Wii Remote in an\narc toward the target area and\nrelease \uE043 to let the Frisbee fly.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 80, + "text": "Once you get the hang of each\ntype of Frisbee, press \uE046\nto head out to the course.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 90, + "text": "\u2460", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 91, + "text": "\u2461", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 92, + "text": "\u2462", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45200, + "index": 93, + "text": "\u2463", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45300, + "index": 50, + "text": "Hold the Wii Remote in your\nleft hand and the Nunchuk\nin your right hand.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45300, + "index": 51, + "text": "Hold the Wii Remote upright.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45300, + "index": 52, + "text": "Hold \uE042 to raise your bow.\nRelease \uE042 to lower it.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45300, + "index": 53, + "text": "{ COMMON_FONT_COLOR 01 00 }Hold \uE04B{ COMMON_FONT_COLOR 00 00 } to draw the bow.\nPull the Nunchuk back at\nthe same time to draw faster.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45300, + "index": 54, + "text": "Aim by moving the Wii Remote,\nand { COMMON_FONT_COLOR 01 00 }release \uE04B{ COMMON_FONT_COLOR 00 00 } to shoot\nthe arrow.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45300, + "index": 55, + "text": "Hold the Wii Remote upright, \ntake a deep breath,\nand get ready to shoot.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45300, + "index": 56, + "text": "You lost your focus.\nPress \uE042 to reset your stance.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45400, + "index": 50, + "text": "Tilt the Wii Remote { COMMON_FONT_COLOR 01 00 }down{ COMMON_FONT_COLOR 00 00 } and\npress \uE043 to grab a ball.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45400, + "index": 51, + "text": "Swing the Wii Remote { COMMON_FONT_COLOR 01 00 }in a quick{ COMMON_FONT_COLOR 00 00 }\n{ COMMON_FONT_COLOR 01 00 }motion over your head{ COMMON_FONT_COLOR 00 00 } to jump\nup and shoot.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45400, + "index": 52, + "text": "Just imagine ringing a bell\nright above your head with\nthe Wii Remote. Nice and easy!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45400, + "index": 53, + "text": "Reach down and press \uE043 to\ntake a ball, then quickly swing\nup to jump and shoot!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45400, + "index": 70, + "text": "Once you\u0027re in position,\nyou have 5 seconds\nto take your shot.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45400, + "index": 71, + "text": "Swing the Wii Remote in a\nthrowing motion to shoot\nbefore you hit the ground.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45400, + "index": 72, + "text": "Press \uE043 to get in position\nto shoot before the\nshot clock hits 0.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45450, + "index": 50, + "text": "How to Play Offense\nPress \uE042 or \uE041 to pass the ball\nand start the game.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45450, + "index": 51, + "text": "Move the Wii Remote as if you\nwere dribbling the ball, and\npush the defenders back.{ T05_0000 }\nIf there\u0027s an opening, you can\neven cut past them and get\nright up beneath the basket.{ T05_0000 }\nPress \uE043 when you\u0027re ready\nto shoot.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45450, + "index": 52, + "text": "Press \uE043 to get in position\nto shoot before the\nshot clock hits 0.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45450, + "index": 53, + "text": "Swing the Wii Remote { COMMON_FONT_COLOR 01 00 }over{ COMMON_FONT_COLOR 00 00 }\n{ COMMON_FONT_COLOR 01 00 }your head{ COMMON_FONT_COLOR 00 00 } to jump. Throw the\nball before you hit the ground.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45450, + "index": 54, + "text": "How to Play Defense\nFlick the Wii Remote to try to\nsteal the ball. Just don\u0027t miss!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45450, + "index": 55, + "text": "Swing the Wii Remote { COMMON_FONT_COLOR 01 00 }over{ COMMON_FONT_COLOR 00 00 }\n{ COMMON_FONT_COLOR 01 00 }your head{ COMMON_FONT_COLOR 00 00 } to jump and try to\nblock a shot.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 50, + "text": "Hold the Wii Remote\n{ COMMON_FONT_COLOR 01 00 }in both hands{ COMMON_FONT_COLOR 00 00 }\nwith \uE041 facing toward you.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 51, + "text": "Hold the Wii Remote upright\nin both hands and get\ninto position.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 52, + "text": "Tilt the Wii Remote { COMMON_FONT_COLOR 01 00 }left and{ COMMON_FONT_COLOR 00 00 }\n{ COMMON_FONT_COLOR 01 00 }right{ COMMON_FONT_COLOR 00 00 } to change the position\nof the paddle.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 53, + "text": "Let\u0027s go over how to use the\nWii Remote to control\nthe paddle.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 54, + "text": "{ COMMON_FONT_COLOR 01 00 }Draw the Wii Remote in an arc{ COMMON_FONT_COLOR 00 00 }\n{ COMMON_FONT_COLOR 01 00 }from front to back{ COMMON_FONT_COLOR 00 00 } to pull\nthe paddle through the water.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 55, + "text": "Those are the basic controls.\nNow, just practice until you\nget the hang of it!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 56, + "text": "Alternate paddling on the left\nand right side to go straight.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 57, + "text": "Try to keep your balance and\nmake clean strokes.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 58, + "text": "Paddle on one side to turn in\nthe opposite direction.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 59, + "text": "Go ahead and try it on your\nown. You can paddle all over\nthe lake.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 60, + "text": "Paddle close to the canoe to\ngo forward. Paddle farther\nout to turn.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 61, + "text": "Dip the paddle in the water\nto make subtle adjustments\nto your canoe\u0027s movement.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 70, + "text": "Hold the Wii Remote\n{ COMMON_FONT_COLOR 01 00 }in both hands{ COMMON_FONT_COLOR 00 00 } with \uE041\nfacing you.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 71, + "text": "Hold the Wii Remote upright\nin both hands and get\ninto position.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 72, + "text": "Pull the Wii Remote from\nfront to back to paddle\nthrough the water.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45500, + "index": 80, + "text": "Once you feel comfortable with\nyour canoe, press \uE046 to start\nthe race.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45700, + "index": 50, + "text": "Try not to swing the ball too\nabruptly.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 50, + "text": "Before you get started,\nlet\u0027s go over a few basic\nlessons.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 51, + "text": "Lesson 1: Basics", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 52, + "text": "Hold the Wii Remote pointing\n{ COMMON_FONT_COLOR 01 00 }down{ COMMON_FONT_COLOR 00 00 } as shown and press \uE043.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 53, + "text": "Imagine hitting the ball with\nthe side of the Wii Remote\nand swing the club.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 54, + "text": "Let\u0027s take a practice shot.\nHold \uE042 and take a swing.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 60, + "text": "Lesson 2: Straight Shots{ T05_0000 }\nNext, let\u0027s try hitting a shot\nstraight.{ T05_0000 }\nHitting the ball straight is\na basic--but really important--\ngolf skill, so try your best.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 61, + "text": "To hit a shot straight, try to\navoid making the Swing\nMeter curve.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 62, + "text": "Pay attention to { COMMON_FONT_COLOR 01 00 }the angle{ COMMON_FONT_COLOR 00 00 } of\nyour wrist at the moment you\nstrike the ball.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 63, + "text": "Try not to change your angle in\nbetween when you take your\nstance and swing the club.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 70, + "text": "Let\u0027s take another practice\nshot.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 71, + "text": "Take a golfing stance and\npress \uE043.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 72, + "text": "Hold \uE042 to step up to the ball\nand then swing the club.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 73, + "text": "Uh-oh. Your shot had a little\ncurve on it.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 74, + "text": "Nice one!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 75, + "text": "Keep your stance the same\nall through your swing and\nthe ball should fly straight.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 76, + "text": "Focus on keeping your wrists\nfirm through your swing.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 80, + "text": "Lesson 3: Swing Control{ T05_0000 }\nThe Swing Meter indicates\nthe power of your swing.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 81, + "text": "Try taking a practice shot\nwithout overfilling the\nSwing Meter.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 82, + "text": "That shot could have used a\nlittle more power.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 83, + "text": "Nice shot! Way to go.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 84, + "text": "Try not to swing too hard.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 85, + "text": "The bigger your swing, the\nmore powerful your shot\nwill be.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 86, + "text": "Use the Swing Meter to\nsee how big your swing\nwill be.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 87, + "text": "Don\u0027t swing too hard, or the\nball may stray off target.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 88, + "text": "Here are two final\nthings to remember.{ T05_0000 }\nFirst, make sure you take a\nfew { COMMON_FONT_COLOR 01 00 }practice swings{ COMMON_FONT_COLOR 00 00 } before\neach shot.{ T05_0000 }\nSwinging the Wii Remote\nwithout holding \uE042 lets you\ntake a practice swing.{ T05_0000 }\nWatch the Swing Meter to\nmonitor your swing power.{ T05_0000 }\nAlso, don\u0027t forget to correct\nyour stance before you swing.{ T05_0000 }\nYou can press \uE043 to\nreposition yourself as many\ntimes as you want.{ T05_0000 }\nThe basic rule is to\n{ COMMON_FONT_COLOR 01 00 }position yourself facing\ndown{ COMMON_FONT_COLOR 00 00 } and press \uE043.{ T05_0000 }\nKeep these tips in mind to\nensure straight shots and\nputts.{ T05_0000 }\nOK, now you\u0027re ready to golf\nlike a pro!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45800, + "index": 99, + "text": "Press \uE043 when you\u0027re ready.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 50, + "text": "\u2460 Keep a secure grip on the\nWii Remote.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 51, + "text": "\u2461 Hold the Wii Remote\nhorizontally and draw your\narm back to take aim.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 52, + "text": "\u2462 The direction the Frisbee flies\ndepends on when you snap\nyour wrist during your throw.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 53, + "text": "\u2463 Swing the Wii Remote. The\nFrisbee will be released when\nyou snap your wrist.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 54, + "text": "Change the angle to toss the\nFrisbee in a { COMMON_FONT_COLOR 01 00 }curve{ COMMON_FONT_COLOR 00 00 }. Try\nexperimenting a little!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 55, + "text": "If you can pop balloons and hit\nyour target, you\u0027ve got it down.\nPress \uE046 to stop practicing.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 56, + "text": "To improve your throwing\naccuracy, try { COMMON_FONT_COLOR 01 00 }turning your{ COMMON_FONT_COLOR 00 00 }\n{ COMMON_FONT_COLOR 01 00 }body{ COMMON_FONT_COLOR 00 00 } toward your target.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 57, + "text": "Tilt the disc { COMMON_FONT_COLOR 01 00 }up a little { COMMON_FONT_COLOR 00 00 }when\nyou throw to make it float\nhigher and travel farther.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 60, + "text": "\u2460 Hold the Wii Remote securely\nwhile holding \uE043 to get in\na throwing stance.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 61, + "text": "\u2461 Hold the Wii Remote\nhorizontally and draw your\narm back to take aim.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 62, + "text": "\u2462 The direction the Frisbee\nflies depends on when you\nrelease \uE043 during your throw.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 63, + "text": "\u2463 Swing the Wii Remote in an\narc toward the target and\nrelease \uE043 to let the Frisbee fly.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 45900, + "index": 80, + "text": "Once you get the hang of each\ntype of Frisbee, press \uE046\nto head out to the course.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46000, + "index": 50, + "text": "To ride and control your board,\nhold the Wii Remote with \uE041\nto the left, as shown here.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46000, + "index": 51, + "text": "In wakeboarding, you skim over\nthe water while being towed\nby a boat.{ T05_0000 }\nThe name comes from the\n\u0022{ COMMON_FONT_COLOR 01 00 }wake{ COMMON_FONT_COLOR 00 00 },\u0022 or the { COMMON_FONT_COLOR 01 00 }V-shaped waves{ COMMON_FONT_COLOR 00 00 },\nleft behind by the boat.{ T05_0000 }\nCut through the water and\ncatch air on the wake. Land\nyour jump to earn points!{ T05_0000 }\nLet\u0027s get back to practice.\nRemember to hold the Wii\nRemote horizontally.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46000, + "index": 60, + "text": "Carve over to one side and\nthen quickly turn and cross\nthe wake to pull off a jump.{ T05_0000 }\nFlick the Wii Remote up when\nyou\u0027re on the crest of the\nwake to get big air!{ T05_0000 }\nLet\u0027s get back to some\npractice. Remember to hold\nthe Wii Remote horizontally.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46000, + "index": 70, + "text": "In this sport, the goal is to\nearn points by landing amazing\nhigh-flying tricks!{ T05_0000 }\nMake sure your board is level\nwhen it hits the water, or the\njudges won\u0027t award you points.{ T05_0000 }\nFor now, just try practicing\na little more.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46000, + "index": 80, + "text": "Go far outside the wake and\ncut back hard to build up\nspeed.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46000, + "index": 81, + "text": "Make sure the board is level\nwith the surface of the water\nwhen you land.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46000, + "index": 85, + "text": "Flick the Wii Remote up as\nyou jump the wake to pull off\na trick.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46000, + "index": 86, + "text": "Try to land flat, with the board\nlevel with the surface of\nthe water.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46000, + "index": 90, + "text": "That\u0027s it for your practice run!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46100, + "index": 50, + "text": "\uE042 fires the balloon blaster.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 0, + "text": "Hold the Wii Remote in your\nright hand and the Nunchuk\nin your left hand, { COMMON_FONT_COLOR 01 00 }both upright{ COMMON_FONT_COLOR 00 00 }.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 1, + "text": "Alternate swinging the Wii \nRemote and Nunchuk to pedal.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 2, + "text": "Follow the instructions and\npedal the bike.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 3, + "text": "Once you get up to speed,\nyour bike will continue moving\neven after you stop pedaling.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 4, + "text": "{ COMMON_FONT_COLOR 01 00 }Pedal faster{ COMMON_FONT_COLOR 00 00 } with the\nWii Remote and Nunchuk\nto sprint.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 5, + "text": "If you pedal too hard or for\ntoo long, your Mii\u0027s energy\nlevel will fall.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 6, + "text": "Keep an eye on the hearts at\nthe top of the screen. If they\nrun out, you\u0027ll be { COMMON_FONT_COLOR 01 00 }out of breath{ COMMON_FONT_COLOR 00 00 }.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 7, + "text": "{ COMMON_FONT_COLOR 01 00 }Stop pedaling{ COMMON_FONT_COLOR 00 00 } for a while to\nrecover some of your energy.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 8, + "text": "Recover energy faster by\n{ COMMON_FONT_COLOR 01 00 }drafting behind your\nopponents{ COMMON_FONT_COLOR 00 00 }.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 9, + "text": "{ COMMON_FONT_COLOR 01 00 }Tilt the Wii Remote and the{ COMMON_FONT_COLOR 00 00 }\n{ COMMON_FONT_COLOR 01 00 }Nunchuk{ COMMON_FONT_COLOR 00 00 } left and right to turn\nyour handlebars and steer.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 10, + "text": "{ COMMON_FONT_COLOR 01 00 }Hold \uE04B or \uE043 to brake{ COMMON_FONT_COLOR 00 00 }.\nHold them both at the same\ntime to brake hard.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 11, + "text": "OK, try practicing on your own!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46200, + "index": 12, + "text": "Once you feel comfortable\non your bike, press \uE046 to\nstart the race.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 50, + "text": "Tilt the Wii Remote to move\nyour Mii around in the air and\nchange your direction.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 51, + "text": "Keep your Mii horizontal to\n{ COMMON_FONT_COLOR 01 00 }slow down your fall{ COMMON_FONT_COLOR 00 00 }.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 52, + "text": "Tilt your Mii { COMMON_FONT_COLOR 01 00 }slightly{ COMMON_FONT_COLOR 00 00 } down\nto fly forward.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 53, + "text": "Point your Mii straight down to\nfall really fast.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 54, + "text": "Tilt your Mii { COMMON_FONT_COLOR 01 00 }slightly{ COMMON_FONT_COLOR 00 00 } left and\nright to turn.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 55, + "text": "Try to glide over to other\nMii characters and link arms\nwith them.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 56, + "text": "That\u0027s it for your practice\ndive!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 57, + "text": "Point your Mii toward the Mii\nyou want to link up with and tilt\nforward a little to glide over.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 58, + "text": "Catch as many Mii characters\nas you can. Catch all 4 in a\ngroup to get a Perfect Catch.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 60, + "text": "If you keep your Mii horizontal,\nyou will { COMMON_FONT_COLOR 01 00 }fall more slowly{ COMMON_FONT_COLOR 00 00 }.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 61, + "text": "Tilt down { COMMON_FONT_COLOR 01 00 }just a little{ COMMON_FONT_COLOR 00 00 } to\nglide forward.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 46300, + "index": 62, + "text": "Get close to the Mii characters\naround you to link up!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 50000, + "index": 0, + "text": "Continue", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 50000, + "index": 1, + "text": "Restart", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 50000, + "index": 2, + "text": "Quit", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 50001, + "index": 0, + "text": "Stop Wii MotionPlus Calibration", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 50001, + "index": 1, + "text": "Calibrate Wii MotionPlus Accessory", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 50001, + "index": 2, + "text": "Place the Wii Remote on a\nflat surface and keep it still.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 50001, + "index": 3, + "text": "OK!", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x78 0x00 0xFF" + }, + { + "group": 50001, + "index": 4, + "text": "Checking...", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x78 0x00 0xFF" + }, + { + "group": 50001, + "index": 5, + "text": "Failed", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x78 0x00 0xFF" + }, + { + "group": 50001, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 50001, + "index": 51, + "text": "Place the Wii Remote on a\nflat surface and keep it still.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x00 0x00" + }, + { + "group": 50100, + "index": 0, + "text": "Press \uE042 and \uE043 together.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x86 0x00 0x00" + }, + { + "group": 50100, + "index": 1, + "text": "2009 Nintendo", + "attributes": "0x0000004B", + "ex_attributes": "0x00 0xA0 0x00 0x00" + }, + { + "group": 50100, + "index": 2, + "text": "\uE042", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x1D 0x00 0x00" + }, + { + "group": 50100, + "index": 3, + "text": "\uE043", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x1D 0x00 0x00" + }, + { + "group": 50100, + "index": 4, + "text": "Instructional\nVideo", + "attributes": "0x0000004B", + "ex_attributes": "0x00 0x64 0x00 0xFE" + }, + { + "group": 50101, + "index": 0, + "text": "Instructional\nVideo", + "attributes": "0x0000004B", + "ex_attributes": "0x00 0x64 0x00 0xFE" + }, + { + "group": 50110, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xB8 0x00 0xFF" + }, + { + "group": 50110, + "index": 51, + "text": "{ VAR_0 }\u3000{ VAR_0 }", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x04 0x00 0x00" + }, + { + "group": 50110, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x04 0x00 0x00" + }, + { + "group": 50202, + "index": 0, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 50204, + "index": 50, + "text": "", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x5E 0x00 0xFF" + }, + { + "group": 50205, + "index": 0, + "text": "Back", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xDC 0x00 0xFE" + }, + { + "group": 50206, + "index": 0, + "text": "Settings", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x74 0x00 0xFE" + }, + { + "group": 50209, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xBE 0x00 0xFE" + }, + { + "group": 50210, + "index": 0, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 50210, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50211, + "index": 0, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 50211, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50212, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 50212, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50213, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 50213, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50214, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 50214, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50215, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 50215, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50216, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 50216, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50217, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 50217, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50218, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 50218, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50219, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 50219, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50220, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50221, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50222, + "index": 50, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xFA 0x00 0xFE" + }, + { + "group": 50222, + "index": 51, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xFA 0x00 0xFE" + }, + { + "group": 50222, + "index": 52, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xFA 0x00 0xFE" + }, + { + "group": 50223, + "index": 0, + "text": "\uFF1F", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x79 0x01 0x00" + }, + { + "group": 50240, + "index": 0, + "text": "OK", + "attributes": "0x00000037", + "ex_attributes": "0x00 0x74 0x01 0xFE" + }, + { + "group": 50240, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0x54 0x01 0xFE" + }, + { + "group": 50240, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x00 0xFF" + }, + { + "group": 50240, + "index": 60, + "text": "1-player game", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 50240, + "index": 61, + "text": "Up to 2 players", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 50240, + "index": 62, + "text": "Up to 3 players", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 50240, + "index": 63, + "text": "Up to 4 players", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 50240, + "index": 64, + "text": "2-player game", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 50240, + "index": 65, + "text": "2 to 4 players", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 50241, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 50241, + "index": 1, + "text": "?", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x50 0x01 0xFE" + }, + { + "group": 50241, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0x5E 0x01 0x00" + }, + { + "group": 50243, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 50243, + "index": 51, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xB1 0x00 0xFF" + }, + { + "group": 50244, + "index": 50, + "text": "Change Player List", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xC8 0x01 0xFE" + }, + { + "group": 50244, + "index": 51, + "text": "Import from Check Mii Out Channel", + "attributes": "0x00000028", + "ex_attributes": "0x01 0xC8 0x01 0xFE" + }, + { + "group": 50244, + "index": 52, + "text": "ENABLED", + "attributes": "0x0000002D", + "ex_attributes": "0x01 0xC8 0x01 0xFE" + }, + { + "group": 50244, + "index": 53, + "text": "DISABLED", + "attributes": "0x0000002D", + "ex_attributes": "0x01 0xC8 0x01 0xFE" + }, + { + "group": 50244, + "index": 54, + "text": "Sensor Bar Assist", + "attributes": "0x00000028", + "ex_attributes": "0x01 0xC8 0x01 0xFE" + }, + { + "group": 50244, + "index": 55, + "text": "ENABLED", + "attributes": "0x0000002D", + "ex_attributes": "0x01 0xC8 0x01 0xFE" + }, + { + "group": 50244, + "index": 56, + "text": "DISABLED", + "attributes": "0x0000002D", + "ex_attributes": "0x01 0xC8 0x01 0xFE" + }, + { + "group": 50245, + "index": 0, + "text": "Settings", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x04 0x00 0xFF" + }, + { + "group": 50250, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x74 0x00 0xFE" + }, + { + "group": 50250, + "index": 1, + "text": "Most Popular", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x74 0x00 0xFE" + }, + { + "group": 50250, + "index": 2, + "text": "Recommended", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x74 0x00 0xFE" + }, + { + "group": 50300, + "index": 50, + "text": "\uE043 Back", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 50300, + "index": 51, + "text": "\uE043 Main Menu", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 50300, + "index": 52, + "text": "\uE043 Players", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 50300, + "index": 53, + "text": "\uE043 Settings", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 50300, + "index": 54, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 50400, + "index": 50, + "text": "Select Players", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x02" + }, + { + "group": 50400, + "index": 51, + "text": "Select a Mii", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x02" + }, + { + "group": 50400, + "index": 52, + "text": "Playing Style", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x02" + }, + { + "group": 50400, + "index": 53, + "text": "Select a Mii", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x02" + }, + { + "group": 50400, + "index": 54, + "text": "Select a Playing Style", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x02" + }, + { + "group": 50400, + "index": 55, + "text": "Confirm Team", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x02" + }, + { + "group": 50400, + "index": 56, + "text": "Select a New Mii", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x22 0x00 0xFF" + }, + { + "group": 50400, + "index": 57, + "text": "Select a Mii to Delete", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x02" + }, + { + "group": 50400, + "index": 58, + "text": "Select a Stage", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x02" + }, + { + "group": 50400, + "index": 59, + "text": "Select a Mii\nfor Player 1", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x22 0x00 0xFF" + }, + { + "group": 50400, + "index": 60, + "text": "Select a Mii\nfor Player 2", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x22 0x00 0xFF" + }, + { + "group": 50400, + "index": 61, + "text": "Select a Mii\nfor Player 3", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x22 0x00 0xFF" + }, + { + "group": 50400, + "index": 62, + "text": "Select a Mii\nfor Player 4", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x22 0x00 0xFF" + }, + { + "group": 50400, + "index": 63, + "text": "Number of Holes", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x22 0x00 0xFF" + }, + { + "group": 50400, + "index": 64, + "text": "Select Course", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x00" + }, + { + "group": 50400, + "index": 65, + "text": "Select Difficulty", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x00" + }, + { + "group": 50400, + "index": 66, + "text": "Select Race", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x00" + }, + { + "group": 50400, + "index": 67, + "text": "Select Course", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x00" + }, + { + "group": 50400, + "index": 68, + "text": "Select Stage", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x00" + }, + { + "group": 50400, + "index": 69, + "text": "Select Time of Day", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x00" + }, + { + "group": 50400, + "index": 70, + "text": "Choose a Race", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x00" + }, + { + "group": 50400, + "index": 98, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x22 0x00 0x00" + }, + { + "group": 50400, + "index": 99, + "text": "{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x22 0x00 0xFF" + }, + { + "group": 51000, + "index": 0, + "text": "1 player", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51000, + "index": 1, + "text": "2 players", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51000, + "index": 2, + "text": "3 players", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51000, + "index": 3, + "text": "4 players", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51000, + "index": 4, + "text": "1 player", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51000, + "index": 5, + "text": "2 players", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51002, + "index": 50, + "text": "1 player", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x8C 0x01 0xFE" + }, + { + "group": 51002, + "index": 51, + "text": "2 players", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x8C 0x01 0xFE" + }, + { + "group": 51003, + "index": 50, + "text": "1 player", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x8C 0x01 0xFE" + }, + { + "group": 51003, + "index": 51, + "text": "2 players", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x8C 0x01 0xFE" + }, + { + "group": 51003, + "index": 52, + "text": "3 players", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x8C 0x01 0xFE" + }, + { + "group": 51003, + "index": 53, + "text": "4 players", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x8C 0x01 0xFE" + }, + { + "group": 51004, + "index": 0, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF5 0x01 0xFE" + }, + { + "group": 51005, + "index": 0, + "text": "OK!", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x57 0x01 0xFF" + }, + { + "group": 51005, + "index": 1, + "text": "?", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x25 0x01 0xFF" + }, + { + "group": 51006, + "index": 50, + "text": "The Wii MotionPlus accessory\nis not connected properly.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 51, + "text": "This mode requires { VAR_0 } Wii Remotes\nwith Wii MotionPlus accessories.\n\nPlease go to the \uE044 HOME Menu\nto add a Wii Remote.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 52, + "text": "This game requires a Wii Remote\nwith a Wii MotionPlus accessory.\n\nPlease go to the \uE044 HOME Menu\nto reconnect your Wii Remote.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 53, + "text": "One or more Wii Remotes\ndo not have Wii MotionPlus\naccessories attached.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 54, + "text": "Play with { VAR_0 } Wii Remote?", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 55, + "text": "Play with { VAR_0 } Wii Remotes?", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 60, + "text": "The Wii MotionPlus accessory\nand the Nunchuk are not\nproperly connected.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 61, + "text": "This mode requires { VAR_0 } Wii Remotes\nwith Wii MotionPlus\naccessories and Nunchuks.\nPlease go to the \uE044 HOME Menu\nto add a Wii Remote.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 62, + "text": "This mode requires a Wii Remote\nwith a Wii MotionPlus accessory\nand a Nunchuk.\nPlease go to the \uE044 HOME Menu\nto reconnect your Wii Remote.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 63, + "text": "The Wii MotionPlus accessories\nand Nunchuks are not properly\nconnected on all Wii Remotes.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 64, + "text": "Play with { VAR_0 } Wii Remote?", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51006, + "index": 65, + "text": "Play with { VAR_0 } Wii Remotes?", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51007, + "index": 50, + "text": "Back", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51007, + "index": 51, + "text": "Play", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51011, + "index": 0, + "text": "OK!", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x78 0x01 0xFF" + }, + { + "group": 51011, + "index": 1, + "text": "?", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x2D 0x01 0xFF" + }, + { + "group": 51013, + "index": 0, + "text": "Add players", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 51014, + "index": 0, + "text": "Go to Wii Remote Settings\nin the \uE044 HOME Menu\nto connect your Wii Remote.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 51100, + "index": 0, + "text": "OK!", + "attributes": "0x00000037", + "ex_attributes": "0x00 0x51 0x01 0xFF" + }, + { + "group": 51100, + "index": 50, + "text": "Connect the Nunchuk\nto the Wii MotionPlus\naccessory.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x22 0x00 0xFE" + }, + { + "group": 51100, + "index": 51, + "text": "Disconnect the extension\ncontroller from the\nWii MotionPlus accessory. ", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x22 0x00 0xFE" + }, + { + "group": 51100, + "index": 52, + "text": "Connect the\nWii MotionPlus\naccessory to the\nWii Remote.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x22 0x00 0xFE" + }, + { + "group": 51100, + "index": 53, + "text": "Please disconnect all\nexternal extension controllers\nexcept the Nunchuk from the\nWii MotionPlus accessory.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x22 0x00 0xFE" + }, + { + "group": 51201, + "index": 0, + "text": "Wii Console", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51201, + "index": 1, + "text": "Guest", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51202, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x96 0x00 0xFF" + }, + { + "group": 51202, + "index": 51, + "text": "Change Mii", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x96 0x00 0xFF" + }, + { + "group": 51202, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x96 0x00 0xFF" + }, + { + "group": 51203, + "index": 50, + "text": "1", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x45 0x00 0x00" + }, + { + "group": 51203, + "index": 51, + "text": "2", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x45 0x00 0x00" + }, + { + "group": 51203, + "index": 52, + "text": "3", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x45 0x00 0x00" + }, + { + "group": 51203, + "index": 53, + "text": "4", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x45 0x00 0x00" + }, + { + "group": 51205, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xC8 0x00 0x00" + }, + { + "group": 51207, + "index": 50, + "text": "", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 51, + "text": "", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 52, + "text": "", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 53, + "text": "", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 54, + "text": "Left-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 55, + "text": "Right-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 56, + "text": "Left-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 57, + "text": "Right-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 58, + "text": "Left-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 59, + "text": "Right-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 60, + "text": "", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 61, + "text": "", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 62, + "text": "", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51207, + "index": 63, + "text": "", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51209, + "index": 50, + "text": "Change Mii", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51209, + "index": 51, + "text": "OK", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51211, + "index": 0, + "text": "Throwing Style", + "attributes": "0x00000028", + "ex_attributes": "0x00 0xBE 0x01 0xFE" + }, + { + "group": 51211, + "index": 50, + "text": "Automatic", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0xBE 0x01 0xFE" + }, + { + "group": 51211, + "index": 51, + "text": "Manual", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0xBE 0x01 0xFE" + }, + { + "group": 51212, + "index": 56, + "text": "Left-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51212, + "index": 57, + "text": "Right-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51212, + "index": 60, + "text": "Left-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51212, + "index": 61, + "text": "Right-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51212, + "index": 62, + "text": "Left-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51212, + "index": 63, + "text": "Right-handed", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51213, + "index": 0, + "text": "Change Throwing Style", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x18 0x00 0x00" + }, + { + "group": 51300, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xBE 0x00 0xFE" + }, + { + "group": 51302, + "index": 50, + "text": "Solo", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51302, + "index": 51, + "text": "Team", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51400, + "index": 0, + "text": "VS", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x6E 0x01 0x00" + }, + { + "group": 51400, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xBE 0x00 0xFE" + }, + { + "group": 51401, + "index": 50, + "text": "Change Team", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51401, + "index": 51, + "text": "OK", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51500, + "index": 0, + "text": "Start\n\nHold the Wii Remote\nand press \uE042 and \uE043.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x27 0x00 0xFE" + }, + { + "group": 51500, + "index": 1, + "text": "\uFF2F\uFF2B\uFF01", + "attributes": "0x00000037", + "ex_attributes": "0x00 0x51 0x01 0xFC" + }, + { + "group": 51500, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xC0 0x00 0xFE" + }, + { + "group": 51600, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 51600, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 51601, + "index": 50, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 51601, + "index": 51, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 51601, + "index": 52, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 51602, + "index": 50, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 51602, + "index": 51, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 51602, + "index": 52, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 51602, + "index": 53, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xA4 0x01 0x01" + }, + { + "group": 51603, + "index": 50, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xE6 0x01 0x01" + }, + { + "group": 51603, + "index": 51, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xE6 0x01 0x01" + }, + { + "group": 51603, + "index": 52, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xE6 0x01 0x01" + }, + { + "group": 51603, + "index": 53, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xE6 0x01 0x01" + }, + { + "group": 51603, + "index": 54, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xE6 0x01 0x01" + }, + { + "group": 51603, + "index": 55, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xE6 0x01 0x01" + }, + { + "group": 51604, + "index": 0, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF5 0x00 0xFE" + }, + { + "group": 51605, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 51605, + "index": 1, + "text": "?", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x50 0x01 0xFE" + }, + { + "group": 51605, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000037", + "ex_attributes": "0x01 0xA4 0x01 0xFE" + }, + { + "group": 51606, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 51606, + "index": 1, + "text": "?", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x50 0x01 0xFE" + }, + { + "group": 51606, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51607, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 51607, + "index": 1, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x50 0x01 0xFE" + }, + { + "group": 51607, + "index": 50, + "text": "", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51609, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 51609, + "index": 1, + "text": "?", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x50 0x01 0xFE" + }, + { + "group": 51609, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000037", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 51610, + "index": 50, + "text": "Normal", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51610, + "index": 51, + "text": "Reverse", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 51611, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 51613, + "index": 0, + "text": "NEW", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 51613, + "index": 1, + "text": "?", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x50 0x01 0xFE" + }, + { + "group": 52000, + "index": 0, + "text": "Why not take a break?\nYou can pause the game\nat any time by pressing \uE045.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 52001, + "index": 0, + "text": "Keep a secure grip on the\nWii Remote, and watch out for \npeople and objects around you.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 52002, + "index": 0, + "text": "If the Wii Remote is not\nresponding normally during\nplay, place it on a flat\nsurface and keep it still.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 52003, + "index": 0, + "text": "Press \uE045 to pause the\ngame and recalibrate the\nWii MotionPlus accessory.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 53000, + "index": 50, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 53000, + "index": 51, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 53001, + "index": 50, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 53001, + "index": 51, + "text": "OK", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 53002, + "index": 50, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 53002, + "index": 51, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 53101, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53102, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53106, + "index": 0, + "text": "Change Mii", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xB5 0x00 0xFE" + }, + { + "group": 53106, + "index": 1, + "text": "Mii", + "attributes": "0x00000069", + "ex_attributes": "0x00 0x32 0x00 0xFF" + }, + { + "group": 53500, + "index": 0, + "text": "Play Again", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53500, + "index": 1, + "text": "Change Course", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53500, + "index": 2, + "text": "Change Settings", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53500, + "index": 3, + "text": "Quit", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53501, + "index": 0, + "text": "Next Stage", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53501, + "index": 1, + "text": "Change Stage", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53501, + "index": 2, + "text": "Change Settings", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53501, + "index": 3, + "text": "Quit", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53502, + "index": 0, + "text": "Play Again", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53502, + "index": 1, + "text": "Change Difficulty", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53502, + "index": 2, + "text": "Change Settings", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53502, + "index": 3, + "text": "Quit", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53503, + "index": 0, + "text": "Play Again", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53503, + "index": 1, + "text": "Change Course", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53503, + "index": 2, + "text": "Change Settings", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53503, + "index": 3, + "text": "Quit", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53504, + "index": 0, + "text": "Play Again", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53504, + "index": 1, + "text": "Change Race", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53504, + "index": 2, + "text": "Change Settings", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53504, + "index": 3, + "text": "Quit", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53505, + "index": 0, + "text": "Play Again", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53505, + "index": 1, + "text": "Change Time of Day", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xAE 0x01 0xFE" + }, + { + "group": 53505, + "index": 2, + "text": "Change Settings", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 53505, + "index": 3, + "text": "Quit", + "attributes": "0x00000037", + "ex_attributes": "0x01 0x45 0x01 0xFE" + }, + { + "group": 60200, + "index": 0, + "text": "Best", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x5F 0x00 0x00" + }, + { + "group": 60200, + "index": 1, + "text": "Level", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x5F 0x00 0x00" + }, + { + "group": 60200, + "index": 2, + "text": "---", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x8C 0x00 0xFE" + }, + { + "group": 60200, + "index": 3, + "text": "Stamps", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 60200, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x91 0x00 0xFE" + }, + { + "group": 60200, + "index": 51, + "text": "{ VAR_0 } { VAR_2 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x8C 0x00 0xFE" + }, + { + "group": 60200, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60201, + "index": 1, + "text": "Level", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xA0 0x00 0xFE" + }, + { + "group": 60201, + "index": 3, + "text": "Stamps", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xA0 0x00 0xFE" + }, + { + "group": 60201, + "index": 4, + "text": "\u332B Points Found", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xBE 0x00 0xFE" + }, + { + "group": 60201, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 60201, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x78 0x00 0xFE" + }, + { + "group": 60201, + "index": 53, + "text": "---", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x78 0x00 0xFE" + }, + { + "group": 60201, + "index": 54, + "text": "{ VAR_0 }/80", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x78 0x00 0xFE" + }, + { + "group": 60300, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 60301, + "index": 0, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 60301, + "index": 1, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 60301, + "index": 50, + "text": "", + "attributes": "0x00000069", + "ex_attributes": "0x00 0xAF 0x00 0xFE" + }, + { + "group": 60301, + "index": 51, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x8C 0x00 0x00" + }, + { + "group": 60301, + "index": 52, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 60310, + "index": 0, + "text": "Level", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 60310, + "index": 1, + "text": "Champion", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 60310, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000069", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 60310, + "index": 51, + "text": "{ VAR_0 } { VAR_2 }", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x8C 0x00 0x00" + }, + { + "group": 60310, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60311, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 60320, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xAF 0x00 0xFE" + }, + { + "group": 60330, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xF5 0x00 0xFF" + }, + { + "group": 60350, + "index": 0, + "text": "Stamps", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xB5 0x00 0xFE" + }, + { + "group": 60352, + "index": 0, + "text": "\uE043 Close", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x04 0x00 0xFE" + }, + { + "group": 60354, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x6E 0x00 0xFE" + }, + { + "group": 60354, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x31 0x00 0xFE" + }, + { + "group": 60355, + "index": 0, + "text": "Stamps", + "attributes": "0x00000028", + "ex_attributes": "0x00 0x93 0x01 0xFE" + }, + { + "group": 60355, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x93 0x01 0xFE" + }, + { + "group": 60400, + "index": 0, + "text": "Record", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x76 0x00 0xFE" + }, + { + "group": 60400, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000082", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 60400, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x78 0x00 0xFF" + }, + { + "group": 60400, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 60401, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000082", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 60401, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000078", + "ex_attributes": "0x00 0xF0 0x00 0xFE" + }, + { + "group": 60401, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x0000008C", + "ex_attributes": "0x00 0xF0 0x00 0x00" + }, + { + "group": 60402, + "index": 0, + "text": "Score", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 60402, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xA5 0x00 0xFE" + }, + { + "group": 60402, + "index": 51, + "text": "{ VAR_0 } { VAR_2 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xC8 0x00 0xFF" + }, + { + "group": 60403, + "index": 5, + "text": "High Score", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xDE 0x00 0xFE" + }, + { + "group": 60403, + "index": 6, + "text": "Current Rankings", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xDE 0x00 0xFE" + }, + { + "group": 60403, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x89 0x00 0xFE" + }, + { + "group": 60403, + "index": 51, + "text": "{ VAR_0 } { VAR_2 }", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xAF 0x00 0xFD" + }, + { + "group": 60403, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x27 0x01 0x00" + }, + { + "group": 60500, + "index": 0, + "text": "Hearts Left", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x91 0x00 0xFE" + }, + { + "group": 60500, + "index": 1, + "text": "Best Combo", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x91 0x00 0xFE" + }, + { + "group": 60500, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xA3 0x00 0xFE" + }, + { + "group": 60500, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x3C 0x00 0xFE" + }, + { + "group": 60520, + "index": 50, + "text": "{ VAR_0 } { VAR_2 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x48 0x00 0xFE" + }, + { + "group": 60520, + "index": 51, + "text": "{ VAR_2 }", + "attributes": "0x0000004B", + "ex_attributes": "0x00 0x29 0x00 0xFE" + }, + { + "group": 60530, + "index": 0, + "text": "1", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x20 0x00 0x00" + }, + { + "group": 60530, + "index": 1, + "text": "2", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x20 0x00 0x00" + }, + { + "group": 60530, + "index": 2, + "text": "3", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x20 0x00 0x00" + }, + { + "group": 60530, + "index": 3, + "text": "F", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 60530, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x41 0x00 0xFE" + }, + { + "group": 60530, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x32 0x00 0xFF" + }, + { + "group": 60530, + "index": 52, + "text": "{ VAR_2 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x2A 0x00 0x02" + }, + { + "group": 60530, + "index": 53, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x28 0x00 0xFF" + }, + { + "group": 60540, + "index": 0, + "text": "\uFF582", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x28 0x00 0xFC" + }, + { + "group": 60540, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xAA 0x00 0x00" + }, + { + "group": 60540, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x4B 0x00 0xFF" + }, + { + "group": 60540, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x23 0x00 0xFF" + }, + { + "group": 60540, + "index": 53, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x34 0x00 0xFF" + }, + { + "group": 60560, + "index": 0, + "text": "Position:", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 60560, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x50 0x01 0xFF" + }, + { + "group": 60561, + "index": 0, + "text": "Time", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0x00" + }, + { + "group": 60561, + "index": 1, + "text": "Excellent", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x86 0x00 0x00" + }, + { + "group": 60561, + "index": 2, + "text": "Nice", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x86 0x00 0x00" + }, + { + "group": 60561, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xFA 0x00 0xFE" + }, + { + "group": 60562, + "index": 0, + "text": "Place", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60562, + "index": 1, + "text": "Time", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x78 0x00 0xFE" + }, + { + "group": 60562, + "index": 2, + "text": "Day 1", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60562, + "index": 3, + "text": "Day 2", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60562, + "index": 4, + "text": "Day 3", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60562, + "index": 5, + "text": "Day 5", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60562, + "index": 6, + "text": "Day 6", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60562, + "index": 7, + "text": "Result", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60562, + "index": 8, + "text": "Result", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60562, + "index": 9, + "text": "Personal Best", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x78 0x00 0xFE" + }, + { + "group": 60562, + "index": 50, + "text": "Day 4", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60562, + "index": 51, + "text": "Results", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 60562, + "index": 60, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x55 0x00 0xFF" + }, + { + "group": 60562, + "index": 61, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x82 0x00 0xFE" + }, + { + "group": 60600, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x8C 0x00 0xFE" + }, + { + "group": 60600, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 60600, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x41 0x00 0xFE" + }, + { + "group": 60601, + "index": 0, + "text": "Level", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x2C 0x01 0x00" + }, + { + "group": 60601, + "index": 1, + "text": "1000", + "attributes": "0x00000041", + "ex_attributes": "0x00 0x41 0x00 0x02" + }, + { + "group": 60601, + "index": 2, + "text": "2000", + "attributes": "0x00000041", + "ex_attributes": "0x00 0x41 0x00 0x02" + }, + { + "group": 60601, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000041", + "ex_attributes": "0x00 0x41 0x00 0x02" + }, + { + "group": 61000, + "index": 0, + "text": "START", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x52 0x01 0x00" + }, + { + "group": 61000, + "index": 1, + "text": "\uFF11", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 61000, + "index": 2, + "text": "\uFF12", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 61000, + "index": 3, + "text": "\uFF13", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 61002, + "index": 0, + "text": "-", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x96 0x01 0x00" + }, + { + "group": 61002, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x96 0x01 0x00" + }, + { + "group": 61100, + "index": 50, + "text": "Start", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61100, + "index": 51, + "text": "Finish", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61100, + "index": 52, + "text": "Switch player", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61100, + "index": 53, + "text": "Game up", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61101, + "index": 50, + "text": "Goal", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61101, + "index": 51, + "text": "Time\u0027s Up!", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61101, + "index": 52, + "text": "{ VAR_0 } { VAR_2 } to goal", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61101, + "index": 53, + "text": "Test your limits!", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61102, + "index": 52, + "text": "Time\u0027s Up!", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61102, + "index": 53, + "text": "Play", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61103, + "index": 50, + "text": "Balloon Challenge", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61104, + "index": 50, + "text": "{ VAR_0 } Place", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61104, + "index": 51, + "text": "Time\u0027s Up!", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61105, + "index": 50, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61106, + "index": 50, + "text": "Next Stage", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61107, + "index": 50, + "text": "Form up!", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61107, + "index": 51, + "text": "Results", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x08 0x01 0xFE" + }, + { + "group": 61200, + "index": 0, + "text": "Replay", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x7E 0x00 0xFE" + }, + { + "group": 61301, + "index": 50, + "text": "\uFF5ERecentering Your Sword\uFF5E\n\nIf your sword\u0027s position feels off\nor has shifted during play, point\nthe Wii Remote at the screen\nand press down on \uE041 to center it.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 61301, + "index": 51, + "text": "\uFF5ERecentering Your Paddle\uFF5E\n\nIf your paddle\u0027s position feels off\nor has shifted during play, point\nthe Wii Remote at the screen\nand press down on \uE041 to center it.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 61400, + "index": 50, + "text": "Practice", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61400, + "index": 51, + "text": "Quit Practice", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61400, + "index": 52, + "text": "Practice", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61400, + "index": 53, + "text": "Free Cruising", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61400, + "index": 54, + "text": "Start Race", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61400, + "index": 55, + "text": "Free Cruising", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61400, + "index": 56, + "text": "Start Contest", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61400, + "index": 57, + "text": "Change Plane", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC3 0x00 0xFE" + }, + { + "group": 61400, + "index": 58, + "text": "Next Step", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61400, + "index": 59, + "text": "Free Practice", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61400, + "index": 60, + "text": "Free Practice", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61450, + "index": 0, + "text": "Skip", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 61500, + "index": 0, + "text": "Give it a try!", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 61501, + "index": 0, + "text": "OK", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xC8 0x01 0x00" + }, + { + "group": 61501, + "index": 50, + "text": "Point the Wii Remote at the\nscreen and press \uE042.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFF" + }, + { + "group": 61600, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xC6 0x00 0xFE" + }, + { + "group": 61600, + "index": 60, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 61600, + "index": 61, + "text": "Hole { VAR_0 }: Par { VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 61600, + "index": 62, + "text": "Stage { VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 61600, + "index": 63, + "text": "Final Stage", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 63001, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x2C 0x00 0xFC" + }, + { + "group": 63002, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 63003, + "index": 0, + "text": "1", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x28 0x00 0xFD" + }, + { + "group": 63003, + "index": 1, + "text": "2", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x28 0x00 0xFD" + }, + { + "group": 63003, + "index": 2, + "text": "3", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x28 0x00 0xFD" + }, + { + "group": 63003, + "index": 3, + "text": "4", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x28 0x00 0xFD" + }, + { + "group": 63003, + "index": 4, + "text": "5", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x28 0x00 0xFD" + }, + { + "group": 63003, + "index": 5, + "text": "6", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x28 0x00 0xFD" + }, + { + "group": 63003, + "index": 6, + "text": "7", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x28 0x00 0xFD" + }, + { + "group": 63003, + "index": 7, + "text": "8", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x28 0x00 0xFD" + }, + { + "group": 63003, + "index": 8, + "text": "9", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x28 0x00 0xFD" + }, + { + "group": 63003, + "index": 9, + "text": "10", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x2A 0x00 0xF9" + }, + { + "group": 63003, + "index": 10, + "text": "Checkpoint", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 63004, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x2C 0x00 0xFC" + }, + { + "group": 65000, + "index": 0, + "text": "", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65000, + "index": 50, + "text": "Fight!", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65000, + "index": 51, + "text": "Start!", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65000, + "index": 52, + "text": "Go!", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65001, + "index": 0, + "text": "Ready", + "attributes": "0x00000078", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65002, + "index": 0, + "text": "", + "attributes": "0x00000078", + "ex_attributes": "0x01 0xF4 0x01 0x01" + }, + { + "group": 65003, + "index": 0, + "text": "Round 1", + "attributes": "0x00000078", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65003, + "index": 1, + "text": "Round 2", + "attributes": "0x00000078", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65003, + "index": 2, + "text": "Round 3", + "attributes": "0x00000078", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65003, + "index": 3, + "text": "Final Round", + "attributes": "0x00000078", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65004, + "index": 0, + "text": "", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65004, + "index": 50, + "text": "Round Over", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65004, + "index": 51, + "text": "Finish", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65004, + "index": 52, + "text": "Finish", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65005, + "index": 0, + "text": "Stop", + "attributes": "0x00000082", + "ex_attributes": "0x01 0x54 0x01 0x00" + }, + { + "group": 65005, + "index": 1, + "text": "\uFF11", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65005, + "index": 2, + "text": "\uFF12", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65005, + "index": 3, + "text": "\uFF13", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65005, + "index": 4, + "text": "\uFF14", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65005, + "index": 5, + "text": "\uFF15", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65005, + "index": 6, + "text": "\uFF16", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65005, + "index": 7, + "text": "\uFF17", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65005, + "index": 8, + "text": "\uFF18", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65005, + "index": 9, + "text": "\uFF19", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65005, + "index": 10, + "text": "\uFF11\uFF10", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0xF8" + }, + { + "group": 65007, + "index": 0, + "text": "1", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65007, + "index": 1, + "text": "2", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65007, + "index": 2, + "text": "3", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65007, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000055", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 65008, + "index": 0, + "text": "\uFF11", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65008, + "index": 1, + "text": "\uFF12", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65008, + "index": 2, + "text": "\uFF13", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65008, + "index": 3, + "text": "\uFF26", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 65009, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFF" + }, + { + "group": 65009, + "index": 1, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xC8 0x01 0xFE" + }, + { + "group": 65009, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xC8 0x01 0x00" + }, + { + "group": 65011, + "index": 0, + "text": "Watch out!", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xFA 0x01 0xFE" + }, + { + "group": 65020, + "index": 0, + "text": "Score", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x5A 0x00 0xFE" + }, + { + "group": 65020, + "index": 1, + "text": "\uFF05", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x1E 0x00 0xFE" + }, + { + "group": 65020, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x50 0x01 0xFF" + }, + { + "group": 65021, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x7F 0x00 0xFF" + }, + { + "group": 65023, + "index": 50, + "text": "{ VAR_0 }-hit Combo!", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xF4 0x01 0xFD" + }, + { + "group": 65024, + "index": 50, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 65024, + "index": 51, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65024, + "index": 52, + "text": "Stage { VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 65024, + "index": 53, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xDC 0x01 0xFE" + }, + { + "group": 65025, + "index": 50, + "text": "Stage Cleared", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x5E 0x01 0x01" + }, + { + "group": 65025, + "index": 52, + "text": "Score { VAR_0 }\uFF05", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x5E 0x01 0x01" + }, + { + "group": 65030, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000055", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 65031, + "index": 0, + "text": "1", + "attributes": "0x000000A0", + "ex_attributes": "0x00 0x96 0x01 0x00" + }, + { + "group": 65031, + "index": 1, + "text": "2", + "attributes": "0x000000A0", + "ex_attributes": "0x00 0x96 0x01 0x00" + }, + { + "group": 65031, + "index": 2, + "text": "3", + "attributes": "0x000000A0", + "ex_attributes": "0x00 0x96 0x01 0x00" + }, + { + "group": 65033, + "index": 0, + "text": "Match Point", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x7C 0x01 0xFE" + }, + { + "group": 65050, + "index": 0, + "text": "Practice", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x8C 0x00 0xFE" + }, + { + "group": 65051, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000055", + "ex_attributes": "0x00 0x9B 0x00 0x00" + }, + { + "group": 65051, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x64 0x01 0x00" + }, + { + "group": 65100, + "index": 50, + "text": " { VAR_2 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x2D 0x00 0xFE" + }, + { + "group": 65100, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x6E 0x01 0xFF" + }, + { + "group": 65101, + "index": 50, + "text": "\u002B{ VAR_0 }", + "attributes": "0x0000008C", + "ex_attributes": "0x00 0xC8 0x01 0x01" + }, + { + "group": 65101, + "index": 51, + "text": ".", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x24 0x01 0x00" + }, + { + "group": 65101, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xC8 0x01 0x00" + }, + { + "group": 65102, + "index": 0, + "text": "Finish", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x52 0x01 0xFD" + }, + { + "group": 65104, + "index": 1, + "text": "\uFF11", + "attributes": "0x000000A0", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65104, + "index": 2, + "text": "\uFF12", + "attributes": "0x000000A0", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65104, + "index": 3, + "text": "\uFF13", + "attributes": "0x000000A0", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65104, + "index": 50, + "text": "Get back on the course!", + "attributes": "0x0000008C", + "ex_attributes": "0x02 0x1C 0x00 0x00" + }, + { + "group": 65104, + "index": 51, + "text": "Wrong way!", + "attributes": "0x0000008C", + "ex_attributes": "0x02 0x1C 0x00 0x00" + }, + { + "group": 65104, + "index": 52, + "text": "Face the course!", + "attributes": "0x0000008C", + "ex_attributes": "0x02 0x1C 0x00 0x00" + }, + { + "group": 65107, + "index": 0, + "text": "Finished", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x54 0x01 0x00" + }, + { + "group": 65107, + "index": 1, + "text": "1", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65107, + "index": 2, + "text": "2", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65107, + "index": 3, + "text": "3", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65107, + "index": 4, + "text": "4", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65107, + "index": 5, + "text": "5", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65107, + "index": 6, + "text": "6", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65107, + "index": 7, + "text": "7", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65107, + "index": 8, + "text": "8", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65107, + "index": 9, + "text": "9", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65107, + "index": 10, + "text": "10", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x01 0xF8" + }, + { + "group": 65108, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x4F 0x00 0xFE" + }, + { + "group": 65109, + "index": 0, + "text": "Time", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 65109, + "index": 50, + "text": "\u002B{ VAR_0 }", + "attributes": "0x00000078", + "ex_attributes": "0x00 0xC8 0x01 0x01" + }, + { + "group": 65109, + "index": 51, + "text": "{ VAR_2 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xC8 0x01 0x00" + }, + { + "group": 65120, + "index": 0, + "text": "x2", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xC8 0x01 0x00" + }, + { + "group": 65121, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xD2 0x01 0xFF" + }, + { + "group": 65121, + "index": 51, + "text": "{ VAR_2 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xED 0x00 0xFE" + }, + { + "group": 65122, + "index": 1, + "text": "1", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x64 0x01 0x00" + }, + { + "group": 65122, + "index": 2, + "text": "2", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x64 0x01 0x00" + }, + { + "group": 65122, + "index": 3, + "text": "3", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x64 0x01 0x00" + }, + { + "group": 65122, + "index": 50, + "text": "Get back on the course!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xB3 0x00 0x00" + }, + { + "group": 65122, + "index": 51, + "text": "Wrong order!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xB3 0x00 0x00" + }, + { + "group": 65124, + "index": 50, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 65124, + "index": 51, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x00 0xFE" + }, + { + "group": 65200, + "index": 50, + "text": "{ VAR_0 }{ COMMON_FONT_SIZE 00 46 } { VAR_2 }", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0xB4 0x00 0x00" + }, + { + "group": 65200, + "index": 51, + "text": "{ VAR_0 }{ COMMON_FONT_SIZE 00 46 } { VAR_2 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xB4 0x00 0x00" + }, + { + "group": 65201, + "index": 1, + "text": "Point the Wii Remote at\nthe middle of the screen.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFF" + }, + { + "group": 65201, + "index": 2, + "text": "Press \uE043 to take\nthe Frisbee.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFF" + }, + { + "group": 65202, + "index": 0, + "text": "Missed!", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x1C 0x01 0x00" + }, + { + "group": 65202, + "index": 1, + "text": "Nice catch!", + "attributes": "0x0000006E", + "ex_attributes": "0x02 0x1C 0x01 0x00" + }, + { + "group": 65202, + "index": 2, + "text": "Jumping catch!", + "attributes": "0x00000073", + "ex_attributes": "0x02 0x1C 0x01 0x00" + }, + { + "group": 65202, + "index": 3, + "text": "Perfect!", + "attributes": "0x00000073", + "ex_attributes": "0x02 0x1C 0x01 0x00" + }, + { + "group": 65202, + "index": 4, + "text": "Great catch!", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x1C 0x01 0xFE" + }, + { + "group": 65203, + "index": 0, + "text": "\u002B100", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65203, + "index": 1, + "text": "\u002B100", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65203, + "index": 2, + "text": "\u002B50", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65203, + "index": 3, + "text": "\u002B10", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65203, + "index": 4, + "text": "\u002B", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x19 0x01 0x00" + }, + { + "group": 65203, + "index": 5, + "text": "100", + "attributes": "0x0000002D", + "ex_attributes": "0x00 0x3A 0x01 0xFE" + }, + { + "group": 65203, + "index": 6, + "text": "50", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x27 0x01 0xFE" + }, + { + "group": 65203, + "index": 50, + "text": "\u002B{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x64 0x01 0x00" + }, + { + "group": 65204, + "index": 0, + "text": "Start", + "attributes": "0x00000073", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65204, + "index": 1, + "text": "Finished", + "attributes": "0x00000073", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65205, + "index": 0, + "text": "Reset", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 65206, + "index": 50, + "text": "The dog couldn\u0027t catch the Frisbee.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 65206, + "index": 51, + "text": "Keep the Wii Remote level.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 65206, + "index": 52, + "text": "Turn your body toward the target.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 65206, + "index": 53, + "text": "Just relax and throw naturally.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 65207, + "index": 50, + "text": "View", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x8C 0x00 0xFE" + }, + { + "group": 65207, + "index": 51, + "text": "Back", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x8C 0x00 0xFE" + }, + { + "group": 65211, + "index": 50, + "text": "Press \uE043 to grab the disc,\nhold it as you swing, then\nrelease \uE043 as you snap\nyour wrist to let go.", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0x45 0x00 0xFE" + }, + { + "group": 65211, + "index": 51, + "text": "Swing the Wii Remote in\nan arc toward the target\narea and flick your wrist.", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0x45 0x00 0xFE" + }, + { + "group": 65212, + "index": 0, + "text": "\uE043 Take stance", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAF 0x00 0xFE" + }, + { + "group": 65300, + "index": 50, + "text": "{ VAR_0 }{ COMMON_FONT_SIZE 00 46 } { VAR_2 }", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 65300, + "index": 51, + "text": "Stage { VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xA0 0x00 0x00" + }, + { + "group": 65300, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x30 0x00 0xFE" + }, + { + "group": 65300, + "index": 53, + "text": "Final Stage", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xA0 0x00 0x00" + }, + { + "group": 65301, + "index": 0, + "text": "Range", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 65301, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x5A 0x01 0xFF" + }, + { + "group": 65301, + "index": 51, + "text": "{ VAR_2 }", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x32 0x00 0xFF" + }, + { + "group": 65302, + "index": 0, + "text": "\u002B10", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65302, + "index": 1, + "text": "Miss", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65302, + "index": 2, + "text": "x2", + "attributes": "0x0000008C", + "ex_attributes": "0x00 0xC8 0x00 0xFF" + }, + { + "group": 65302, + "index": 50, + "text": "\u002B{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65303, + "index": 0, + "text": "Ready", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 65303, + "index": 1, + "text": "Draw bow", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAA 0x00 0xFE" + }, + { + "group": 65304, + "index": 0, + "text": "Wind", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x4E 0x00 0x00" + }, + { + "group": 65304, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x2D 0x00 0x00" + }, + { + "group": 65304, + "index": 51, + "text": "{ VAR_2 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65305, + "index": 0, + "text": "\u002B10", + "attributes": "0x0000004B", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65305, + "index": 1, + "text": "Perfect", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65305, + "index": 2, + "text": "\u002B10", + "attributes": "0x0000004B", + "ex_attributes": "0x00 0xE6 0x01 0x00" + }, + { + "group": 65305, + "index": 3, + "text": "x2", + "attributes": "0x00000082", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 65311, + "index": 0, + "text": "Hold the Wii Remote\nupright and get in\na good stance.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 65320, + "index": 50, + "text": "Stage { VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x90 0x01 0x01" + }, + { + "group": 65320, + "index": 51, + "text": "Final Stage", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x90 0x01 0x01" + }, + { + "group": 65400, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x4B 0x01 0xFE" + }, + { + "group": 65401, + "index": 0, + "text": "Shoot", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 65401, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x52 0x01 0xFF" + }, + { + "group": 65403, + "index": 50, + "text": "Take ball", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xB9 0x00 0x00" + }, + { + "group": 65403, + "index": 51, + "text": "Shoot", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xB9 0x00 0x00" + }, + { + "group": 65404, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x64 0x00 0xFE" + }, + { + "group": 65405, + "index": 0, + "text": "Perfect!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65405, + "index": 1, + "text": "Bonus for Remaining Time", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 65405, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000004B", + "ex_attributes": "0x00 0xC8 0x01 0xFC" + }, + { + "group": 65406, + "index": 50, + "text": "Extra Time", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x01 0xFE" + }, + { + "group": 65406, + "index": 51, + "text": "Traveling", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x01 0xFE" + }, + { + "group": 65407, + "index": 0, + "text": "New record!", + "attributes": "0x0000005F", + "ex_attributes": "0x00 0xB9 0x00 0xFE" + }, + { + "group": 65407, + "index": 1, + "text": "Break your record!", + "attributes": "0x0000005F", + "ex_attributes": "0x00 0xB9 0x00 0xFE" + }, + { + "group": 65408, + "index": 0, + "text": "Press \uE042 or \uE041 to pass.", + "attributes": "0x00000078", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 65410, + "index": 0, + "text": "Press \uE043 to hold the\nball above your head,\nthen release it with\na flick of the wrist.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 65420, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x46 0x01 0xFE" + }, + { + "group": 65421, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x46 0x01 0xFE" + }, + { + "group": 65500, + "index": 0, + "text": "New record!", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 65500, + "index": 50, + "text": "{ VAR_0 } { VAR_2 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x82 0x01 0xFE" + }, + { + "group": 65500, + "index": 51, + "text": "{ VAR_2 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x28 0x00 0xFE" + }, + { + "group": 65501, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 65502, + "index": 50, + "text": "Timed Run", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 65503, + "index": 0, + "text": "Finish", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x52 0x01 0xFD" + }, + { + "group": 65504, + "index": 50, + "text": "Halfway point", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 65504, + "index": 51, + "text": "Almost there!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 65505, + "index": 0, + "text": "Ready", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 65507, + "index": 0, + "text": "x", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x12 0x00 0x00" + }, + { + "group": 65507, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x2F 0x00 0xFE" + }, + { + "group": 65508, + "index": 0, + "text": "Stray Ducklings", + "attributes": "0x00000073", + "ex_attributes": "0x01 0x4A 0x00 0xFE" + }, + { + "group": 65508, + "index": 1, + "text": "Finish", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x4A 0x00 0x00" + }, + { + "group": 65508, + "index": 2, + "text": "My best", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x87 0x00 0xFE" + }, + { + "group": 65508, + "index": 3, + "text": "Record!", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xFA 0x00 0xFE" + }, + { + "group": 65508, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000035", + "ex_attributes": "0x00 0xAA 0x01 0x00" + }, + { + "group": 65508, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x7E 0x00 0xFE" + }, + { + "group": 65510, + "index": 0, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xB4 0x00 0x00" + }, + { + "group": 65510, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x5F 0x00 0xFF" + }, + { + "group": 65511, + "index": 0, + "text": "Pts.", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x90 0x00 0x00" + }, + { + "group": 65511, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x3C 0x01 0xFE" + }, + { + "group": 65511, + "index": 51, + "text": "Got 1 Point!", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x90 0x00 0x00" + }, + { + "group": 65511, + "index": 52, + "text": "Match Point!", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x90 0x00 0x00" + }, + { + "group": 65512, + "index": 0, + "text": "Match Point!", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFE" + }, + { + "group": 65513, + "index": 0, + "text": "Go for the checkpoints!", + "attributes": "0x00000078", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 65513, + "index": 50, + "text": "First to { VAR_0 } pts. wins!", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x01 0xFD" + }, + { + "group": 65514, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xBE 0x00 0xFE" + }, + { + "group": 65520, + "index": 0, + "text": "Type", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x5F 0x00 0x03" + }, + { + "group": 65520, + "index": 50, + "text": "Left-turner", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 51, + "text": "Left-turn master", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 52, + "text": "Right-turner", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 53, + "text": "Right-turn master", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 54, + "text": "Evenhanded", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 55, + "text": "Heavy lifter", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 56, + "text": "Splasher", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 57, + "text": "Along for the ride", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 58, + "text": "Stowaway", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 59, + "text": "Strong arm", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 60, + "text": "Thrasher", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 61, + "text": "Paddle wheeler", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 62, + "text": "Iron arms", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 63, + "text": "Oarsman", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 64, + "text": "Helmsman", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65520, + "index": 65, + "text": "Unknown quantity", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x63 0x00 0x00" + }, + { + "group": 65600, + "index": 0, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x6E 0x00 0xFE" + }, + { + "group": 65600, + "index": 1, + "text": "Game", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x6E 0x00 0xFE" + }, + { + "group": 65600, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000041", + "ex_attributes": "0x00 0x35 0x01 0xFD" + }, + { + "group": 65600, + "index": 51, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x00 0x2F 0x00 0xFE" + }, + { + "group": 65600, + "index": 52, + "text": "{ VAR_0 }-Point Match", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x88 0x00 0xFE" + }, + { + "group": 65610, + "index": 50, + "text": "2 bounces", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xA0 0x00 0xFE" + }, + { + "group": 65610, + "index": 51, + "text": "No bounce", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xA0 0x00 0xFE" + }, + { + "group": 65610, + "index": 52, + "text": "Out", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xA0 0x00 0xFE" + }, + { + "group": 65610, + "index": 53, + "text": "Net", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xA0 0x00 0xFE" + }, + { + "group": 65610, + "index": 54, + "text": "Miss", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xA0 0x00 0xFE" + }, + { + "group": 65620, + "index": 0, + "text": "Server", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x84 0x00 0xFE" + }, + { + "group": 65630, + "index": 0, + "text": "Serve", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xB9 0x00 0x00" + }, + { + "group": 65631, + "index": 0, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xB9 0x00 0xFE" + }, + { + "group": 65640, + "index": 0, + "text": "Match point", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x7C 0x01 0xFE" + }, + { + "group": 65641, + "index": 0, + "text": "Deuce", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x7C 0x01 0xFE" + }, + { + "group": 65641, + "index": 1, + "text": "Get two points ahead to win!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xA4 0x00 0xFE" + }, + { + "group": 65650, + "index": 50, + "text": " { VAR_2 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x2A 0x00 0xFE" + }, + { + "group": 65650, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x49 0x01 0xFE" + }, + { + "group": 65650, + "index": 52, + "text": "{ VAR_0 } { VAR_2 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x4D 0x00 0xFE" + }, + { + "group": 65660, + "index": 0, + "text": "New record!", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xB6 0x00 0xFE" + }, + { + "group": 65700, + "index": 0, + "text": "\uFF11", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65700, + "index": 1, + "text": "\uFF12", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65700, + "index": 2, + "text": "\uFF13", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65700, + "index": 3, + "text": "\uFF14", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65700, + "index": 4, + "text": "\uFF15", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65700, + "index": 5, + "text": "\uFF16", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65700, + "index": 6, + "text": "\uFF17", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65700, + "index": 7, + "text": "\uFF18", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65700, + "index": 8, + "text": "\uFF19", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65700, + "index": 9, + "text": "\uFF11\uFF10", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65700, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000043", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 65701, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x14 0x00 0x00" + }, + { + "group": 65701, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 65701, + "index": 52, + "text": "-", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x14 0x00 0x00" + }, + { + "group": 65701, + "index": 53, + "text": "-", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x14 0x00 0x00" + }, + { + "group": 65701, + "index": 54, + "text": "\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467\u2468", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x14 0x00 0x00" + }, + { + "group": 65702, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x14 0x00 0x00" + }, + { + "group": 65702, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 65702, + "index": 52, + "text": "-", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x14 0x00 0x00" + }, + { + "group": 65702, + "index": 53, + "text": "-", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x14 0x00 0x00" + }, + { + "group": 65702, + "index": 54, + "text": "\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467\u2468", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x14 0x00 0x00" + }, + { + "group": 65703, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x15 0x00 0xFF" + }, + { + "group": 65703, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 65703, + "index": 52, + "text": "-", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x15 0x00 0xFF" + }, + { + "group": 65703, + "index": 53, + "text": "-", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x15 0x00 0xFF" + }, + { + "group": 65703, + "index": 54, + "text": "\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467\u2468", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x15 0x00 0xFF" + }, + { + "group": 65704, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x15 0x00 0xFF" + }, + { + "group": 65704, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 65704, + "index": 52, + "text": "-", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x15 0x00 0xFF" + }, + { + "group": 65704, + "index": 53, + "text": "-", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x15 0x00 0xFF" + }, + { + "group": 65704, + "index": 54, + "text": "\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467\u2468", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x15 0x00 0xFF" + }, + { + "group": 65710, + "index": 0, + "text": "Switch", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x8C 0x00 0x00" + }, + { + "group": 65710, + "index": 50, + "text": "Move", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x8C 0x00 0x00" + }, + { + "group": 65710, + "index": 51, + "text": "Turn", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x8C 0x00 0x00" + }, + { + "group": 65710, + "index": 52, + "text": "Zoom", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x8C 0x00 0x00" + }, + { + "group": 65710, + "index": 53, + "text": "Back", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x8C 0x00 0x00" + }, + { + "group": 65711, + "index": 0, + "text": "1", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65711, + "index": 1, + "text": "2", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65711, + "index": 2, + "text": "3", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65711, + "index": 3, + "text": "4", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65711, + "index": 4, + "text": "5", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65711, + "index": 5, + "text": "6", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65711, + "index": 6, + "text": "7", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65711, + "index": 7, + "text": "8", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65711, + "index": 8, + "text": "9", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65711, + "index": 9, + "text": "10", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x00 0xFC" + }, + { + "group": 65720, + "index": 50, + "text": "Hold the ball at chest level,\nthen roll it { COMMON_FONT_COLOR 01 00 }while holding { COMMON_FONT_COLOR 00 00 }\uE043.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 65720, + "index": 51, + "text": "\uE041 Adjust your position or the direction of your throw\n\uE042 Switch between adjusting position and direction", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 65720, + "index": 52, + "text": "Press and hold \uE043 before you start your\nswing, and release it to let go of the ball.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xF4 0x00 0xFF" + }, + { + "group": 65721, + "index": 50, + "text": "When you\u0027re bowling,\n{ COMMON_FONT_COLOR 01 00 }do not release { COMMON_FONT_COLOR 00 00 }\uE043.\nHold the Wii Remote\nsecurely.", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0x45 0x00 0xFE" + }, + { + "group": 65721, + "index": 51, + "text": "Take a swing while\nholding \uE043. Release \uE043\nas you roll the ball.", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0x45 0x00 0xFE" + }, + { + "group": 65730, + "index": 0, + "text": "Perfect", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65731, + "index": 0, + "text": "Split", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x26 0x01 0xFF" + }, + { + "group": 65732, + "index": 50, + "text": "{ VAR_0 } { VAR_2 }", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x2C 0x01 0x00" + }, + { + "group": 65733, + "index": 50, + "text": "Double", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65733, + "index": 51, + "text": "Turkey", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65733, + "index": 52, + "text": "Four in a row", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65733, + "index": 53, + "text": "Five in a row", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65733, + "index": 54, + "text": "Six in a row", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65733, + "index": 55, + "text": "Seven in a row", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65733, + "index": 56, + "text": "Eight in a row", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65733, + "index": 57, + "text": "Nine in a row", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65733, + "index": 58, + "text": "Ten in a row", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65733, + "index": 59, + "text": "Eleven in a row", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65733, + "index": 60, + "text": "Perfect", + "attributes": "0x00000055", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 65734, + "index": 0, + "text": "Level", + "attributes": "0x00000073", + "ex_attributes": "0x01 0x70 0x00 0xFF" + }, + { + "group": 65734, + "index": 50, + "text": "Beginner", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x70 0x01 0xFE" + }, + { + "group": 65734, + "index": 51, + "text": "Intermediate", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x70 0x01 0xFE" + }, + { + "group": 65734, + "index": 52, + "text": "Expert", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x70 0x01 0xFE" + }, + { + "group": 65734, + "index": 53, + "text": "Open", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x70 0x01 0xFE" + }, + { + "group": 65800, + "index": 0, + "text": "Hole", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x9E 0x00 0xFE" + }, + { + "group": 65800, + "index": 1, + "text": "Total", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x33 0x00 0xFE" + }, + { + "group": 65800, + "index": 2, + "text": "Par", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x9E 0x00 0xFE" + }, + { + "group": 65800, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x19 0x00 0x00" + }, + { + "group": 65800, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x19 0x00 0xFE" + }, + { + "group": 65800, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x32 0x00 0xFE" + }, + { + "group": 65801, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 65801, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x1E 0x00 0xFE" + }, + { + "group": 65801, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x36 0x00 0xFE" + }, + { + "group": 65802, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x79 0x00 0x00" + }, + { + "group": 65802, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x1E 0x00 0xFE" + }, + { + "group": 65802, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x36 0x00 0xFE" + }, + { + "group": 65804, + "index": 0, + "text": "Angle", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 65804, + "index": 50, + "text": "Driver", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFF" + }, + { + "group": 65804, + "index": 51, + "text": "3 Wood", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFF" + }, + { + "group": 65804, + "index": 52, + "text": "3 Iron", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFF" + }, + { + "group": 65804, + "index": 53, + "text": "5 Iron", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFF" + }, + { + "group": 65804, + "index": 54, + "text": "7 Iron", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFF" + }, + { + "group": 65804, + "index": 55, + "text": "9 Iron", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFF" + }, + { + "group": 65804, + "index": 56, + "text": "Wedge", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 65804, + "index": 57, + "text": "Putter", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 65805, + "index": 0, + "text": "Wind", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x4E 0x00 0x00" + }, + { + "group": 65805, + "index": 1, + "text": "High", + "attributes": "0x0000004B", + "ex_attributes": "0x00 0x3A 0x00 0x00" + }, + { + "group": 65805, + "index": 2, + "text": "Low", + "attributes": "0x0000004B", + "ex_attributes": "0x00 0x3A 0x00 0x00" + }, + { + "group": 65805, + "index": 50, + "text": "Hole { VAR_0 }: Par { VAR_0 }", + "attributes": "0x0000004B", + "ex_attributes": "0x00 0xA8 0x00 0x00" + }, + { + "group": 65805, + "index": 51, + "text": "{ VAR_0 } { VAR_2 } to go", + "attributes": "0x0000004B", + "ex_attributes": "0x00 0xA8 0x00 0x00" + }, + { + "group": 65805, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x2D 0x00 0x00" + }, + { + "group": 65805, + "index": 53, + "text": "{ VAR_2 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x32 0x00 0xFE" + }, + { + "group": 65805, + "index": 54, + "text": "{ VAR_0 } { VAR_2 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x3C 0x00 0xFF" + }, + { + "group": 65806, + "index": 50, + "text": "Green", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x70 0x00 0x01" + }, + { + "group": 65806, + "index": 51, + "text": "Edge of Green", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x70 0x00 0x01" + }, + { + "group": 65806, + "index": 52, + "text": "Fairway", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x70 0x00 0x01" + }, + { + "group": 65806, + "index": 53, + "text": "Rough", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x70 0x00 0x01" + }, + { + "group": 65806, + "index": 54, + "text": "Bunker", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x70 0x00 0x01" + }, + { + "group": 65806, + "index": 55, + "text": "Out of Bounds", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x70 0x00 0x01" + }, + { + "group": 65806, + "index": 56, + "text": "Water Hazard", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x70 0x00 0x01" + }, + { + "group": 65806, + "index": 57, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x70 0x00 0x01" + }, + { + "group": 65806, + "index": 58, + "text": "Safe", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x70 0x00 0x01" + }, + { + "group": 65806, + "index": 60, + "text": "Remaining: { VAR_0 } { VAR_2 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x70 0x00 0x00" + }, + { + "group": 65806, + "index": 61, + "text": "Distance: { VAR_0 } { VAR_2 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x70 0x00 0x00" + }, + { + "group": 65807, + "index": 50, + "text": "Shot { VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xF4 0x01 0x01" + }, + { + "group": 65807, + "index": 51, + "text": "Throw { VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xF4 0x01 0x01" + }, + { + "group": 65808, + "index": 0, + "text": "\uE043 Reset stance", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xBE 0x00 0xFE" + }, + { + "group": 65809, + "index": 0, + "text": "Terrain", + "attributes": "0x00000055", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 65809, + "index": 50, + "text": "Zoom", + "attributes": "0x00000055", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 65809, + "index": 51, + "text": "Back", + "attributes": "0x00000055", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 65810, + "index": 50, + "text": "Hole in One", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0x01" + }, + { + "group": 65810, + "index": 51, + "text": "Albatross", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0x01" + }, + { + "group": 65810, + "index": 52, + "text": "Eagle", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0x01" + }, + { + "group": 65810, + "index": 53, + "text": "Birdie", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0x01" + }, + { + "group": 65811, + "index": 50, + "text": "Par", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65812, + "index": 50, + "text": "Bogey", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65812, + "index": 51, + "text": "Double Bogey", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65812, + "index": 52, + "text": "Triple Bogey", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65813, + "index": 50, + "text": "\u002B{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x96 0x01 0x01" + }, + { + "group": 65814, + "index": 0, + "text": "Give up", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 65814, + "index": 50, + "text": "\u002B{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x64 0x01 0x00" + }, + { + "group": 65815, + "index": 50, + "text": "Birdie Chance", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xC2 0x01 0xFE" + }, + { + "group": 65815, + "index": 51, + "text": "Eagle Chance", + "attributes": "0x00000050", + "ex_attributes": "0x01 0xC2 0x01 0xFE" + }, + { + "group": 65816, + "index": 0, + "text": "Hole", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x33 0x00 0xFF" + }, + { + "group": 65816, + "index": 1, + "text": "Total", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x33 0x00 0xFE" + }, + { + "group": 65816, + "index": 2, + "text": "Par", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x33 0x00 0xFE" + }, + { + "group": 65816, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x14 0x00 0xFE" + }, + { + "group": 65816, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x14 0x00 0x00" + }, + { + "group": 65816, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x33 0x00 0x00" + }, + { + "group": 65816, + "index": 53, + "text": "{ VAR_0 }", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x14 0x00 0xFD" + }, + { + "group": 65817, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x14 0x00 0xFD" + }, + { + "group": 65817, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 65820, + "index": 50, + "text": "Hole { VAR_0 }: Par { VAR_0 }", + "attributes": "0x00000032", + "ex_attributes": "0x00 0xF0 0x01 0xFF" + }, + { + "group": 65900, + "index": 0, + "text": "Putter", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xA7 0x00 0xFE" + }, + { + "group": 65900, + "index": 1, + "text": "Midrange", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xA7 0x00 0xFE" + }, + { + "group": 65900, + "index": 2, + "text": "Driver", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xA7 0x00 0xFE" + }, + { + "group": 65900, + "index": 3, + "text": "Average 30 yd.", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xA7 0x01 0xFE" + }, + { + "group": 65900, + "index": 4, + "text": "Average 90 yd.", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xA7 0x01 0xFE" + }, + { + "group": 65900, + "index": 5, + "text": "Average 180 yd.", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xA7 0x01 0xFE" + }, + { + "group": 65900, + "index": 6, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xA7 0x00 0xFE" + }, + { + "group": 65900, + "index": 7, + "text": "Recommended", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x8C 0x00 0xFE" + }, + { + "group": 65900, + "index": 8, + "text": "Direction", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 65900, + "index": 50, + "text": "{ VAR_0 } { VAR_2 } to go", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xA8 0x00 0x00" + }, + { + "group": 65900, + "index": 51, + "text": "Point the Wii Remote at the\nscreen to select a Frisbee.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFF" + }, + { + "group": 65900, + "index": 52, + "text": "\uE043 Select a Frisbee", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFF" + }, + { + "group": 65900, + "index": 53, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFF" + }, + { + "group": 65900, + "index": 54, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFF" + }, + { + "group": 65900, + "index": 55, + "text": "Throw { VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xC8 0x01 0x01" + }, + { + "group": 65901, + "index": 0, + "text": "Direction", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 65901, + "index": 1, + "text": "Change Frisbee", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 65901, + "index": 2, + "text": "View", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC8 0x00 0xFE" + }, + { + "group": 65902, + "index": 0, + "text": "\uE043 Take stance", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAF 0x00 0xFE" + }, + { + "group": 65902, + "index": 50, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xAF 0x00 0xFE" + }, + { + "group": 65904, + "index": 50, + "text": "Press \uE043 to grab the disc,\nhold it as you swing, then\nrelease \uE043 as you snap\nyour wrist to let go.", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0x45 0x00 0xFE" + }, + { + "group": 65904, + "index": 51, + "text": "Swing the Wii Remote in\nan arc toward the target\narea and flick your wrist.", + "attributes": "0x0000005F", + "ex_attributes": "0x01 0x45 0x00 0xFE" + }, + { + "group": 66000, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x5E 0x01 0xFE" + }, + { + "group": 66000, + "index": 51, + "text": "{ VAR_2 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x2A 0x00 0xFE" + }, + { + "group": 66001, + "index": 0, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x7C 0x00 0xFE" + }, + { + "group": 66004, + "index": 0, + "text": "\u002B{ VAR_0 }", + "attributes": "0x00000041", + "ex_attributes": "0x00 0x96 0x01 0x00" + }, + { + "group": 66006, + "index": 0, + "text": "START", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x52 0x01 0x00" + }, + { + "group": 66007, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x72 0x01 0xFD" + }, + { + "group": 66010, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x69 0x01 0xFF" + }, + { + "group": 66010, + "index": 51, + "text": "{ VAR_2 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x2A 0x00 0xFE" + }, + { + "group": 66011, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 66012, + "index": 0, + "text": "Finish", + "attributes": "0x00000078", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 66012, + "index": 1, + "text": "1", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66012, + "index": 2, + "text": "2", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66012, + "index": 3, + "text": "3", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66012, + "index": 4, + "text": "4", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66012, + "index": 5, + "text": "5", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66012, + "index": 6, + "text": "6", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66012, + "index": 7, + "text": "7", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66012, + "index": 8, + "text": "8", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66012, + "index": 9, + "text": "9", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66012, + "index": 10, + "text": "10", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0xF8" + }, + { + "group": 66100, + "index": 50, + "text": "", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 66100, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 66101, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000078", + "ex_attributes": "0x00 0xDC 0x00 0xFE" + }, + { + "group": 66101, + "index": 51, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF5 0x00 0xFD" + }, + { + "group": 66102, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x46 0x00 0xFE" + }, + { + "group": 66103, + "index": 50, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x39 0x01 0xFF" + }, + { + "group": 66104, + "index": 0, + "text": "x", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x17 0x00 0x00" + }, + { + "group": 66104, + "index": 1, + "text": "\u002B", + "attributes": "0x00000078", + "ex_attributes": "0x00 0x1E 0x00 0x00" + }, + { + "group": 66104, + "index": 2, + "text": "10", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x41 0x01 0xFF" + }, + { + "group": 66104, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x39 0x01 0xFF" + }, + { + "group": 66105, + "index": 0, + "text": "Get more balloons!", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x7C 0x01 0xFE" + }, + { + "group": 66105, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66105, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66105, + "index": 3, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66105, + "index": 4, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66105, + "index": 5, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66105, + "index": 50, + "text": "Go to { VAR_0 }!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x2C 0x00 0xFE" + }, + { + "group": 66108, + "index": 0, + "text": "Next", + "attributes": "0x00000078", + "ex_attributes": "0x00 0xBE 0x00 0xFE" + }, + { + "group": 66108, + "index": 50, + "text": "Next", + "attributes": "0x00000078", + "ex_attributes": "0x00 0xBE 0x00 0xFE" + }, + { + "group": 66108, + "index": 51, + "text": "Close", + "attributes": "0x00000078", + "ex_attributes": "0x00 0xBE 0x00 0xFE" + }, + { + "group": 66109, + "index": 0, + "text": "Flight Record", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x2C 0x00 0xFE" + }, + { + "group": 66109, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xB4 0x00 0xFE" + }, + { + "group": 66109, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66109, + "index": 52, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66109, + "index": 53, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66109, + "index": 54, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66109, + "index": 55, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66109, + "index": 56, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66109, + "index": 57, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66109, + "index": 58, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66109, + "index": 59, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66110, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66111, + "index": 0, + "text": "Finish", + "attributes": "0x00000078", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 66111, + "index": 1, + "text": "1", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66111, + "index": 2, + "text": "2", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66111, + "index": 3, + "text": "3", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66111, + "index": 4, + "text": "4", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66111, + "index": 5, + "text": "5", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66111, + "index": 6, + "text": "6", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66111, + "index": 7, + "text": "7", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66111, + "index": 8, + "text": "8", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66111, + "index": 9, + "text": "9", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66111, + "index": 10, + "text": "10", + "attributes": "0x00000069", + "ex_attributes": "0x01 0x90 0x01 0xF8" + }, + { + "group": 66112, + "index": 50, + "text": "Let\u0027s start with\nlearning how to\ncontrol the plane.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 51, + "text": "Tilt the Wii Remote\nright and left to\nturn your plane.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 52, + "text": "Thrust the Wii Remote\nforward for a speed\nboost, and pull it back\nto slow down.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 53, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 54, + "text": "Let\u0027s fly! Hold the Wii\nRemote horizontally,\nlike a paper airplane.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 55, + "text": "Other controls:\n\uE042 Balloon blaster\n\uE043 Cut the engine", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 56, + "text": "Simply move the Wii\nRemote as if you were\nholding the airplane.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 57, + "text": "Imagine that the Wii\nRemote is a plane,\nwith \uE041 at the front.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 60, + "text": "This symbol will\nappear over every\nsightseeing spot.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 61, + "text": "Fly closer to a spot\nto get some more\ninformation about it.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 62, + "text": "If you fly { COMMON_FONT_COLOR 01 00 }through{ COMMON_FONT_COLOR 00 00 } the\n\u332B symbol, the\nlocation will be saved\nto your flight record.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 63, + "text": "Fly all around the\nisland, and try to find\nas many \u332B points\nas you can!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 70, + "text": "You can now pop\nballoons!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 71, + "text": "Press \uE042 to fire the\nballoon blaster at\nballoons.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 72, + "text": "Fly straight into the\nhuge balloons to pop\nthem!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 80, + "text": "You may have already\nnoticed, but your\nplane is loaded with\ncool features.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 81, + "text": "\uE042 Balloon blaster\n\uE043 Cut the engine\n\uE041 Look around\n\uE047 Shoot a flare", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66112, + "index": 82, + "text": "Try them out once\nyou\u0027ve gotten used to \nflying!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x36 0x00 0xFE" + }, + { + "group": 66113, + "index": 0, + "text": "Turn back to the island.", + "attributes": "0x00000082", + "ex_attributes": "0x02 0x1C 0x00 0xFE" + }, + { + "group": 66115, + "index": 0, + "text": "01-40", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 66115, + "index": 1, + "text": "41-80", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 66115, + "index": 2, + "text": "Special", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x50 0x00 0xFE" + }, + { + "group": 66117, + "index": 0, + "text": "?", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x41 0x01 0x00" + }, + { + "group": 66118, + "index": 0, + "text": "\u332B points found", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xB0 0x00 0xFE" + }, + { + "group": 66118, + "index": 1, + "text": "\u334A popped", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xB0 0x00 0xFE" + }, + { + "group": 66118, + "index": 2, + "text": "Record", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xB0 0x00 0xFE" + }, + { + "group": 66118, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xA5 0x01 0xFF" + }, + { + "group": 66118, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0xA5 0x01 0xFF" + }, + { + "group": 66118, + "index": 52, + "text": "Best { VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xB0 0x00 0xFE" + }, + { + "group": 66118, + "index": 53, + "text": "Best { VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xB0 0x00 0xFE" + }, + { + "group": 66118, + "index": 54, + "text": "Best ---", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xB0 0x00 0xFE" + }, + { + "group": 66118, + "index": 55, + "text": "Best ---", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xB0 0x00 0xFE" + }, + { + "group": 66119, + "index": 50, + "text": "Found { VAR_0 } \u332B points", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x4A 0x01 0xFC" + }, + { + "group": 66119, + "index": 60, + "text": "You can now pop\nballoons!", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66119, + "index": 61, + "text": "You can now fly\nin the evening!", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66119, + "index": 62, + "text": "You can now use\nthe double blaster!", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66119, + "index": 63, + "text": "You can now fly\nat night!", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66119, + "index": 64, + "text": "The islands are now\nlit up at night!", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66119, + "index": 65, + "text": "You can now fly a\ntwo-seater plane!", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66119, + "index": 66, + "text": "The Whale Shark has\na new design!", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66119, + "index": 67, + "text": "A vacation house has\nbeen built for you!", + "attributes": "0x0000008C", + "ex_attributes": "0x01 0xE0 0x00 0xFE" + }, + { + "group": 66120, + "index": 0, + "text": "Hit!", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x01 0xFF" + }, + { + "group": 66120, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66120, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66120, + "index": 3, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66120, + "index": 4, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66120, + "index": 5, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66120, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x2C 0x00 0xFE" + }, + { + "group": 66121, + "index": 0, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xC3 0x00 0xFE" + }, + { + "group": 66123, + "index": 0, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x01 0x7C 0x01 0xFE" + }, + { + "group": 66123, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66123, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66123, + "index": 3, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66123, + "index": 4, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66123, + "index": 5, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x29 0x01 0x00" + }, + { + "group": 66123, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x2C 0x00 0xFE" + }, + { + "group": 66124, + "index": 50, + "text": "Unlocked balloons.", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xE1 0x00 0xFE" + }, + { + "group": 66124, + "index": 51, + "text": "Unlocked\nevening flyover.", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xE1 0x00 0xFE" + }, + { + "group": 66124, + "index": 52, + "text": "Unlocked\ndouble blaster.", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xE1 0x00 0xFE" + }, + { + "group": 66124, + "index": 53, + "text": "Unlocked\nnight flyover.", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xE1 0x00 0xFE" + }, + { + "group": 66124, + "index": 54, + "text": "Unlocked\nnight lights.", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xE1 0x00 0xFE" + }, + { + "group": 66124, + "index": 55, + "text": "Unlocked\ntwo-seater plane.", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xE1 0x00 0xFE" + }, + { + "group": 66124, + "index": 56, + "text": "Got new Whale\nShark design.", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xE1 0x00 0xFE" + }, + { + "group": 66124, + "index": 57, + "text": "Got vacation home.", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xE1 0x00 0xFE" + }, + { + "group": 66125, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x38 0x00 0xFE" + }, + { + "group": 66125, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x2A 0x00 0xFE" + }, + { + "group": 66126, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x2A 0x00 0xFE" + }, + { + "group": 66200, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x5F 0x00 0xFE" + }, + { + "group": 66200, + "index": 51, + "text": "Full Power", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x5F 0x00 0xFE" + }, + { + "group": 66200, + "index": 52, + "text": "Sprint", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x5F 0x00 0xFE" + }, + { + "group": 66200, + "index": 53, + "text": "Energy Low", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x5F 0x00 0xFE" + }, + { + "group": 66200, + "index": 54, + "text": "Out of Breath", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x5F 0x00 0xFE" + }, + { + "group": 66200, + "index": 55, + "text": "Rest Stop", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x5F 0x00 0xFE" + }, + { + "group": 66201, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x5E 0x00 0xFE" + }, + { + "group": 66202, + "index": 0, + "text": "Switch view", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 66202, + "index": 50, + "text": "Rear view", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 66202, + "index": 51, + "text": "Left view", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 66202, + "index": 52, + "text": "Right view", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 66202, + "index": 53, + "text": "Front view", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 66203, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x78 0x01 0xFF" + }, + { + "group": 66203, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x2A 0x00 0xFE" + }, + { + "group": 66203, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x8C 0x01 0xFF" + }, + { + "group": 66204, + "index": 50, + "text": "{ VAR_0 }-Stage Race", + "attributes": "0x00000055", + "ex_attributes": "0x00 0xC6 0x00 0xFE" + }, + { + "group": 66204, + "index": 60, + "text": "{ VAR_0 }: Around the Island", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 61, + "text": "{ VAR_0 }: To the Beach", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 62, + "text": "{ VAR_0 }: Across the Bridge", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 63, + "text": "{ VAR_0 }: Over Talon Rock", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 64, + "text": "{ VAR_0 }: Up the Volcano", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 65, + "text": "{ VAR_0 }: Into Maka Wuhu", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 70, + "text": "Around the Island", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 71, + "text": "To the Beach", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 72, + "text": "Across the Bridge", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 73, + "text": "Over Talon Rock", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 74, + "text": "Up the Volcano", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 75, + "text": "Into Maka Wuhu", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 80, + "text": "Day 1", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 81, + "text": "Day 2", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 82, + "text": "Day 3", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 83, + "text": "Day 4", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 84, + "text": "Day 5", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66204, + "index": 85, + "text": "Final Day", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0x40 0x00 0xFE" + }, + { + "group": 66205, + "index": 0, + "text": "Finish", + "attributes": "0x00000078", + "ex_attributes": "0x01 0x52 0x01 0xFD" + }, + { + "group": 66205, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xF4 0x01 0xFF" + }, + { + "group": 66206, + "index": 0, + "text": "Wrong way!", + "attributes": "0x00000082", + "ex_attributes": "0x02 0x1C 0x00 0x00" + }, + { + "group": 66206, + "index": 1, + "text": "1", + "attributes": "0x000000A0", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66206, + "index": 2, + "text": "2", + "attributes": "0x000000A0", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66206, + "index": 3, + "text": "3", + "attributes": "0x000000A0", + "ex_attributes": "0x01 0x90 0x01 0x00" + }, + { + "group": 66207, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 66207, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x98 0x00 0xFE" + }, + { + "group": 66209, + "index": 50, + "text": "Ride around the island, ending in a long slope down to the finish line.", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x04 0x00 0x00" + }, + { + "group": 66209, + "index": 51, + "text": "Race on every surface: concrete in town, mud by the river, and sand on the beach.", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x04 0x00 0x00" + }, + { + "group": 66209, + "index": 52, + "text": "Ride a tough circuit up Heartbreak Peak, by the Hilltop Overlook, and across the Swaying Bridge.", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x04 0x00 0x00" + }, + { + "group": 66209, + "index": 53, + "text": "Catch air off Talon Rock, then ride through town and up a long hill.", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x04 0x00 0x00" + }, + { + "group": 66209, + "index": 54, + "text": "Ride from Red Iron Bridge to mountain caverns; tour different sides of the island. Watch out for the edge on the mountain roads!", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x04 0x00 0x00" + }, + { + "group": 66209, + "index": 55, + "text": "Ride through the center of the Maka Wuhu volcano all the way down the mountain. Don\u0027t look down!", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x04 0x00 0x00" + }, + { + "group": 66210, + "index": 0, + "text": "START", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x78 0x00 0xFF" + }, + { + "group": 66210, + "index": 1, + "text": "GOAL", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x78 0x00 0xFF" + }, + { + "group": 66210, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 66214, + "index": 50, + "text": "Day { VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xE0 0x01 0x00" + }, + { + "group": 66214, + "index": 51, + "text": "Final Day", + "attributes": "0x00000046", + "ex_attributes": "0x01 0xE0 0x01 0x00" + }, + { + "group": 66220, + "index": 0, + "text": "Position", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x2E 0x00 0xFE" + }, + { + "group": 66220, + "index": 50, + "text": "{ VAR_0 }", + "attributes": "0x00000055", + "ex_attributes": "0x00 0x46 0x01 0xFF" + }, + { + "group": 66220, + "index": 51, + "text": "{ VAR_0 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x2E 0x00 0xFE" + }, + { + "group": 66220, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x00000055", + "ex_attributes": "0x00 0x6E 0x01 0xFF" + }, + { + "group": 66222, + "index": 50, + "text": "Almost there!", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0x04 0x01 0xFF" + }, + { + "group": 66222, + "index": 51, + "text": "You\u0027re halfway there!", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0x04 0x01 0xFF" + }, + { + "group": 66223, + "index": 0, + "text": "Wrong way!", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x04 0x00 0xFE" + }, + { + "group": 66223, + "index": 1, + "text": "1", + "attributes": "0x0000008C", + "ex_attributes": "0x00 0x96 0x01 0x00" + }, + { + "group": 66223, + "index": 2, + "text": "2", + "attributes": "0x0000008C", + "ex_attributes": "0x00 0x96 0x01 0x00" + }, + { + "group": 66223, + "index": 3, + "text": "3", + "attributes": "0x0000008C", + "ex_attributes": "0x00 0x96 0x01 0x00" + }, + { + "group": 66225, + "index": 0, + "text": "VS", + "attributes": "0x000000DC", + "ex_attributes": "0x00 0xC8 0x00 0xFF" + }, + { + "group": 66225, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x00000104", + "ex_attributes": "0x02 0x49 0x00 0xFE" + }, + { + "group": 66225, + "index": 51, + "text": "Wii Sports", + "attributes": "0x00000104", + "ex_attributes": "0x02 0x49 0x00 0xFE" + }, + { + "group": 66225, + "index": 52, + "text": "Resort", + "attributes": "0x00000104", + "ex_attributes": "0x02 0x49 0x00 0xFE" + }, + { + "group": 66231, + "index": 50, + "text": "{ VAR_1 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0xA0 0x00 0xFE" + }, + { + "group": 66300, + "index": 0, + "text": "You\u0027re over the drop zone.\nJump out and skydive down\nto Wuhu Island!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFE" + }, + { + "group": 66300, + "index": 1, + "text": "Dive!", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xA4 0x01 0xFE" + }, + { + "group": 66300, + "index": 2, + "text": "OK", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xC8 0x01 0x00" + }, + { + "group": 66300, + "index": 50, + "text": "You\u0027re over the drop zone.\nJump out and skydive down\nto Wuhu Island!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFE" + }, + { + "group": 66300, + "index": 51, + "text": "Dive!", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xA4 0x01 0xFE" + }, + { + "group": 66300, + "index": 60, + "text": "Do you want to take a\npractice jump so you can \nlearn how to skydive?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xA4 0x00 0xFE" + }, + { + "group": 66300, + "index": 61, + "text": "Sure!", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xA4 0x01 0xFE" + }, + { + "group": 66300, + "index": 62, + "text": "Sure!", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xA4 0x01 0xFE" + }, + { + "group": 66301, + "index": 50, + "text": "Catch", + "attributes": "0x00000050", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 66301, + "index": 51, + "text": "Double Catch!", + "attributes": "0x00000050", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 66301, + "index": 52, + "text": "Triple Catch!", + "attributes": "0x00000050", + "ex_attributes": "0x02 0x26 0x01 0x00" + }, + { + "group": 66302, + "index": 0, + "text": "Perfect Catch!", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x26 0x01 0xFE" + }, + { + "group": 66304, + "index": 0, + "text": "Next", + "attributes": "0x00000078", + "ex_attributes": "0x00 0xEB 0x00 0x00" + }, + { + "group": 66304, + "index": 1, + "text": "Change photo", + "attributes": "0x00000064", + "ex_attributes": "0x00 0xC3 0x00 0xFE" + }, + { + "group": 66305, + "index": 0, + "text": "People photographed", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x9A 0x00 0xFE" + }, + { + "group": 66305, + "index": 1, + "text": "/", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x24 0x00 0xFC" + }, + { + "group": 66305, + "index": 2, + "text": "Results", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 66305, + "index": 3, + "text": "\u002B", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x16 0x00 0x00" + }, + { + "group": 66305, + "index": 4, + "text": "\u002B", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x14 0x00 0x00" + }, + { + "group": 66305, + "index": 50, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x48 0x01 0xFE" + }, + { + "group": 66305, + "index": 51, + "text": "", + "attributes": "0x00000030", + "ex_attributes": "0x00 0x2B 0x01 0xFF" + }, + { + "group": 66305, + "index": 52, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x2B 0x00 0xFE" + }, + { + "group": 66305, + "index": 53, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x24 0x00 0xFE" + }, + { + "group": 66305, + "index": 54, + "text": "{ VAR_0 }", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x3F 0x01 0xFF" + }, + { + "group": 66305, + "index": 55, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x3E 0x00 0xFF" + }, + { + "group": 66305, + "index": 56, + "text": "{ VAR_0 }", + "attributes": "0x00000032", + "ex_attributes": "0x00 0x3F 0x01 0xFF" + }, + { + "group": 66305, + "index": 57, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x00 0x3D 0x00 0xFE" + }, + { + "group": 66305, + "index": 58, + "text": "{ VAR_0 }", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x6B 0x01 0xFF" + }, + { + "group": 66305, + "index": 59, + "text": " { VAR_2 }", + "attributes": "0x00000050", + "ex_attributes": "0x00 0x35 0x00 0xFE" + }, + { + "group": 66305, + "index": 60, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x2B 0x00 0xFF" + }, + { + "group": 66305, + "index": 61, + "text": "{ VAR_2 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x37 0x00 0xFF" + }, + { + "group": 66305, + "index": 62, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x00 0x2B 0x00 0xFF" + }, + { + "group": 66305, + "index": 63, + "text": "{ VAR_2 }", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x36 0x00 0xFE" + }, + { + "group": 66309, + "index": 0, + "text": "To Formation", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xEB 0x01 0xFF" + }, + { + "group": 66309, + "index": 1, + "text": "ft.", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0x32 0x01 0xFB" + }, + { + "group": 66350, + "index": 50, + "text": "Link up with other skydivers!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xAE 0x00 0xFE" + }, + { + "group": 80000, + "index": 0, + "text": "Pt.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80000, + "index": 1, + "text": "Pts.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80010, + "index": 0, + "text": "yd.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80010, + "index": 1, + "text": "yd.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80011, + "index": 0, + "text": "yd.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80011, + "index": 1, + "text": "yd.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80012, + "index": 0, + "text": "ft.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80012, + "index": 1, + "text": "ft.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80012, + "index": 10, + "text": "ft.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80012, + "index": 11, + "text": "ft.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80013, + "index": 0, + "text": "yd.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80013, + "index": 1, + "text": "yd.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80013, + "index": 10, + "text": "yd.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80013, + "index": 11, + "text": "yd.", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80014, + "index": 0, + "text": "mph", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80014, + "index": 1, + "text": "mph", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80015, + "index": 0, + "text": "pin", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80015, + "index": 1, + "text": "pins", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80016, + "index": 0, + "text": "return", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80016, + "index": 1, + "text": "returns", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80017, + "index": 0, + "text": "minute", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80017, + "index": 1, + "text": "minutes", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80018, + "index": 0, + "text": "person", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80018, + "index": 1, + "text": "people", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80019, + "index": 0, + "text": "Smile", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80019, + "index": 1, + "text": "Smiles", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80020, + "index": 0, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80020, + "index": 1, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x00 0xF0 0x03 0x00" + }, + { + "group": 80100, + "index": 0, + "text": "{ T0A_0000 01 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 80100, + "index": 1, + "text": "{ VAR_0 }", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xC2 0x00 0xFE" + }, + { + "group": 80101, + "index": 0, + "text": "{ T0A_0000 02 00 }{ T0A_0001 00 00 }{ T0A_0003 01 00 }{ T0A_0004 00 00 }{ T0A_0005 00 00 }", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 80101, + "index": 1, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xC2 0x00 0xFF" + }, + { + "group": 80101, + "index": 2, + "text": "Next", + "attributes": "0x0000003C", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80110, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xAE 0x00 0x01" + }, + { + "group": 80200, + "index": 0, + "text": "(Sun)", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80200, + "index": 1, + "text": "(Mon)", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80200, + "index": 2, + "text": "(Tue)", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80200, + "index": 3, + "text": "(Wed)", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80200, + "index": 4, + "text": "(Thu)", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80200, + "index": 5, + "text": "(Fri)", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80200, + "index": 6, + "text": "(Sat)", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 3, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 4, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 5, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 6, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 7, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 8, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 9, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 10, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80201, + "index": 11, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 80300, + "index": 0, + "text": "Swordplay", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80300, + "index": 1, + "text": "Duel", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80300, + "index": 2, + "text": "Speed Slice", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80300, + "index": 3, + "text": "Showdown", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80301, + "index": 0, + "text": "Frisbee\u00AE", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80301, + "index": 1, + "text": "Frisbee Dog", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80301, + "index": 2, + "text": "Frisbee Golf", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80302, + "index": 0, + "text": "Power Cruising", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80302, + "index": 1, + "text": "Slalom Course", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80302, + "index": 2, + "text": "VS", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80303, + "index": 0, + "text": "Archery", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80304, + "index": 0, + "text": "Basketball", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80304, + "index": 1, + "text": "Pickup Game", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80304, + "index": 2, + "text": "3-Point Contest", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80305, + "index": 0, + "text": "Canoeing", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80305, + "index": 1, + "text": "Speed Challenge", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80305, + "index": 2, + "text": "VS", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80306, + "index": 0, + "text": "Wakeboarding", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80307, + "index": 0, + "text": "Air Sports", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80307, + "index": 1, + "text": "Island Flyover", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80307, + "index": 2, + "text": "Dogfight", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80307, + "index": 3, + "text": "Skydiving", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80308, + "index": 0, + "text": "Cycling", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80308, + "index": 1, + "text": "Road Race", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80308, + "index": 2, + "text": "VS", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80309, + "index": 0, + "text": "Table Tennis", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80309, + "index": 1, + "text": "Match", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80309, + "index": 2, + "text": "Return Challenge", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80310, + "index": 0, + "text": "Golf", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80311, + "index": 0, + "text": "Bowling", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80311, + "index": 1, + "text": "Standard Game", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80311, + "index": 2, + "text": "100-Pin Game", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80311, + "index": 3, + "text": "Spin Control", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80400, + "index": 50, + "text": "Beach", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80400, + "index": 51, + "text": "Lagoon", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80400, + "index": 52, + "text": "Lighthouse", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80400, + "index": 53, + "text": "Marina", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80400, + "index": 54, + "text": "Cavern", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80400, + "index": 55, + "text": "Shoals", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80401, + "index": 50, + "text": "Beach", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80401, + "index": 51, + "text": "Lagoon", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80401, + "index": 52, + "text": "Lighthouse", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80401, + "index": 53, + "text": "Marina", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80401, + "index": 54, + "text": "Cavern", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80401, + "index": 55, + "text": "Shoals", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80402, + "index": 50, + "text": "Beginner", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80402, + "index": 51, + "text": "Intermediate", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80402, + "index": 52, + "text": "Expert", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80403, + "index": 50, + "text": "Three Holes - Resort A", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80403, + "index": 51, + "text": "Three Holes - Resort B", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80403, + "index": 52, + "text": "Three Holes - Resort C", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80403, + "index": 53, + "text": "Three Holes - Classic A", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80403, + "index": 54, + "text": "Three Holes - Classic B", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80403, + "index": 55, + "text": "Three Holes - Classic C", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80403, + "index": 56, + "text": "Three Holes - Special", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80403, + "index": 57, + "text": "Nine Holes - Resort", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80403, + "index": 58, + "text": "Nine Holes - Classic", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80403, + "index": 59, + "text": "Eighteen Holes", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80404, + "index": 50, + "text": "Beginner", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80404, + "index": 51, + "text": "Intermediate", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80404, + "index": 52, + "text": "Expert", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80405, + "index": 50, + "text": "Three Holes - Resort A", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80405, + "index": 51, + "text": "Three Holes - Resort B", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80405, + "index": 52, + "text": "Three Holes - Resort C", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80405, + "index": 53, + "text": "Three Holes - Classic A", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80405, + "index": 54, + "text": "Three Holes - Classic B", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80405, + "index": 55, + "text": "Three Holes - Classic C", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80405, + "index": 56, + "text": "Three Holes - Special", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80405, + "index": 57, + "text": "Nine Holes - Resort", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80405, + "index": 58, + "text": "Nine Holes - Classic", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80405, + "index": 59, + "text": "Eighteen Holes", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80406, + "index": 50, + "text": "Daytime", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80406, + "index": 51, + "text": "Evening", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80406, + "index": 52, + "text": "Night", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80407, + "index": 50, + "text": "Daytime", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80407, + "index": 51, + "text": "Evening", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80407, + "index": 52, + "text": "Night", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80408, + "index": 50, + "text": "Beginner", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80408, + "index": 51, + "text": "Intermediate", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80408, + "index": 52, + "text": "Expert", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80409, + "index": 50, + "text": "Beginner", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80409, + "index": 51, + "text": "Intermediate", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80409, + "index": 52, + "text": "Expert", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80410, + "index": 50, + "text": "1-Stage Race - Around the Island", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80410, + "index": 51, + "text": "1-Stage Race - To the Beach", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80410, + "index": 52, + "text": "1-Stage Race - Across the Bridge", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80410, + "index": 53, + "text": "1-Stage Race - Over Talon Rock", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80410, + "index": 54, + "text": "1-Stage Race - Up the Volcano", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80410, + "index": 55, + "text": "1-Stage Race - Into Maka Wuhu", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80410, + "index": 56, + "text": "3-Stage Race A", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80410, + "index": 57, + "text": "3-Stage Race B", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80410, + "index": 58, + "text": "6-Stage Race", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80411, + "index": 50, + "text": "Around the Island", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80411, + "index": 51, + "text": "To the Beach", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80411, + "index": 52, + "text": "Across the Bridge", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80411, + "index": 53, + "text": "Over Talon Rock", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80411, + "index": 54, + "text": "Up the Volcano", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80411, + "index": 55, + "text": "Into Maka Wuhu", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80411, + "index": 56, + "text": "3-Stage Race A", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80411, + "index": 57, + "text": "3-Stage Race B", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80411, + "index": 58, + "text": "6-Stage Race", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80420, + "index": 50, + "text": "Three Holes", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80420, + "index": 51, + "text": "Nine Holes", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80420, + "index": 52, + "text": "Eighteen Holes", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80421, + "index": 50, + "text": "Resort A", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80421, + "index": 51, + "text": "Resort B", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80421, + "index": 52, + "text": "Resort C", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80421, + "index": 53, + "text": "Classic A", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80421, + "index": 54, + "text": "Classic B", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80421, + "index": 55, + "text": "Classic C", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80421, + "index": 56, + "text": "Special", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80422, + "index": 50, + "text": "Resort", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80422, + "index": 51, + "text": "Classic", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80430, + "index": 50, + "text": "1-Stage Race", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80430, + "index": 51, + "text": "3-Stage Race", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80430, + "index": 52, + "text": "6-Stage Race", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80430, + "index": 53, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80430, + "index": 54, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80430, + "index": 55, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80430, + "index": 56, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80430, + "index": 57, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80430, + "index": 58, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80431, + "index": 50, + "text": "Around the Island", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80431, + "index": 51, + "text": "To the Beach", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80431, + "index": 52, + "text": "Across the Bridge", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80431, + "index": 53, + "text": "Over Talon Rock", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80431, + "index": 54, + "text": "Up the Volcano", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80431, + "index": 55, + "text": "Into Maka Wuhu", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80432, + "index": 50, + "text": "3-Stage Race A", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80432, + "index": 51, + "text": "3-Stage Race B", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 80500, + "index": 0, + "text": "Swordplay", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80500, + "index": 1, + "text": "Knock your opponent\noff the platform with\nyour sword. Best\n2 out of 3 wins!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80500, + "index": 2, + "text": "Slice objects at the\nright angle as fast as\nyou can. The judge\ndecides who wins!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80500, + "index": 3, + "text": "Fight a horde\nof sword fighters!\nTake 3 hits, and it\u0027s\nover. Defeat all the\nenemies to win!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80501, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80501, + "index": 1, + "text": "Throw the Frisbee at\nthe target--the dog\nwill catch it!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80501, + "index": 2, + "text": "Play golf with a\nFrisbee! Throw the\nFrisbee into the\ntarget on the green.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80502, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80502, + "index": 1, + "text": "Cruise through the\ngates as fast as you\ncan. Bonus rings are \nworth double points!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80502, + "index": 2, + "text": "Ride through the\nrings in order, and\nrace to reach the\nfinish line first!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80503, + "index": 0, + "text": "Use the Wii Remote\nand Nunchuk to aim\nyour bow and shoot\nyour arrows right on\ntarget.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80504, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80504, + "index": 1, + "text": "It\u0027s a 3-on-3 pickup\ngame. Dribble, pass,\nshoot...or dunk it!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80504, + "index": 2, + "text": "Sink as many 3-point\nshots as you can\nbefore time runs out!\nThe bonus ball is\nworth double points!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80505, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80505, + "index": 1, + "text": "Paddle to the finish\nline! Maintain a\nsteady pace to keep\nup your speed.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80505, + "index": 2, + "text": "The first player to\npass a checkpoint\nscores 1 point.\nThe winner is the\nfirst to get 5 points!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80506, + "index": 0, + "text": "Wakeboard behind the\nboat and catch air off\nthe wake! Just be\nsure to land flat.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80507, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80507, + "index": 1, + "text": "Take a flying tour of\nWuhu Island! How\nmany \u332B points can\nyou find?", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80507, + "index": 2, + "text": "Shoot your rival\u0027s\nballoons! Whoever has\nthe most balloons left\nat the end wins.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80507, + "index": 3, + "text": "It\u0027s a long way down!\nLink up with other Mii\ncharacters as you\nfree-fall, then smile\nfor the camera.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80508, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80508, + "index": 1, + "text": "Use your hands to\npedal with the Wii\nRemote and Nunchuk.\nThe key to speed\nis good timing.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80508, + "index": 2, + "text": "Reach the goal first\nto win. The trick is\nto save your energy\nand use it at the\nright moments.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80509, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80509, + "index": 1, + "text": "Score 6 points first\nto win. Try angling\nyour paddle to put\nspin on the ball.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80509, + "index": 2, + "text": "Return as many\nserves as you can.\nThink fast and hit\nfaster!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80510, + "index": 0, + "text": "Get the ball in the\ncup in as few shots\nas you can. It\u0027s all in\nhow you swing the\nclub!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80511, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80511, + "index": 1, + "text": "Hit the lanes and\nknock down as many\npins as you can!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80511, + "index": 2, + "text": "Bowling with 100 pins!\nKnock down as many\nas you can for a max\nscore of 3,000.", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80511, + "index": 3, + "text": "It takes skill to avoid\nthe barriers in the\nlane. Put some spin\non that ball!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x54 0x03 0xFF" + }, + { + "group": 80600, + "index": 0, + "text": "Bridge at High Noon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 1, + "text": "Lighthouse at High Noon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 2, + "text": "Beach at High Noon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 3, + "text": "Mountain at High Noon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 4, + "text": "Forest at High Noon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 5, + "text": "Ruins at High Noon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 6, + "text": "Waterfall at High Noon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 7, + "text": "Cliffs at High Noon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 8, + "text": "Castle at High Noon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 9, + "text": "Volcano at High Noon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 10, + "text": "Bridge at Dusk", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 11, + "text": "Lighthouse at Dusk", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 12, + "text": "Beach at Dusk", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 13, + "text": "Mountain at Dusk", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 14, + "text": "Forest at Dusk", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 15, + "text": "Ruins at Dusk", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 16, + "text": "Waterfall at Dusk", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 17, + "text": "Cliffs at Dusk", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 18, + "text": "Castle at Dusk", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 19, + "text": "Volcano at Dusk", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 20, + "text": "Bridge at Midnight", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 21, + "text": "Lighthouse at Midnight", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 22, + "text": "Beach at Midnight", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 23, + "text": "Mountain at Midnight", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 24, + "text": "Forest at Midnight", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 25, + "text": "Ruins at Midnight", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 26, + "text": "Waterfall at Midnight", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 27, + "text": "Cliffs at Midnight", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 28, + "text": "Castle at Midnight", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 29, + "text": "Volcano at Midnight", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 30, + "text": "Bridge at High Noon\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 31, + "text": "Lighthouse at High Noon\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 32, + "text": "Beach at High Noon\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 33, + "text": "Mountain at High Noon\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 34, + "text": "Forest at High Noon\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 35, + "text": "Ruins at High Noon\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 36, + "text": "Waterfall at High Noon\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 37, + "text": "Cliffs at High Noon\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 38, + "text": "Castle at High Noon\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 39, + "text": "Volcano at High Noon\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 40, + "text": "Bridge at Dusk\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 41, + "text": "Lighthouse at Dusk\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 42, + "text": "Beach at Dusk\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 43, + "text": "Mountain at Dusk\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 44, + "text": "Forest at Dusk\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 45, + "text": "Ruins at Dusk\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 46, + "text": "Waterfall at Dusk\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 47, + "text": "Cliffs at Dusk\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 48, + "text": "Castle at Dusk\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 49, + "text": "Volcano at Dusk\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 50, + "text": "Bridge at Midnight\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 51, + "text": "Lighthouse at Midnight\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 52, + "text": "Beach at Midnight\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 53, + "text": "Mountain at Midnight\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 54, + "text": "Forest at Midnight\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 55, + "text": "Ruins at Midnight\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 56, + "text": "Waterfall at Midnight\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 57, + "text": "Cliffs at Midnight\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 58, + "text": "Castle at Midnight\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80600, + "index": 59, + "text": "Volcano at Midnight\nReverse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x01 0xFE" + }, + { + "group": 80601, + "index": 0, + "text": "Bridge at High Noon", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 1, + "text": "Lighthouse at High Noon", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 2, + "text": "Beach at High Noon", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 3, + "text": "Mountain at High Noon", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 4, + "text": "Forest at High Noon", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 5, + "text": "Ruins at High Noon", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 6, + "text": "Waterfall at High Noon", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 7, + "text": "Cliffs at High Noon", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 8, + "text": "Castle at High Noon", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 9, + "text": "Volcano at High Noon", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 10, + "text": "Bridge at Dusk", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 11, + "text": "Lighthouse at Dusk", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 12, + "text": "Beach at Dusk", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 13, + "text": "Mountain at Dusk", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 14, + "text": "Forest at Dusk", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 15, + "text": "Ruins at Dusk", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 16, + "text": "Waterfall at Dusk", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 17, + "text": "Cliffs at Dusk", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 18, + "text": "Castle at Dusk", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 19, + "text": "Volcano at Dusk", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 20, + "text": "Bridge at Midnight", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 21, + "text": "Lighthouse at Midnight", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 22, + "text": "Beach at Midnight", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 23, + "text": "Mountain at Midnight", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 24, + "text": "Forest at Midnight", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 25, + "text": "Ruins at Midnight", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 26, + "text": "Waterfall at Midnight", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 27, + "text": "Cliffs at Midnight", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 28, + "text": "Castle at Midnight", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 29, + "text": "Volcano at Midnight", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 30, + "text": "Bridge at High Noon\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 31, + "text": "Lighthouse at High Noon\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 32, + "text": "Beach at High Noon\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 33, + "text": "Mountain at High Noon\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 34, + "text": "Forest at High Noon\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 35, + "text": "Ruins at High Noon\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 36, + "text": "Waterfall at High Noon\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 37, + "text": "Cliffs at High Noon\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 38, + "text": "Castle at High Noon\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 39, + "text": "Volcano at High Noon\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 40, + "text": "Bridge at Dusk\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 41, + "text": "Lighthouse at Dusk\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 42, + "text": "Beach at Dusk\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 43, + "text": "Mountain at Dusk\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 44, + "text": "Forest at Dusk\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 45, + "text": "Ruins at Dusk\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 46, + "text": "Waterfall at Dusk\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 47, + "text": "Cliffs at Dusk\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 48, + "text": "Castle at Dusk\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 49, + "text": "Volcano at Dusk\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 50, + "text": "Bridge at Midnight\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 51, + "text": "Lighthouse at Midnight\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 52, + "text": "Beach at Midnight\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 53, + "text": "Mountain at Midnight\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 54, + "text": "Forest at Midnight\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 55, + "text": "Ruins at Midnight\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 56, + "text": "Waterfall at Midnight\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 57, + "text": "Cliffs at Midnight\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 58, + "text": "Castle at Midnight\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80601, + "index": 59, + "text": "Volcano at Midnight\nReverse", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x01 0x00" + }, + { + "group": 80610, + "index": 0, + "text": "Bridge", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 1, + "text": "Lighthouse", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 2, + "text": "Beach", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 3, + "text": "Mountain", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 4, + "text": "Forest", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 5, + "text": "Ruins", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 6, + "text": "Waterfall", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 7, + "text": "Cliffs", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 8, + "text": "Castle", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 9, + "text": "Volcano", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 10, + "text": "Bridge - R", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 11, + "text": "Lighthouse - R", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 12, + "text": "Beach - R", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 13, + "text": "Mountain - R", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 14, + "text": "Forest - R", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 15, + "text": "Ruins - R", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 16, + "text": "Waterfall - R", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 17, + "text": "Cliffs - R", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 18, + "text": "Castle - R", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80610, + "index": 19, + "text": "Volcano - R", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0x2C 0x00 0x00" + }, + { + "group": 80700, + "index": 0, + "text": "1st", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 1, + "text": "2nd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 2, + "text": "3rd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 3, + "text": "4th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 4, + "text": "5th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 5, + "text": "6th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 6, + "text": "7th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 7, + "text": "8th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 8, + "text": "9th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 9, + "text": "10th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 10, + "text": "11th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 11, + "text": "12th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 12, + "text": "13th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 13, + "text": "14th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 14, + "text": "15th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 15, + "text": "16th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 16, + "text": "17th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 17, + "text": "18th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 18, + "text": "19th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 19, + "text": "20th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 20, + "text": "21st", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 21, + "text": "22nd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 22, + "text": "23rd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 23, + "text": "24th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 24, + "text": "25th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 25, + "text": "26th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 26, + "text": "27th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 27, + "text": "28th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 28, + "text": "29th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 29, + "text": "30th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 30, + "text": "31st", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 31, + "text": "32nd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 32, + "text": "33rd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 33, + "text": "34th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 34, + "text": "35th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 35, + "text": "36th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 36, + "text": "37th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 37, + "text": "38th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 38, + "text": "39th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 39, + "text": "40th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 40, + "text": "41st", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 41, + "text": "42nd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 42, + "text": "43rd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 43, + "text": "44th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 44, + "text": "45th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 45, + "text": "46th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 46, + "text": "47th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 47, + "text": "48th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 48, + "text": "49th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 49, + "text": "50th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 50, + "text": "51st", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 51, + "text": "52nd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 52, + "text": "53rd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 53, + "text": "54th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 54, + "text": "55th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 55, + "text": "56th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 56, + "text": "57th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 57, + "text": "58th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 58, + "text": "59th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 59, + "text": "60th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 60, + "text": "61st", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 61, + "text": "62nd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 62, + "text": "63rd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 63, + "text": "64th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 64, + "text": "65th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 65, + "text": "66th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 66, + "text": "67th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 67, + "text": "68th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 68, + "text": "69th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 69, + "text": "70th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 70, + "text": "71st", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 71, + "text": "72nd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 72, + "text": "73rd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 73, + "text": "74th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 74, + "text": "75th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 75, + "text": "76th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 76, + "text": "77th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 77, + "text": "78th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 78, + "text": "79th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 79, + "text": "80th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 80, + "text": "81st", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 81, + "text": "82nd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 82, + "text": "83rd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 83, + "text": "84th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 84, + "text": "85th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 85, + "text": "86th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 86, + "text": "87th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 87, + "text": "88th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 88, + "text": "89th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 89, + "text": "90th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 90, + "text": "91st", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 91, + "text": "92nd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 92, + "text": "93rd", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 93, + "text": "94th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 94, + "text": "95th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 95, + "text": "96th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 96, + "text": "97th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 97, + "text": "98th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 98, + "text": "99th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80700, + "index": 99, + "text": "100th", + "attributes": "0x0000003C", + "ex_attributes": "0x01 0xF4 0x03 0x00" + }, + { + "group": 80800, + "index": 0, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 1, + "text": "You\u0027re halfway there!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 2, + "text": "Almost there!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 3, + "text": "Wait for the right time and then\nsprint for the finish line!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 4, + "text": "You\u0027re almost there!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 5, + "text": "They\u0027re catching up! Stay focused!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 6, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 7, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 8, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 9, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 10, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80800, + "index": 11, + "text": "Nice job!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80801, + "index": 0, + "text": "You\u0027re running out of breath!\nDon\u0027t overdo it!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80801, + "index": 1, + "text": "Try to ride behind the cyclist\nin front of you to draft them.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80801, + "index": 2, + "text": "That\u0027s it! Save energy by drafting\nbehind the cyclist in front of you!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80810, + "index": 0, + "text": "Watch out for the strong crosswind\nas you get out of the tunnel!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80810, + "index": 1, + "text": "There\u0027s a long, winding hill up ahead.\nKeep your energy up!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80810, + "index": 2, + "text": "There\u0027s a strong crosswind blowing\nout to the sea. Be careful!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80810, + "index": 3, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80810, + "index": 4, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80811, + "index": 0, + "text": "There\u0027s a sharp turn up ahead.\nPress \uE043 or \uE04B to slow down.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80811, + "index": 1, + "text": "The course goes over a small cliff up\nahead. Don\u0027t worry--keep riding!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80811, + "index": 2, + "text": "There\u0027s a strong tailwind pushing\nyou along. Nice to have a break, eh?", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80811, + "index": 3, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80811, + "index": 4, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80812, + "index": 0, + "text": "There\u0027s a series of small turns up\nahead. Steer carefully.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80812, + "index": 1, + "text": "This is Heartbreak Peak! It can live\nup to its name, so take it easy!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80812, + "index": 2, + "text": "Sharp turn to the left! Press\n\uE043 and \uE04B together to hit the brakes!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80812, + "index": 3, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80812, + "index": 4, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80813, + "index": 0, + "text": "Talon Rock is just around the corner!\nDon\u0027t hesitate--just ride straight off!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80813, + "index": 1, + "text": "If you take this right turn carefully,\nyou can do it without braking.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80813, + "index": 2, + "text": "There are more hills ahead. There\u0027s\na ways to go, so save your energy.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80813, + "index": 3, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80813, + "index": 4, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80814, + "index": 0, + "text": "Pedal hard! You might get up\nRed Iron Bridge in one shot.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80814, + "index": 1, + "text": "You\u0027re entering the town. Is anyone\nyou know cheering for you?", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80814, + "index": 2, + "text": "Behind the waterfall is a long, uphill\ntunnel. Save your energy!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80814, + "index": 3, + "text": "There are no barriers here, so be\ncareful not to fall off the edge!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80814, + "index": 4, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80815, + "index": 0, + "text": "It\u0027s still a little way up the hill.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80815, + "index": 1, + "text": "You\u0027re inside the volcano! Good\nthing those barriers are there.", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80815, + "index": 2, + "text": "It\u0027s all downhill from here. Use your\nbrakes to control your speed!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80815, + "index": 3, + "text": "There\u0027s a sharp turn just after the\nbridge. Don\u0027t be caught off guard!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80815, + "index": 4, + "text": "Turn right and cross the small bridge\nacross the river. Don\u0027t fall off!", + "attributes": "0x0000005A", + "ex_attributes": "0x01 0xD2 0x00 0xFE" + }, + { + "group": 80850, + "index": 0, + "text": "Island Loop Tunnel No. 1", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80850, + "index": 1, + "text": "Downhill Stretch", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80850, + "index": 2, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80850, + "index": 3, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80850, + "index": 4, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80851, + "index": 0, + "text": "Footbridge", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80851, + "index": 1, + "text": "Sugarsand Beach", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80851, + "index": 2, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80851, + "index": 3, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80851, + "index": 4, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80852, + "index": 0, + "text": "Heartbreak Peak", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80852, + "index": 1, + "text": "Hilltop Overlook", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80852, + "index": 2, + "text": "Swaying Bridge", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80852, + "index": 3, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80852, + "index": 4, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80853, + "index": 0, + "text": "Talon Rock", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80853, + "index": 1, + "text": "Uphill Stretch", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80853, + "index": 2, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80853, + "index": 3, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80853, + "index": 4, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80854, + "index": 0, + "text": "Red Iron Bridge", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80854, + "index": 1, + "text": "Weathered Monument", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80854, + "index": 2, + "text": "Heart of Maka Wuhu", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80854, + "index": 3, + "text": "Mountain Path", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80854, + "index": 4, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80855, + "index": 0, + "text": "Volcano", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80855, + "index": 1, + "text": "Cobbled Bridge", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80855, + "index": 2, + "text": "Slippery Bridge", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80855, + "index": 3, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 80855, + "index": 4, + "text": "", + "attributes": "0x00000046", + "ex_attributes": "0x00 0x96 0x00 0xFE" + }, + { + "group": 81000, + "index": 0, + "text": "Red Iron Bridge", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81000, + "index": 1, + "text": "This massive bridge is a famous\nlandmark of Wuhu Island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81000, + "index": 2, + "text": "The evening sunset is dazzling\nfor drivers heading into town.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81000, + "index": 3, + "text": "It\u0027s tempting to fly through it, but\ndon\u0027t get clipped by cables!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81001, + "index": 0, + "text": "Cocoba Hotel", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81001, + "index": 1, + "text": "Five-star accommodations. Sadly,\nthey don\u0027t take coupons.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81001, + "index": 2, + "text": "World-class hospitality. Stop by\nto watch the evening cycling race.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81001, + "index": 3, + "text": "Only the finest sheets are soft\nenough for this hotel\u0027s fancy beds!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81002, + "index": 0, + "text": "Cabana Lagoon", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81002, + "index": 1, + "text": "Quiet and laid-back, this is a place\nto put your feet up and relax.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81002, + "index": 2, + "text": "Nice and quiet, when the Power\nCruisers aren\u0027t racing.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81002, + "index": 3, + "text": "It\u0027s even quieter here at night.\nExcept for the occasional plane...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81003, + "index": 0, + "text": "The Queen Peach", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81003, + "index": 1, + "text": "This luxury cruiser is the picture\nof elegant opulence.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81003, + "index": 2, + "text": "While in port, the ship\u0027s extravagant\nswimming pool is closed.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81003, + "index": 3, + "text": "This ship hosts lavish parties every\nnight. Sorry, no flip-flops.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81004, + "index": 0, + "text": "The Nineteenth Hole Hotel", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81004, + "index": 1, + "text": "Drop by the cafe for a bite to eat\nafter a round of golf.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81004, + "index": 2, + "text": "Your golfing mishaps will melt away\nat the sauna and spa facilities.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81004, + "index": 3, + "text": "Most of the golfers who vacation\nhere are early-morning types.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81005, + "index": 0, + "text": "Summerstone Castle", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81005, + "index": 1, + "text": "It\u0027s not an easy hike, but the view\nfrom the castle is amazing!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81005, + "index": 2, + "text": "This castle has unbelievable\nviews--especially at sunset!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81005, + "index": 3, + "text": "The high walls of the castle make for\na perfect spot to watch fireworks.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81006, + "index": 0, + "text": "The Candle", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81006, + "index": 1, + "text": "This lighthouse was mistakenly\nbuilt at twice the planned size.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81006, + "index": 2, + "text": "Some say it was designed to look\nlike a candle, but that\u0027s just a myth.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81006, + "index": 3, + "text": "This lighthouse shines as bright as\n1,600,000 candles!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81007, + "index": 0, + "text": "Mysterious Ruins", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81007, + "index": 1, + "text": "Archaeologists have discovered\npiles of ancient coins in these ruins.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81007, + "index": 2, + "text": "These ruins have signs of ancient\ntraps built to scare away thieves.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81007, + "index": 3, + "text": "A pit was discovered in the ruins, but\neveryone is too scared to explore it!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81008, + "index": 0, + "text": "Wind Orchard", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81008, + "index": 1, + "text": "These massive windmills provide\nclean power for the whole island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81008, + "index": 2, + "text": "A warm tropical breeze keeps these\nhuge blades spinning.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81008, + "index": 3, + "text": "Imagine how fast your plane could\ngo if it had a propeller that big...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81009, + "index": 0, + "text": "Swaying Bridge", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81009, + "index": 1, + "text": "This rickety bridge is fun--and\nscary--to walk across.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81009, + "index": 2, + "text": "It takes a lot of guts to ride a\nbicycle across this bridge!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81009, + "index": 3, + "text": "In Swordplay Showdown, you\nhave to fight across this bridge!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81010, + "index": 0, + "text": "Summerstone Falls", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81010, + "index": 1, + "text": "Seven tons of water cascade every\nsecond from a height of 330 ft.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81010, + "index": 2, + "text": "You really wouldn\u0027t want to go down\nthis waterfall in a canoe!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81010, + "index": 3, + "text": "The water of Wuhu Island is full of\nhealthy minerals. Delicious!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81011, + "index": 0, + "text": "Crab Rock", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81011, + "index": 1, + "text": "This unnatural-looking rock\nformation is popular with climbers.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81011, + "index": 2, + "text": "Tourists often ask why it\u0027s called\nCrab Rock. Locals only shrug.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81011, + "index": 3, + "text": "Local golfers have nicknamed this\nrock formation the \u0022Double Bogeys.\u0022 ", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81012, + "index": 0, + "text": "Starboard Harbor", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81012, + "index": 1, + "text": "Fancy yachts from all over the world\ndrop anchor here.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81012, + "index": 2, + "text": "Many boaters like to watch the\nsunset from their yachts.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81012, + "index": 3, + "text": "The harbor is full of life even\nlate into the night.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81013, + "index": 0, + "text": "Silk Sands", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81013, + "index": 1, + "text": "The soft, smooth sand in this pit\nsquishes between your toes.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81013, + "index": 2, + "text": "The unusual type of sand here sets\nlike concrete when mixed with water.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81013, + "index": 3, + "text": "How did this pit of silky sand get up\nhere, anyway?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81014, + "index": 0, + "text": "Evergreen Grove", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81014, + "index": 1, + "text": "This untouched grove is filled\nwith rare and exotic birds.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81014, + "index": 2, + "text": "It\u0027s getting dark, so the exotic birds\nthat nest here are quieting down.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81014, + "index": 3, + "text": "At night, wild animals roam around\nthese woods.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81015, + "index": 0, + "text": "Mountain Monument", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81015, + "index": 1, + "text": "This monument looks man-made, but\nhow did they get the rocks up here?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81015, + "index": 2, + "text": "Shards of rock splintered off when\nthe monument fell over.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81015, + "index": 3, + "text": "Legends say this monument will\nright itself one day.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81016, + "index": 0, + "text": "Gateway to Wuhu", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81016, + "index": 1, + "text": "This picture-perfect arch welcomes\nyou to the island with a great view.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81016, + "index": 2, + "text": "It does look a little like Barnacle\nArch, actually...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81016, + "index": 3, + "text": "At night, the arch does look a little\nlike a gateway to another world...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81017, + "index": 0, + "text": "Sugarsand Beach", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81017, + "index": 1, + "text": "A huge white beach with sand\nlike powdered sugar.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81017, + "index": 2, + "text": "At sunset, the sky, sea, and sand\nblend into a golden glow.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81017, + "index": 3, + "text": "This is the place to go for hanging\nout after the sun goes down.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81018, + "index": 0, + "text": "Hillside Cabins", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81018, + "index": 1, + "text": "These small vacation cabins are\njust a five-minute walk from town!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81018, + "index": 2, + "text": "These cabins are a great alternative\nto the bustle of downtown living.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81018, + "index": 3, + "text": "Sounds like someone\u0027s playing an\nNES, but they need some pointers...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81019, + "index": 0, + "text": "Talon Rock", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81019, + "index": 1, + "text": "If you had wings, you could glide off\nthis cliff all the way to town.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81019, + "index": 2, + "text": "You\u0027d need a wingspan of 30 yards\nto fly...if you had wings.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81019, + "index": 3, + "text": "Some cyclists are brave enough to\nride a bike off this cliff!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81020, + "index": 0, + "text": "Power-Cruising Area", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81020, + "index": 1, + "text": "This is where the Power Cruising\nraces are held.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81020, + "index": 2, + "text": "You can press \uE046 before a race to\ncruise around the island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81020, + "index": 3, + "text": "Try free cruising on the Lighthouse\ncourse to explore at night!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81021, + "index": 0, + "text": "Camel Rock", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81021, + "index": 1, + "text": "This rock used to look more like\na camel, you know...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81021, + "index": 2, + "text": "Over the years, the wind has worn\naway the camel\u0027s humps.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81021, + "index": 3, + "text": "Maybe they should change the name\nto \u0022Not-Quite-A-Camel Rock\u0022?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81022, + "index": 0, + "text": "Duckling Lake", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81022, + "index": 1, + "text": "This glassy mountain lake is popular\nwith canoeists. Beautiful!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81022, + "index": 2, + "text": "The lake water at sunset looks\njust like orange juice!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81022, + "index": 3, + "text": "The water is so dark at night...is\nanything lurking down there?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81023, + "index": 0, + "text": "Basketball Court", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81023, + "index": 1, + "text": "All of the basketball action on Wuhu\nIsland happens here.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81023, + "index": 2, + "text": "Three-point contests are held here,\nbut it\u0027s mostly quiet in the evening.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81023, + "index": 3, + "text": "At night, the 3-Point Contest\nis held here. Fans go wild!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81024, + "index": 0, + "text": "Bowling Alley", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81024, + "index": 1, + "text": "If you\u0027re into bowling, this is the\nplace to be.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81024, + "index": 2, + "text": "This island is proud to have one of\nthe best bowling alleys around!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81024, + "index": 3, + "text": "Some people travel to Wuhu Island\njust to bowl here.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81025, + "index": 0, + "text": "Swordplay Colosseum", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81025, + "index": 1, + "text": "Swordplay duels are held in this\nspecially built floating arena.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81025, + "index": 2, + "text": "The spectators obviously enjoy\nwatching people fall in the sea!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81025, + "index": 3, + "text": "Night is the only time the colosseum\nis quiet and tranquil.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81026, + "index": 0, + "text": "Pool Patio", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81026, + "index": 1, + "text": "Table-tennis fans play all day,\nthen cool off on the pool patio.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81026, + "index": 2, + "text": "Somebody has to fish all of the stray\nballs out of the pool!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81026, + "index": 3, + "text": "The pool patio is a popular\nhangout at night.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81027, + "index": 0, + "text": "Frisbee Dog Park", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81027, + "index": 1, + "text": "Frisbee Dog competitions are held\non this beach.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81027, + "index": 2, + "text": "The sand is perfectly manicured\njust for the dogs.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81027, + "index": 3, + "text": "The dogs on Wuhu Island are even\nmore pampered than the guests!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81028, + "index": 0, + "text": "Wishing Fountain", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81028, + "index": 1, + "text": "Tourists throw coins in the\nfountain and make a wish.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81028, + "index": 2, + "text": "When the sun is right, all of the coins\nin the fountain sparkle.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81028, + "index": 3, + "text": "Nobody makes any promises about\nwishes coming true, you know!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81029, + "index": 0, + "text": "Serpent\u0027s Mouth", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81029, + "index": 1, + "text": "This spooky cave entrance seems\nto be an entrance to the ruins.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81029, + "index": 2, + "text": "Don\u0027t even think about trying\nto fly a plane in there...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81029, + "index": 3, + "text": "Some say the waves hitting this cave\nentrance make a sound like a hiss...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81030, + "index": 0, + "text": "Beginner\u0027s Wakeboarding Area", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81030, + "index": 1, + "text": "This stretch of sea is where the\nwakeboarders catch big air!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81030, + "index": 2, + "text": "The smooth water here attracts\nsome world-class wakeboarders.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81030, + "index": 3, + "text": "The secret to wakeboarding is to\nland flat! OK, it\u0027s not such a secret...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81031, + "index": 0, + "text": "Forest Monument", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81031, + "index": 1, + "text": "This is one of three mysterious\nrock monuments on the island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81031, + "index": 2, + "text": "It\u0027s almost like this monument was\nbuilt to guard the forest.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81031, + "index": 3, + "text": "Who built this strange monument,\nor is it natural?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81032, + "index": 0, + "text": "Golf Area A", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81032, + "index": 1, + "text": "Countless golfers have shaken their\nfists at these brutal water hazards.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81032, + "index": 2, + "text": "Golfers on this course quickly learn\nit pays to take a practice swing.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81032, + "index": 3, + "text": "Every blade of grass is meticulously\ncared for on this first-class course.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81033, + "index": 0, + "text": "Golf Area B", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81033, + "index": 1, + "text": "The groundskeepers can hardly keep\nup with the fast-growing grass.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81033, + "index": 2, + "text": "The wind can really pick up\noff the shore of Wedge Island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81033, + "index": 3, + "text": "Even if you have a bad day on the\ncourse, there\u0027s always the view!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81034, + "index": 0, + "text": "Golf Area C", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81034, + "index": 1, + "text": "Scuba divers often search off the\ncoast of Wedge Island for stray balls.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81034, + "index": 2, + "text": "On some of these holes, you\u0027re one\nhook or slice from the sea!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81034, + "index": 3, + "text": "Pack extra golf balls when you\u0027re\nplaying this course!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81035, + "index": 0, + "text": "Off-Road Vehicle", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81035, + "index": 1, + "text": "Only electric vehicles are allowed to\ndrive on Wuhu Island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81035, + "index": 2, + "text": "Looks like a dead battery! Hope\nthey make it home before dark...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81035, + "index": 3, + "text": "Don\u0027t worry--somebody will come\nhelp them soon. Hopefully...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81036, + "index": 0, + "text": "Toppled Monument", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81036, + "index": 1, + "text": "This ancient stone monument has\ntoppled over.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81036, + "index": 2, + "text": "How many centuries did this\nmonument stand before it fell over?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81036, + "index": 3, + "text": "Now the fallen rocks look as\nthough they belong there.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81037, + "index": 0, + "text": "Hilltop Overlook", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81037, + "index": 1, + "text": "What a view! You can see the\nbridge, lighthouse, and Wedge Island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81037, + "index": 2, + "text": "A great spot to admire the island\nat sunset.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81037, + "index": 3, + "text": "The town is nice, but people\nmostly come for the fireworks.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81038, + "index": 0, + "text": "Maka Wuhu", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81038, + "index": 1, + "text": "Inside this active volcano, lava boils\nand churns all year round.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81038, + "index": 2, + "text": "This volcano is unusual--the\ncenter is completely hollow!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81038, + "index": 3, + "text": "This volcano is active, but it\nhasn\u0027t erupted in 200 years.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81039, + "index": 0, + "text": "Heart of Maka Wuhu", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81039, + "index": 1, + "text": "This mountain tunnel bores right\nthrough the heart of the volcano.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81039, + "index": 2, + "text": "The rocks here are always wet and\nslippery--don\u0027t slip and fall in!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81039, + "index": 3, + "text": "Big, empty caves can be a little\nunnerving. Especially in a volcano!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81040, + "index": 0, + "text": "Pirate\u0027s Eye", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81040, + "index": 1, + "text": "The elements have cut a perfect hole\nin the side of this cliff.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81040, + "index": 2, + "text": "Flying through the Eye is said\nto bring good luck. If you\u0027re lucky.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81040, + "index": 3, + "text": "Don\u0027t worry--there aren\u0027t any\npirates in these waters!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81041, + "index": 0, + "text": "Island Loop Tunnel #1", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81041, + "index": 1, + "text": "This tunnel burrows through the\nmountain to link the Island Loop road.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81041, + "index": 2, + "text": "Don\u0027t even think about trying to fly\nout between the pillars!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81041, + "index": 3, + "text": "Rumor has it, there are monsters\nliving in this tunnel...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81042, + "index": 0, + "text": "Lava Tube", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81042, + "index": 1, + "text": "What could have made this massive\nhole in the side of the volcano?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81042, + "index": 2, + "text": "Apparently, it wasn\u0027t made by lava at\nall... It\u0027s man-made!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81042, + "index": 3, + "text": "Archaeologists think this tunnel was\nbuilt by ancient inhabitants.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81043, + "index": 0, + "text": "Sea Serpent Cavern", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81043, + "index": 1, + "text": "This twisting sea cave snakes\nunderneath the Mysterious Ruins.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81043, + "index": 2, + "text": "This spooky sea cave is now a\nplayground for Power Cruisers.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81043, + "index": 3, + "text": "At night, the cave has a kind of\ncalm, tranquil atmosphere.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81044, + "index": 0, + "text": "Miguel\u0027s Guide Plane", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81044, + "index": 1, + "text": "I\u0027m Miguel! If you follow me, I\u0027ll guide\nyou to some of the \u332B points!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81044, + "index": 2, + "text": "If you get lost, press \uE047 to fire a\nflare. I\u0027ll shoot one off, too!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81044, + "index": 3, + "text": "I fly around to some of the island\u0027s\nsightseeing spots.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81045, + "index": 0, + "text": "Broken Clock Tower", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81045, + "index": 1, + "text": "Don\u0027t set your watch to this\nclock tower--it stopped!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81045, + "index": 2, + "text": "Some clock fanatic stole one of\nthe clock\u0027s hands!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81045, + "index": 3, + "text": "They could repair it, but then it\nwouldn\u0027t have the same charm.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81046, + "index": 0, + "text": "Palm Boulevard", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81046, + "index": 1, + "text": "This seaside boulevard is lined\nwith majestic palm trees.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81046, + "index": 2, + "text": "It\u0027s not that grand, but it\ncreates a vacation atmosphere.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81046, + "index": 3, + "text": "The first cycling stage, \u0022Around the \nIsland,\u0022 starts here.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81047, + "index": 0, + "text": "Heartbreak Peak", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81047, + "index": 1, + "text": "It\u0027s easy to see how this steep\nhill got its name.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81047, + "index": 2, + "text": "This is a top destination for people\nwanting a serious workout.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81047, + "index": 3, + "text": "It won\u0027t break your heart, but it will\ndefinitely make it pound!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81048, + "index": 0, + "text": "Weathered Monument", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81048, + "index": 1, + "text": "This ancient monument was built\nwith massive blocks of stone.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81048, + "index": 2, + "text": "It\u0027s not entirely clear what this\nmonument\u0027s original purpose was.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81048, + "index": 3, + "text": "The stone on top weighs an\nastonishing 120 tons.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81049, + "index": 0, + "text": "Lone Cedar", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81049, + "index": 1, + "text": "It\u0027s a long hike up here, so don\u0027t\nforget anything!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81049, + "index": 2, + "text": "There\u0027s a path right into the\nvolcano nearby.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81049, + "index": 3, + "text": "How did this big cedar grow so close\nto an active volcano?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81050, + "index": 0, + "text": "Firework Launch Zone 1", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81050, + "index": 1, + "text": "They launch fireworks off from\nhere at night. It\u0027s quite a show!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81050, + "index": 2, + "text": "Firework teams compete on the\nisland for the most dazzling show.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81050, + "index": 3, + "text": "Hey! You can\u0027t fly over here at\nnight! It\u0027s dangerous!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81051, + "index": 0, + "text": "Firework Launch Zone 2", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81051, + "index": 1, + "text": "One of two firework launch zones\non Wuhu Island. Watch out at night!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81051, + "index": 2, + "text": "One of the best firework teams\nshoots off their fireworks from here.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81051, + "index": 3, + "text": "You can\u0027t fly over here at night!\nThey launch fireworks from here!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81052, + "index": 0, + "text": "Sweet Beach", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81052, + "index": 1, + "text": "This quiet, tranquil spot is one of\nthe most romantic on the island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81052, + "index": 2, + "text": "There\u0027s nothing but the soft sound\nof lapping waves. And planes.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81052, + "index": 3, + "text": "This gorgeous spot is featured on\ncountless postcards.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81053, + "index": 0, + "text": "Starry Beach", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81053, + "index": 1, + "text": "The sand grains are curiously\nshaped like stars.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81053, + "index": 2, + "text": "As you\u0027d guess, this beach is also a\ngreat place to watch the night sky.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81053, + "index": 3, + "text": "They sell bottles of the star-shaped\nsand grains as souvenirs.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81054, + "index": 0, + "text": "Tennis Courts", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81054, + "index": 1, + "text": "Unfortunately, the dogs on the beach\nran off with all the tennis balls.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81054, + "index": 2, + "text": "If you\u0027re in the mood for Table\nTennis, head to the pool patio.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81054, + "index": 3, + "text": "Hopefully, the dogs won\u0027t get the\nnext shipment of tennis balls, too...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81055, + "index": 0, + "text": "Beginner\u0027s Archery Area", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81055, + "index": 1, + "text": "Even this easiest Archery range\ntakes skill to master.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81055, + "index": 2, + "text": "Wind can push the flight of the\narrows. Planes probably don\u0027t help...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81055, + "index": 3, + "text": "Take aim and hold your breath...\nbut not for too long!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81056, + "index": 0, + "text": "Needlepoint Spire", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81056, + "index": 1, + "text": "This needle-sharp rock juts straight\nout of the sea.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81056, + "index": 2, + "text": "At almost 200 ft. high, it\u0027s one of\nthe tallest formations on the island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81056, + "index": 3, + "text": "This tall spire doesn\u0027t look nearly as\nforbidding next to Maka Wuhu!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81057, + "index": 0, + "text": "Dead-End Point", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81057, + "index": 1, + "text": "This is the end of the road. Better\nstart the long hike back!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81057, + "index": 2, + "text": "It may be a dead end, but it\u0027s got a\ngreat view of the ruins.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81057, + "index": 3, + "text": "It\u0027s getting dark! Those people\nbetter start heading back to town.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81058, + "index": 0, + "text": "Cliffside Ruins", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81058, + "index": 1, + "text": "How did they build this all the way\nup here?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81058, + "index": 2, + "text": "The stone blocks are perfectly laid--\nyou can hardly see any gaps!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81058, + "index": 3, + "text": "Ancient writing is chiseled into the\nrock, but it\u0027s getting faded.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81059, + "index": 0, + "text": "Entrance to the Mysterious Ruins", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81059, + "index": 1, + "text": "This is as far as vehicles go; from\nhere on up, you have to walk!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81059, + "index": 2, + "text": "Lots of hikers come here, but\nmost get tired and turn back.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81059, + "index": 3, + "text": "Sometimes you can hear eerie\nsinging at night...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81060, + "index": 0, + "text": "Barnacle Arch", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81060, + "index": 1, + "text": "This sea arch is just begging for\nsomeone to fly under it...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81060, + "index": 2, + "text": "There\u0027s another arch like this one\naround Wuhu Island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81060, + "index": 3, + "text": "At night, this arch looks a little like\na pair of rocky pants...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81061, + "index": 0, + "text": "Private Island", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81061, + "index": 1, + "text": "This island would be a perfect\nplace to build a vacation home.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81061, + "index": 2, + "text": "A house here would have an amazing\nview of the island and ocean.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81061, + "index": 3, + "text": "How would a home out here get\nwater and electricity?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81062, + "index": 0, + "text": "Deserted Island", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81062, + "index": 1, + "text": "It wouldn\u0027t be so bad to be\nstranded on this tropical island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81062, + "index": 2, + "text": "This small island has never been\ninhabited.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81062, + "index": 3, + "text": "This tiny island remains as a\nslice of untouched paradise.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81063, + "index": 0, + "text": "Island Loop Tunnel #2", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81063, + "index": 1, + "text": "The main road around Wuhu Island\ngoes through this tunnel.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81063, + "index": 2, + "text": "Watch out for traffic!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81063, + "index": 3, + "text": "Slow down!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81064, + "index": 0, + "text": "Stillwater Grotto", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81064, + "index": 1, + "text": "Watch out!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81064, + "index": 2, + "text": "Stop reading this and pay attention\nto not crashing!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81064, + "index": 3, + "text": "Are you sure you can make it?!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81065, + "index": 0, + "text": "Lava Monument", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81065, + "index": 1, + "text": "Nobody knows how these rocks\ngot into this pool of lava.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81065, + "index": 2, + "text": "Maybe this volcano wasn\u0027t active\nwhen this monument was built.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81065, + "index": 3, + "text": "It\u0027s so hot in here! You could bake a\npizza on these rocks...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81066, + "index": 0, + "text": "Mountain Hikers", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81066, + "index": 1, + "text": "It\u0027s a tough hike, but the view is\nworth it.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81066, + "index": 2, + "text": "It\u0027s starting to get dark. Those\nhikers better head back!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81066, + "index": 3, + "text": "Up here, you could almost reach\nout and grab the stars in the sky.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81067, + "index": 0, + "text": "Sundown Point", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81067, + "index": 1, + "text": "Every photo taken here ends up\nturning out like a postcard.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81067, + "index": 2, + "text": "The setting sun beyond the island\nmakes for a breathtaking view.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81067, + "index": 3, + "text": "People come here at night just to see\nthe moon over the sparkling sea.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81068, + "index": 0, + "text": "Runner\u0027s Circle", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81068, + "index": 1, + "text": "Die-hard runners meet up here\nbefore their daily run.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81068, + "index": 2, + "text": "Some people don\u0027t like to run in\nthe day because of the island heat.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81068, + "index": 3, + "text": "Some people prefer to run in the\nnight, when it\u0027s nice and cool.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81069, + "index": 0, + "text": "Footbridge", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81069, + "index": 1, + "text": "When it\u0027s windy, you can get\ndrenched by the waterfall mist!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81069, + "index": 2, + "text": "Occasionally, the bridge will get\nwashed away after a big storm.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81069, + "index": 3, + "text": "On a hot night, people hang out on\nthe bridge to cool off.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81070, + "index": 0, + "text": "Cedar-Tree Tunnel", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81070, + "index": 1, + "text": "The tunnel leads to the Lone Cedar\nand the volcano entrance.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81070, + "index": 2, + "text": "The path snakes past the Lone Cedar\nand to the Mountain Monument.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81070, + "index": 3, + "text": "This path goes all the way\nround the top of the mountain.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81071, + "index": 0, + "text": "Wedge Island Marina", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81071, + "index": 1, + "text": "The people carrying small bags must\nbe here for Frisbee Golf.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81071, + "index": 2, + "text": "The last ferry to the main island\nleaves at 8:30 p.m. Don\u0027t be late!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81071, + "index": 3, + "text": "The last ferry to the main island\nhas already left.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81072, + "index": 0, + "text": "Whale Watchers", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81072, + "index": 1, + "text": "Whales are often sighted off the\nisland, especially in this area.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81072, + "index": 2, + "text": "The massive whales here make\nquite a splash.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81072, + "index": 3, + "text": "You can\u0027t see anything at night,\nbut people come to watch anyway.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81073, + "index": 0, + "text": "Diving Spot", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81073, + "index": 1, + "text": "Divers of all skill levels come to\nswim with the ocean life here.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81073, + "index": 2, + "text": "Divers go down to watch the\nundersea life at all hours.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81073, + "index": 3, + "text": "Diving at night must be pretty\nscary!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81074, + "index": 0, + "text": "Sportfishing Spot", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81074, + "index": 1, + "text": "All of the sportfishing on Wuhu\nIsland is catch and release.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81074, + "index": 2, + "text": "Being out on the beautiful ocean is\nhalf the fun of sportfishing.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81074, + "index": 3, + "text": "At night, the sportfishing types hang\nup their poles and swap stories.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81075, + "index": 0, + "text": "Extreme Canoeist", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81075, + "index": 1, + "text": "Wedge Island and back?\nA piece of cake!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81075, + "index": 2, + "text": "The view of the setting sun must\nbe worth the effort to get out there!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81075, + "index": 3, + "text": "That\u0027s a long way to paddle.\nMust be lonely...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81076, + "index": 0, + "text": "Undersea-Cable Inspectors", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81076, + "index": 1, + "text": "Wedge Island is linked to the main\nisland through undersea cables.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81076, + "index": 2, + "text": "Inspecting undersea cables can\u0027t\nbe all that exciting...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81076, + "index": 3, + "text": "It\u0027s too dark to even see the\ncables, let alone inspect them!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81077, + "index": 0, + "text": "The Whale Shark", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81077, + "index": 1, + "text": "Sky, sea, and sand!\n\uFF5E Wii Sports Resort \uFF5E", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81077, + "index": 2, + "text": "Surfing, slicing, slaloming!\n\uFF5E Wii Sports Resort \uFF5E", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81077, + "index": 3, + "text": "Swinging, splashing, shooting!\n\uFF5E Wii Sports Resort \uFF5E", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81078, + "index": 0, + "text": "Seaplane Team", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81078, + "index": 1, + "text": "We\u0027re the Blue Sky Acrobatics Club.\nYou should join us sometime!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81078, + "index": 2, + "text": "We\u0027re the Sunset Acrobatics Club.\nWant to be a member?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81078, + "index": 3, + "text": "We\u0027re the Starry Sky Acrobatics\nClub. How about it--want to try?", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81079, + "index": 0, + "text": "The Sea Caddy", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81079, + "index": 1, + "text": "This regular ferry service links\nWuhu Island and Wedge Island.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81079, + "index": 2, + "text": "If you\u0027re lucky, you might spot\na whale on your ferry ride!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81079, + "index": 3, + "text": "This is the last boat back to\nWuhu Island today.", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81080, + "index": 0, + "text": "Private Island", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81080, + "index": 1, + "text": "{ VAR_1 }\u0027s resort house is\nhere! The mark of a true islander!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81080, + "index": 2, + "text": "{ VAR_1 }\u0027s resort house is\nhere. A little rustic, but what a view!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81080, + "index": 3, + "text": "{ VAR_1 }\u0027s resort house is\nhere. A little piece of paradise...", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81081, + "index": 0, + "text": "The Whale Shark", + "attributes": "0x0000006E", + "ex_attributes": "0x01 0xF4 0x00 0xFE" + }, + { + "group": 81081, + "index": 1, + "text": "You did it, { VAR_1 }! Hope you enjoyed\nflying around the island!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81081, + "index": 2, + "text": "Amazing, { VAR_1 }!\nYou were born to fly!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 81081, + "index": 3, + "text": "Wow, { VAR_1 }! You know\nthis island better than the locals!", + "attributes": "0x00000050", + "ex_attributes": "0x01 0x90 0x00 0xFE" + }, + { + "group": 89999, + "index": 0, + "text": "\u30FB\uFF1A", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 89999, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x03 0x00" + }, + { + "group": 90000, + "index": 0, + "text": "Wii Sports Resort", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xCC 0x00 0x00" + }, + { + "group": 90000, + "index": 1, + "text": "Sky, sea, and sand!", + "attributes": "0x00000064", + "ex_attributes": "0x01 0xCC 0x00 0x00" + }, + { + "group": 94000, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 94001, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94001, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94010, + "index": 0, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94010, + "index": 1, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94010, + "index": 2, + "text": "", + "attributes": "0x00000032", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 94010, + "index": 3, + "text": "", + "attributes": "0x00000032", + "ex_attributes": "0x00 0xDC 0x00 0x00" + }, + { + "group": 94020, + "index": 0, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94020, + "index": 1, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94021, + "index": 0, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94021, + "index": 1, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94022, + "index": 0, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94022, + "index": 1, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94023, + "index": 0, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94023, + "index": 1, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94024, + "index": 0, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94024, + "index": 1, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94025, + "index": 0, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 94025, + "index": 1, + "text": "", + "attributes": "0x0000005A", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 95000, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 3, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 4, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 5, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 51, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 52, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 53, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 54, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 55, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 56, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 57, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 58, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 59, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 60, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95000, + "index": 61, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95010, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95010, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95011, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95011, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95011, + "index": 51, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 3, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 4, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 5, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 6, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 7, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 8, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 9, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 51, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 52, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 53, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 54, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 55, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 56, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 57, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 58, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95012, + "index": 59, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95013, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95013, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95013, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95013, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95013, + "index": 51, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95013, + "index": 52, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95100, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95100, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95101, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95101, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95102, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95102, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95103, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95103, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95110, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95110, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95110, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95110, + "index": 3, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95110, + "index": 51, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95110, + "index": 52, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x90 0x00 0x00" + }, + { + "group": 95110, + "index": 53, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95110, + "index": 54, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95200, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95200, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95210, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95220, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95221, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95230, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95230, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95230, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95231, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95231, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95231, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95250, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95250, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95250, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95250, + "index": 51, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95250, + "index": 52, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95250, + "index": 53, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95250, + "index": 54, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x8B 0x00 0x03" + }, + { + "group": 95500, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 2, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 3, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 4, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 51, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 52, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 53, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 54, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 55, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 56, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 57, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 58, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95500, + "index": 59, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95510, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95510, + "index": 50, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 95510, + "index": 51, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x01 0x5E 0x00 0x00" + }, + { + "group": 99990, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 99990, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 99991, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 99991, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 99991, + "index": 2, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x02 0x08 0x01 0x00" + }, + { + "group": 99992, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 99992, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0xFF" + }, + { + "group": 99992, + "index": 2, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xDC 0x01 0x00" + }, + { + "group": 99992, + "index": 3, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xDC 0x01 0x00" + }, + { + "group": 99993, + "index": 0, + "text": "", + "attributes": "0x00000050", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 99993, + "index": 1, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xDC 0x01 0x00" + }, + { + "group": 99993, + "index": 2, + "text": "", + "attributes": "0x0000003C", + "ex_attributes": "0x00 0xDC 0x01 0x00" + }, + { + "group": 99994, + "index": 0, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 99994, + "index": 1, + "text": "", + "attributes": "0x00000064", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 99995, + "index": 0, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 99995, + "index": 1, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 99995, + "index": 2, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + }, + { + "group": 99996, + "index": 0, + "text": "", + "attributes": "0x00000058", + "ex_attributes": "0x02 0x08 0x00 0x00" + } + ] +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/common_message.json b/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/common_message.json new file mode 100644 index 0000000..3ed8318 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/common_message.json @@ -0,0 +1,939 @@ +{ + "encoding": "UTF16", + "group_id": 0, + "form": "MAIN", + "form_supplement": "GROUP24", + "messages": [ + { + "group": 0, + "index": 0, + "text": "Yes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 1, + "index": 0, + "text": "No", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2, + "index": 0, + "text": "Back", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3, + "index": 0, + "text": "Wii Menu", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 10, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 11, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 12, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 13, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 14, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 15, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20, + "index": 0, + "text": "Wii Sports", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21, + "index": 0, + "text": "Wii Play", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 40, + "index": 0, + "text": "An error has occurred.\nPress the Eject Button\uFF0C\nremove the Game Disc\uFF0C\nand turn the power off.\nPlease read the\nWii Operations Manual\nfor help troubleshooting.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 41, + "index": 0, + "text": "The Game Disc could not be read.\nPlease read the Wii operations\nmanual for more information.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 42, + "index": 0, + "text": "Please insert the { VAR_0 }\nGame Disc.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 43, + "index": 0, + "text": "Press a button on the Wii Remote\nif you want to continue playing.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 50, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 51, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 52, + "index": 0, + "text": "The game could not be saved.\nContinue without saving?{ WINDOW_DEFAULT_CURSOR 01 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 53, + "index": 0, + "text": "The Wii System Memory is\ncorrupted. Please refer to the\nWii Operations Manual for help\ntroubleshooting. Continue without\nsaving?{ WINDOW_DEFAULT_CURSOR 01 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 100, + "index": 0, + "text": "This game\u0027s save data is\ncorrupted and must be formatted.\nFormat the data now?{ WINDOW_DEFAULT_CURSOR 01 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 101, + "index": 0, + "text": "Continue without saving?{ WINDOW_DEFAULT_CURSOR 01 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 102, + "index": 0, + "text": "", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 103, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 104, + "index": 0, + "text": "The Wii System Memory does not\nhave enough free space. Either\nmove files to an SD Card or erase\nfiles to save. This game requires\n{ VAR_0 } empty blocks.\nOpen the Data Management\nscreen now?{ WINDOW_DEFAULT_CURSOR 01 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 105, + "index": 0, + "text": "Create a save file for { VAR_0 }?{ WINDOW_DEFAULT_CURSOR 00 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 106, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 107, + "index": 0, + "text": "A save file has been created.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 108, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 110, + "index": 0, + "text": "The Wii System Memory does not\nhave enough empty files. Either\nmove files to an SD Card or erase\nfiles to save. Open the Data\nManagement screen now?{ WINDOW_DEFAULT_CURSOR 01 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 150, + "index": 0, + "text": "The batteries in the Wii Remote\nare running low. Please check the\nbattery level on the HOME Menu.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 160, + "index": 0, + "text": "Unable to load Mii Channel data.\nPlease access the Mii Channel\nand check Mii Channel data.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 161, + "index": 0, + "text": "Unable to load Mii data stored\nin the Wii Remote.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 170, + "index": 0, + "text": "Unable to load saved data.\nPlease try again later.\nIf this problem continues, see\nthe Wii Operations Manual for\nhelp troubleshooting.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 171, + "index": 0, + "text": "Unable to save.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 200, + "index": 0, + "text": "To play with this many players,\nyou need { VAR_0 } Wii Remotes.\nPlease connect more Wii Remotes.{ WINDOW_DELAY 00 3C }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 210, + "index": 0, + "text": "Use { VAR_0 } Wii Remote with { VAR_0 } players.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 211, + "index": 0, + "text": "Use { VAR_0 } Wii Remotes with { VAR_0 } players.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 250, + "index": 0, + "text": "You can\u0027t select this until you\u0027ve\ncreated a Mii in the Mii Channel.{ WINDOW_CANCEL_SE 00 00 }{ WINDOW_DEFAULT_CURSOR 00 00 }", + "attributes": "0x00000002", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 250, + "index": 1, + "text": "Back", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 250, + "index": 2, + "text": "To Wii Menu", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 251, + "index": 0, + "text": "There are no Miis stored on this\nWii Remote. Please add a Mii in\nthe Mii Channel.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 260, + "index": 0, + "text": "You can\u0027t save your records\nwith this Mii. Continue?{ WINDOW_CANCEL_SE 01 00 }{ WINDOW_DEFAULT_CURSOR 01 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 261, + "index": 0, + "text": "You can\u0027t save My Record data\nwith this Mii. Continue?{ WINDOW_DEFAULT_CURSOR 01 00 }{ WINDOW_CANCEL_SE 01 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 270, + "index": 0, + "text": "You can\u0027t select this Mii today\nbecause it has taken the Wii\nFitness test. Try again tomorrow.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 271, + "index": 0, + "text": "The connection between the\nWii Remote and Wii console has\nbeen lost. Press \uE047 and \uE048\nsimultaneously to reconnect...", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 280, + "index": 0, + "text": "Added { VAR_1 } to\nthe player list. If you erase\nthis Mii from the Mii Channel, it\nwill be deleted from your player\nlist, so be careful!{ WINDOW_DELAY 00 B4 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 281, + "index": 0, + "text": "Added { VAR_1 } to\nthe player list. If you erase\nthis Mii from the Mii Channel, it\nwill be deleted from your player\nlist, so be careful!{ WINDOW_DELAY 00 B4 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 290, + "index": 0, + "text": "One or more Miis have been\nerased from the Mii Channel\nand will be removed from your\nplayer list.{ WINDOW_DELAY 00 B4 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 291, + "index": 0, + "text": "One or more Miis have been\nerased from the Mii Channel\nand will be removed from your\nplayer list.{ WINDOW_DELAY 00 B4 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 300, + "index": 0, + "text": "Which hand do you want to use?", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 301, + "index": 0, + "text": "Tennis", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 302, + "index": 0, + "text": "Baseball", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 303, + "index": 0, + "text": "Bowling", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 304, + "index": 0, + "text": "Golf", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 305, + "index": 0, + "text": "Boxing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 310, + "index": 0, + "text": "Swing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 311, + "index": 0, + "text": "Pitch", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 312, + "index": 0, + "text": "Bat", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 313, + "index": 0, + "text": "Bowl", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 314, + "index": 0, + "text": "Swing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 315, + "index": 0, + "text": "Stance", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 320, + "index": 0, + "text": "L", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 321, + "index": 0, + "text": "R", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 330, + "index": 0, + "text": "OK", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 400, + "index": 0, + "text": "Select Mii", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 401, + "index": 0, + "text": "Select Players", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 402, + "index": 0, + "text": "Tennis", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 403, + "index": 0, + "text": "Baseball", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 404, + "index": 0, + "text": "Bowling", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 405, + "index": 0, + "text": "Golf", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 406, + "index": 0, + "text": "Boxing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 407, + "index": 0, + "text": "Training", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 408, + "index": 0, + "text": "Wii Fitness", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 409, + "index": 0, + "text": "Main Menu", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 450, + "index": 0, + "text": "Back", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 450, + "index": 1, + "text": "Main Menu", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 451, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 452, + "index": 0, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 453, + "index": 0, + "text": "P3", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 454, + "index": 0, + "text": "P4", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 455, + "index": 0, + "text": "{ VAR_1 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 470, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 500, + "index": 0, + "text": "Select the number of players.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 510, + "index": 0, + "text": "1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 511, + "index": 0, + "text": "2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 520, + "index": 0, + "text": "1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 521, + "index": 0, + "text": "2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 522, + "index": 0, + "text": "3", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 523, + "index": 0, + "text": "4", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 530, + "index": 0, + "text": "More", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 531, + "index": 0, + "text": "OK", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 540, + "index": 0, + "text": "Wii Remotes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4C 0x00 0x00" + }, + { + "group": 541, + "index": 0, + "text": "Press \uE047 and \uE048 at the same time on\neach Wii Remote you want to add.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x53 0x00 0x00" + }, + { + "group": 600, + "index": 0, + "text": "Select a Mii for Player { VAR_0 }.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 600, + "index": 1, + "text": "Select a Mii.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 610, + "index": 0, + "text": "Wii Console", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 611, + "index": 0, + "text": "Guest", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 612, + "index": 0, + "text": "Wii Remote", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 613, + "index": 0, + "text": "Reading Mii data...\nDo not unplug the extension controller.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 620, + "index": 0, + "text": "Play with this Mii.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 620, + "index": 1, + "text": "Play with these Miis.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 630, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 631, + "index": 0, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 632, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 633, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 640, + "index": 0, + "text": "{ VAR_1 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3A 0x00 0x00" + }, + { + "group": 650, + "index": 0, + "text": "Change", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 651, + "index": 0, + "text": "OK", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 660, + "index": 0, + "text": "Guest A", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3A 0x00 0x00" + }, + { + "group": 661, + "index": 0, + "text": "Guest B", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3A 0x00 0x00" + }, + { + "group": 662, + "index": 0, + "text": "Guest C", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3A 0x00 0x00" + }, + { + "group": 663, + "index": 0, + "text": "Guest D", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3A 0x00 0x00" + }, + { + "group": 664, + "index": 0, + "text": "Guest E", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3A 0x00 0x00" + }, + { + "group": 665, + "index": 0, + "text": "Guest F", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3A 0x00 0x00" + }, + { + "group": 700, + "index": 0, + "text": "Yes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 700, + "index": 1, + "text": "Back", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 701, + "index": 0, + "text": "No", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 701, + "index": 1, + "text": "Wii Menu", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 702, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 750, + "index": 0, + "text": "Continue", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 751, + "index": 0, + "text": "Start over", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 752, + "index": 0, + "text": "Quit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 800, + "index": 0, + "text": "Attach the Wii Remote wrist strap.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 850, + "index": 0, + "text": "Slip the Wii Remote strap\nthrough the connector\nhook of the Nunchuk plug,\nthen connect the Nunchuk.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 851, + "index": 0, + "text": "Unplug the extension controller\nconnected to this Wii Remote.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 860, + "index": 0, + "text": "Put the Wii Remote strap through\nthe Nunchuk\u0027s connector hook.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 870, + "index": 0, + "text": "{ VAR_1 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 871, + "index": 0, + "text": "OK!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 880, + "index": 0, + "text": "Starting the game...\n\nHold the Wii Remote\nsecurely in your hand and\npress \uE042 and \uE043.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 900, + "index": 0, + "text": "Are you using your Wii Remote\nJacket? Make sure there are\nno people or objects around\nthat you might bump into!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 901, + "index": 0, + "text": "Why not take a break?\nYou can pause the game\nby pressing \uE045.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 999, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + } + ] +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/party_message.json b/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/party_message.json new file mode 100644 index 0000000..d45ced7 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/party_message.json @@ -0,0 +1,4075 @@ +{ + "encoding": "UTF16", + "group_id": 0, + "form": "MAIN", + "form_supplement": "GROUP24", + "messages": [ + { + "group": 1000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x01 0x90 0x64 0x00" + }, + { + "group": 1001, + "index": 0, + "text": "Wii Play", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 1002, + "index": 0, + "text": "Become a Wii Remote master!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2001, + "index": 0, + "text": "Yank it in!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x37 0x00 0x00" + }, + { + "group": 2002, + "index": 0, + "text": " You\u0027ll be able to move your pole\n more smoothly if you bring the Wii\n Remote closer to the Sensor Bar.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2003, + "index": 0, + "text": "Hold the fishing rod.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2004, + "index": 0, + "text": "Start fishing!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x72 0x00 0x00" + }, + { + "group": 2050, + "index": 0, + "text": "Touchy Fish", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 2050, + "index": 1, + "text": "Nibbler", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 2050, + "index": 2, + "text": "Plain Ol\u0027 Fish", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 2050, + "index": 3, + "text": "Small Fry", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 2050, + "index": 4, + "text": "King of the Pond", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 2050, + "index": 5, + "text": "Mystery Fish", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 2051, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2052, + "index": 0, + "text": "Bonus", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2053, + "index": 0, + "text": "Bonus!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x35 0x00 0x00" + }, + { + "group": 2054, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4C 0x00 0x00" + }, + { + "group": 2054, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4C 0x00 0x00" + }, + { + "group": 2055, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4C 0x00 0x00" + }, + { + "group": 2055, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4C 0x00 0x00" + }, + { + "group": 2056, + "index": 0, + "text": "pt.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x24 0x00 0x00" + }, + { + "group": 2056, + "index": 1, + "text": "pts.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x24 0x00 0x00" + }, + { + "group": 2057, + "index": 0, + "text": "point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x24 0x00 0x00" + }, + { + "group": 2057, + "index": 1, + "text": "points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x24 0x00 0x00" + }, + { + "group": 2058, + "index": 0, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2058, + "index": 1, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2100, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2101, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2101, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2102, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2102, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2102, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2102, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2103, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2103, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2104, + "index": 0, + "text": "Hit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x2B 0x00 0x00" + }, + { + "group": 2104, + "index": 1, + "text": "Hits", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x2B 0x00 0x00" + }, + { + "group": 2105, + "index": 0, + "text": "Bonus", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x24 0x00 0x00" + }, + { + "group": 2106, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x39 0xFB 0x00" + }, + { + "group": 2106, + "index": 1, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x39 0xFB 0x00" + }, + { + "group": 2107, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x39 0xFE 0x00" + }, + { + "group": 2107, + "index": 1, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x39 0xFE 0x00" + }, + { + "group": 2108, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0xFA 0x00" + }, + { + "group": 2108, + "index": 1, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0xFA 0x00" + }, + { + "group": 2109, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 2109, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 2110, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0xFA 0x00" + }, + { + "group": 2110, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0xFA 0x00" + }, + { + "group": 2111, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2112, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0xFA 0x00" + }, + { + "group": 2150, + "index": 0, + "text": "Level { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2150, + "index": 1, + "text": "Final Level", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2150, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2154, + "index": 0, + "text": "Finished!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 2200, + "index": 0, + "text": "Hold your paddle.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2200, + "index": 1, + "text": "\uE042: Serve", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2200, + "index": 2, + "text": "Move into position and serve.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2201, + "index": 0, + "text": "\uE042: Start", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2201, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2201, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2201, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2202, + "index": 0, + "text": "Rally 100 times!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2202, + "index": 1, + "text": "Keep rallying!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2203, + "index": 0, + "text": "Rally", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2203, + "index": 1, + "text": "Nice work!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2203, + "index": 2, + "text": "Incredible!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2204, + "index": 0, + "text": "time", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2204, + "index": 1, + "text": "times", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2204, + "index": 10, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0xFB 0x00" + }, + { + "group": 2205, + "index": 0, + "text": "11-Point Match", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2206, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2206, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2207, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0xF8 0x00" + }, + { + "group": 2207, + "index": 1, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0xF8 0x00" + }, + { + "group": 2208, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0xFB 0x00" + }, + { + "group": 2209, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2209, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2250, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2250, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2250, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2250, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2251, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2251, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2251, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2251, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2251, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2251, + "index": 5, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2253, + "index": 0, + "text": "Net", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 2253, + "index": 1, + "text": "Out", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 2253, + "index": 2, + "text": "Obstruction", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 2254, + "index": 0, + "text": "Change Serve", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 2260, + "index": 0, + "text": "P1\u0027s point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 2260, + "index": 1, + "text": "P2\u0027s point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 2260, + "index": 4, + "text": "CPU\u0027s point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 2270, + "index": 0, + "text": "Server", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2300, + "index": 0, + "text": "Move the cursor over the\ncue ball and press \uE043.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x54 0x00 0x00" + }, + { + "group": 2300, + "index": 1, + "text": "Hold down \uE043 and move the cursor to change your aim. Press \uE042 to check the table.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2300, + "index": 2, + "text": "Hold down \uE043 and\npull the Wii Remote\nstraight back.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4D 0x00 0x00" + }, + { + "group": 2300, + "index": 3, + "text": "Release \uE043 as you\npush the Wii Remote\nstraight forward.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4D 0x00 0x00" + }, + { + "group": 2300, + "index": 4, + "text": "Press \uE043 to place the cue ball wherever you want.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2300, + "index": 5, + "text": "Pull!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 2300, + "index": 6, + "text": "Push!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 2301, + "index": 0, + "text": "Foul", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2301, + "index": 1, + "text": "The cue ball failed to hit\nthe target ball first.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2301, + "index": 2, + "text": "The cue ball fell\ninto the pocket.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2301, + "index": 3, + "text": "The cue ball missed\nthe target ball.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2301, + "index": 4, + "text": "You shot a ball\noff the table.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2302, + "index": 0, + "text": "P1\u0027s turn", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2302, + "index": 1, + "text": "P2\u0027s turn", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2303, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2304, + "index": 0, + "text": "Ball points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2304, + "index": 1, + "text": "Shots", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5B 0x00 0x00" + }, + { + "group": 2304, + "index": 2, + "text": "Fouls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2304, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2304, + "index": 4, + "text": "Total", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2304, + "index": 5, + "text": "Fouls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5B 0x00 0x00" + }, + { + "group": 2304, + "index": 6, + "text": "Total", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2305, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2306, + "index": 0, + "text": "Move your Wii Remote closer to the Sensor Bar for better cue control.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2307, + "index": 0, + "text": "Shot", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2308, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2308, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2309, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2309, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2310, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2310, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2311, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2311, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2312, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 2312, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 2314, + "index": 0, + "text": "{ VAR_0 } foul", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4E 0x00 0x00" + }, + { + "group": 2314, + "index": 1, + "text": "{ VAR_0 } fouls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4E 0x00 0x00" + }, + { + "group": 2316, + "index": 0, + "text": "{ VAR_0 } foul", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4E 0x00 0x00" + }, + { + "group": 2316, + "index": 1, + "text": "{ VAR_0 } fouls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4E 0x00 0x00" + }, + { + "group": 2317, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x88 0x00 0x00" + }, + { + "group": 2319, + "index": 0, + "text": "{ VAR_0 } shot", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2319, + "index": 1, + "text": "{ VAR_0 } shots", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2320, + "index": 0, + "text": "{ VAR_0 } foul", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2320, + "index": 1, + "text": "{ VAR_0 } fouls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2321, + "index": 0, + "text": "Balls Sunk", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2400, + "index": 0, + "text": "Find this Mii!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 1, + "text": "Find 2 look-alikes!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 2, + "text": "Find 3 look-alikes!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 3, + "text": "Find 4 look-alikes!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 4, + "text": "Find 5 look-alikes!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 5, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 6, + "text": "Pick a favorite!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 7, + "text": "Find your favorite!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 8, + "text": "Find this Mii!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 9, + "text": "Find the odd Mii out!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 10, + "text": "Find 2 odd Miis out!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 11, + "text": "Find 3 odd Miis out!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 12, + "text": "Find the fastest Mii!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 13, + "text": "Find the fastest Mii!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2400, + "index": 14, + "text": "Find the sleepyhead!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 15, + "text": "Find 2 sleepyheads!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 16, + "text": "Find 3 sleepyheads!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 17, + "text": "Find the insomniac!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 18, + "text": "Find 2 insomniacs!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 19, + "text": "Find 3 insomniacs!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 20, + "text": "Find the odd Mii out!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 21, + "text": "Find the Mii you\u0027re using!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2400, + "index": 22, + "text": "Find the Miis you\u0027re using!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2401, + "index": 0, + "text": "Move the Wii Remote to zoom!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2401, + "index": 1, + "text": "Press \uE043 to check the goal.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2402, + "index": 0, + "text": "Start!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x8C 0x00 0x00" + }, + { + "group": 2403, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 2403, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 2404, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x35 0xFD 0x00" + }, + { + "group": 2404, + "index": 1, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x35 0xFD 0x00" + }, + { + "group": 2405, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 2405, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 2406, + "index": 0, + "text": "Level { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2406, + "index": 1, + "text": "Final Level", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2407, + "index": 0, + "text": "Finished!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 2408, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x43 0xFC 0x00" + }, + { + "group": 2409, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x37 0x00 0x00" + }, + { + "group": 2410, + "index": 0, + "text": "level", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2410, + "index": 1, + "text": "levels", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2411, + "index": 0, + "text": "Awesome!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2500, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2501, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2502, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2550, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2551, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2552, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2552, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2552, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2554, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2555, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2600, + "index": 0, + "text": "Goal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x81 0x00 0x00" + }, + { + "group": 2601, + "index": 0, + "text": "Game Over", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x81 0x00 0x00" + }, + { + "group": 2602, + "index": 0, + "text": "Start!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x72 0x00 0x00" + }, + { + "group": 2603, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2603, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2603, + "index": 2, + "text": "CPU", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2604, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x52 0x00 0x00" + }, + { + "group": 2604, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x52 0x00 0x00" + }, + { + "group": 2605, + "index": 0, + "text": "8-Point Game", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x39 0x00 0x00" + }, + { + "group": 2700, + "index": 0, + "text": "Perfect!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2700, + "index": 1, + "text": "Perfect!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2701, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2701, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2702, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2702, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2703, + "index": 0, + "text": "Tilt the Wii Remote on its side\nso that \uE041 is on your left.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2703, + "index": 1, + "text": "Raise the Wii Remote quickly to jump.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2703, + "index": 2, + "text": "Tilt the Wii Remote forward to run,\nand tilt it back to slow down.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2704, + "index": 0, + "text": "Perfect!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2705, + "index": 0, + "text": "Knock down the scarecrows!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 2705, + "index": 1, + "text": "Knock down those scarecrows!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 2706, + "index": 0, + "text": "Start!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 2707, + "index": 0, + "text": "Goal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 2708, + "index": 0, + "text": "Time Bonus", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2709, + "index": 0, + "text": ".", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2710, + "index": 0, + "text": "Time\u0027s Up!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 2711, + "index": 0, + "text": "Finished!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 2712, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2712, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2713, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2713, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2714, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2800, + "index": 0, + "text": "Match that pose!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x52 0x00 0x00" + }, + { + "group": 2801, + "index": 0, + "text": "Switch poses with \uE042 or \uE043.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2801, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2801, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2801, + "index": 3, + "text": "Don\u0027t let the bubbles drop!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2802, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0xFD 0x00" + }, + { + "group": 2802, + "index": 1, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0xFD 0x00" + }, + { + "group": 2803, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5B 0x00 0x00" + }, + { + "group": 2803, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5B 0x00 0x00" + }, + { + "group": 2804, + "index": 0, + "text": "X2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x2F 0x00 0x00" + }, + { + "group": 2805, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0xFD 0x00" + }, + { + "group": 2805, + "index": 1, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0xFD 0x00" + }, + { + "group": 2806, + "index": 0, + "text": "Finished!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2807, + "index": 0, + "text": "Level { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2807, + "index": 1, + "text": "Final Level", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 2808, + "index": 0, + "text": "Ready?", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2810, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2820, + "index": 0, + "text": "Level cleared!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2821, + "index": 0, + "text": "Excellent!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2822, + "index": 0, + "text": "Perfect Bonus", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2823, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2823, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2824, + "index": 0, + "text": "Awesome!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2825, + "index": 0, + "text": "Dropped a bubble!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2825, + "index": 1, + "text": "P1 missed a\nblue bubble!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2825, + "index": 2, + "text": "P2 missed a\nred bubble!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2830, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2900, + "index": 0, + "text": "Mission { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x28 0x00 0x00" + }, + { + "group": 2900, + "index": 1, + "text": "Enemy forces:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2901, + "index": 0, + "text": "Mission cleared!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2901, + "index": 1, + "text": "Mission failed!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2902, + "index": 0, + "text": "Destroyed", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2903, + "index": 0, + "text": "Bonus Tank!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 2903, + "index": 1, + "text": "Restock tanks", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2904, + "index": 0, + "text": "Mission complete!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2905, + "index": 0, + "text": "Results", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2905, + "index": 1, + "text": "Total:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2906, + "index": 0, + "text": "Mission:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2906, + "index": 1, + "text": "Tanks left: ", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2907, + "index": 0, + "text": "Start!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 2908, + "index": 0, + "text": "Hit!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 2909, + "index": 0, + "text": "Mission { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5F 0x00 0x00" + }, + { + "group": 2909, + "index": 1, + "text": "Final Mission", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5F 0x00 0x00" + }, + { + "group": 2910, + "index": 0, + "text": "Enemy tanks: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2911, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2911, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2912, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2912, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2913, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2913, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2914, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2914, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2915, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2916, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2916, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 2917, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2918, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2918, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 2919, + "index": 0, + "text": "Results", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2920, + "index": 0, + "text": "Results", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 2930, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2930, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2940, + "index": 0, + "text": "Move the tank with \u3327 or \uE041.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2940, + "index": 1, + "text": "Aim at the enemy tank.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2940, + "index": 2, + "text": "Fire with \uE043.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 2940, + "index": 3, + "text": "Drop mines with \uE043.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 6000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 6000, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 6001, + "index": 0, + "text": "Press \uE042 and \uE043.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 6002, + "index": 0, + "text": "Wii Play", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7000, + "index": 0, + "text": "Shooting Range", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7000, + "index": 1, + "text": "Find Mii", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7000, + "index": 2, + "text": "Table Tennis", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7000, + "index": 3, + "text": "Pose Mii", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7000, + "index": 4, + "text": "Laser Hockey", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7000, + "index": 5, + "text": "Billiards", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7000, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7000, + "index": 7, + "text": "Fishing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7000, + "index": 8, + "text": "Charge!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7000, + "index": 9, + "text": "Tanks!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7001, + "index": 0, + "text": "Shoot down the\ntargets by aiming the\nWii Remote at the\nscreen. Fire with \uE043.\nCombo 5 or more\nshots for a bonus!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7001, + "index": 1, + "text": "Pick out the right\nfaces from the\ncrowd. Aim with\nthe Wii Remote,\nand press \uE042 to\nselect.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7001, + "index": 2, + "text": "Move the paddle to\nreturn the ball. Aim\nthe Wii Remote at\nthe screen to move\nthe paddle. How many\ntimes can you rally?", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7001, + "index": 3, + "text": "Twist the Wii\nRemote to spin the\nMii left and right.\nSwitch poses by\npressing \uE042 or \uE043.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7001, + "index": 4, + "text": "Hit the puck into\nyour opponent\u0027s\ngoal with the Wii\nRemote. Twist the\nWii Remote left and\nright to rotate.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7001, + "index": 5, + "text": "Strike the cue ball\nwith the Wii Remote.\nAim for the ball with\nthe cursor over it.\nHow many shots will it\ntake to sink them all?", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7001, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7001, + "index": 7, + "text": "Move the Wii Remote\nforward, back, up,\ndown, left, and right\nto move the rod.\nWhen you get a\nnibble, pull back!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7001, + "index": 8, + "text": "Turn the Wii Remote\nso that \uE041 is on the\nleft. Tilt forward to\nrun, back to slow,\nand sideways to turn.\nRaise it to jump.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7001, + "index": 9, + "text": "Wii Remote: Aim\n\u3327 or \uE041: Steer tank\n\uE043: Fire\n\uE042: Drop a mine", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7002, + "index": 0, + "text": "Shoot down the\ntargets by aiming the\nWii Remote at the\nscreen. Fire with \uE043.\nCombo 5 or more\nshots for a bonus!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7002, + "index": 1, + "text": "Pick the right faces\nfrom the crowd. Aim\nwith the Wii Remote,\nand press \uE042 to\nselect. Press \uE043 for\na reminder.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7002, + "index": 2, + "text": "Move the paddle to\nreturn the ball.\nThe first player to\n11 wins. Change\nwhere it lands by\nmoving the paddle.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7002, + "index": 3, + "text": "Twist the Wii\nRemote to spin the\nMii left and right.\nSwitch poses by\npressing \uE042 or \uE043.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7002, + "index": 4, + "text": "Hit the puck into\nyour opponent\u0027s\ngoal with the Wii\nRemote. Twist the\nWii Remote left and\nright to rotate.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7002, + "index": 5, + "text": "Strike the cue ball\nwith the Wii Remote.\nAim for the ball with\nthe cursor over it.\nSink a ball to earn\nthat many points.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7002, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7002, + "index": 7, + "text": "Move the Wii Remote\nforward, back, up,\ndown, left, and right\nto move the rod.\nWhen you get a\nnibble, pull back!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7002, + "index": 8, + "text": "Turn the Wii Remote\nso that \uE041 is on the\nleft. Tilt forward to\nrun, back to slow,\nand sideways to turn.\nRaise it to jump.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7002, + "index": 9, + "text": "Wii Remote: Aim\n\u3327 or \uE041: Steer tank\n\uE043: Fire\n\uE042: Drop a mine", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7003, + "index": 0, + "text": "\uE042: Start", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7004, + "index": 0, + "text": "Stage 1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7004, + "index": 1, + "text": "Stage 2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7004, + "index": 2, + "text": "Stage 3", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7004, + "index": 3, + "text": "Stage 4", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7004, + "index": 4, + "text": "Stage 5", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7004, + "index": 5, + "text": "Stage 6", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7004, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7004, + "index": 7, + "text": "Stage 7", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7004, + "index": 8, + "text": "Stage 8", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7004, + "index": 9, + "text": "Stage 9", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7005, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7005, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7010, + "index": 0, + "text": "Shooting Range", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 7010, + "index": 1, + "text": "Find Mii", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 7010, + "index": 2, + "text": "Table Tennis", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 7010, + "index": 3, + "text": "Pose Mii", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 7010, + "index": 4, + "text": "Laser Hockey", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 7010, + "index": 5, + "text": "Billiards", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 7010, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 7010, + "index": 7, + "text": "Fishing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 7010, + "index": 8, + "text": "Charge!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 7010, + "index": 9, + "text": "Tanks!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 7020, + "index": 0, + "text": "Return to Select Players screen?{ WINDOW_DEFAULT_CURSOR 01 00 }", + "attributes": "0x00000002", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7020, + "index": 1, + "text": "Yes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7020, + "index": 2, + "text": "No", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7021, + "index": 0, + "text": "If you go back to the Select\nPlayers screen, your results\nwill be lost. Are you sure?{ WINDOW_DEFAULT_CURSOR 01 00 }", + "attributes": "0x00000002", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7021, + "index": 1, + "text": "Yes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7021, + "index": 2, + "text": "No", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 7030, + "index": 0, + "text": " { WINDOW_ALIGN 00 00 }Welcome to Wii Play!\n\n This game will teach you\n everything you need to know\n about the Wii Remote.\n In stage one, you\u0027ll use the Wii\n Remote to shoot targets.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7031, + "index": 0, + "text": " { WINDOW_ALIGN 00 00 }Stage two is now open!\n\n In stage two, you\u0027ll use the Wii\n Remote to pick the correct Mii out\n of the crowd. You\u0027ll see a lot of\n Miis out there--maybe even a few\n that you\u0027ve created yourself!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x62 0x00 0x00" + }, + { + "group": 7032, + "index": 0, + "text": " { WINDOW_ALIGN 00 00 }Stage three is now open!\n\n So, you\u0027ve gotten used to using\n the Wii Remote as a pointer, have\n you? The next stage will help\n improve your pointing speed and\n accuracy.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7033, + "index": 0, + "text": " { WINDOW_ALIGN 00 00 }Stage four is now open!\n\n Pointing directly at the screen\n is only one of the many uses for\n the Wii Remote. In the next\n stage, you\u0027ll have to twist the\n Wii Remote, too!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7034, + "index": 0, + "text": " { WINDOW_ALIGN 00 00 }Stage five is now open!\n\n Think you\u0027re getting the hang of\n twisting the Wii Remote? Then\n show off your new skills in a\n little match of Laser Hockey!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7035, + "index": 0, + "text": " { WINDOW_ALIGN 00 00 }Stage six is now open!\n\n This time, move the Wii Remote\n closer to the TV and then farther\n away for some 3-D movement.\n For the best results, sit so that\n you\u0027re centered with the TV.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7036, + "index": 0, + "text": " { WINDOW_ALIGN 00 00 }Stage seven is now open!\n\n Move the Wii Remote forward,\n back, left, and right to move the\n fishing pole. It might seem odd at\n first, but just relax, take your\n time, and enjoy yourself!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7037, + "index": 0, + "text": " { WINDOW_ALIGN 00 00 }Stage eight is now open!\n\n You\u0027ve come a long way, haven\u0027t\n you? Let\u0027s change things up a\n little by holding the Wii Remote\n sideways for this next game!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7038, + "index": 0, + "text": " { WINDOW_ALIGN 00 00 }The final stage is now open!\n\n This might seem complex, but\n you\u0027ve done great so far! You\n can use the Nunchuk to play\n this game (or just use the Wii\n Remote by itself if you like).", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7039, + "index": 0, + "text": " { WINDOW_ALIGN 00 00 }Congratulations!\n\n You are now a Wii Remote master!\n You\u0027ve just gotten a small taste\n of what the Wii Remote can do.\n Now, challenge a friend, or try\n to earn all the gold medals!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x62 0x00 0x00" + }, + { + "group": 7040, + "index": 0, + "text": "Bronze Medal Completed", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7040, + "index": 1, + "text": "Silver Medal Completed", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7040, + "index": 2, + "text": "Gold Medal Completed", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7040, + "index": 3, + "text": "Platinum Medal Completed", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7041, + "index": 0, + "text": "Congratulations!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 7050, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7050, + "index": 1, + "text": "Aim", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7050, + "index": 2, + "text": "Point left and right", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7050, + "index": 3, + "text": "Twist to rotate", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7050, + "index": 4, + "text": "Twist to rotate", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7050, + "index": 5, + "text": "Pull back to strike", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7050, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7050, + "index": 7, + "text": "Move in all directions", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7050, + "index": 8, + "text": "Tilt sideways", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 7050, + "index": 9, + "text": "Point to aim", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8000, + "index": 0, + "text": "My Record", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8001, + "index": 0, + "text": "1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8001, + "index": 1, + "text": "2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8001, + "index": 2, + "text": "3", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8001, + "index": 3, + "text": "4", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8001, + "index": 4, + "text": "5", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8004, + "index": 0, + "text": "New record!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8005, + "index": 0, + "text": "Personal best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8010, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8011, + "index": 0, + "text": "Stage 1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8011, + "index": 1, + "text": "Stage 2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8011, + "index": 2, + "text": "Stage 3", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8011, + "index": 3, + "text": "Stage 4", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8011, + "index": 4, + "text": "Stage 5", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8011, + "index": 5, + "text": "Stage 6", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8011, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8011, + "index": 7, + "text": "Stage 7", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8011, + "index": 8, + "text": "Stage 8", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8011, + "index": 9, + "text": "Stage 9", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8012, + "index": 0, + "text": "Bronze Medal Earned", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 8012, + "index": 1, + "text": "Silver Medal Earned", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 8012, + "index": 2, + "text": "Gold Medal Earned", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 8012, + "index": 3, + "text": "Platinum Medal Earned", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 8013, + "index": 0, + "text": "Congratulations!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 8020, + "index": 0, + "text": "{ VAR_0 } win", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 8020, + "index": 1, + "text": "{ VAR_0 } wins", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 8021, + "index": 0, + "text": "Play again", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8021, + "index": 1, + "text": "Play a different game", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 8022, + "index": 0, + "text": "P1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8022, + "index": 1, + "text": "P2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8100, + "index": 0, + "text": "point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8100, + "index": 1, + "text": "points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8101, + "index": 0, + "text": "level", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8101, + "index": 1, + "text": "levels", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8102, + "index": 0, + "text": "time", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8102, + "index": 1, + "text": "times", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8103, + "index": 0, + "text": "point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8103, + "index": 1, + "text": "points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8104, + "index": 0, + "text": "point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8104, + "index": 1, + "text": "points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8105, + "index": 0, + "text": "point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8105, + "index": 1, + "text": "points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8106, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8106, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8107, + "index": 0, + "text": "point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8107, + "index": 1, + "text": "points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8108, + "index": 0, + "text": "point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8108, + "index": 1, + "text": "points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8109, + "index": 0, + "text": "tank", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8109, + "index": 1, + "text": "tanks", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 8200, + "index": 0, + "text": "{ VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8200, + "index": 1, + "text": "{ VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8201, + "index": 0, + "text": "{ VAR_0 } level", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8201, + "index": 1, + "text": "{ VAR_0 } levels", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8202, + "index": 0, + "text": "{ VAR_0 } time", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8202, + "index": 1, + "text": "{ VAR_0 } times", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8203, + "index": 0, + "text": "{ VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8203, + "index": 1, + "text": "{ VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8204, + "index": 0, + "text": "{ VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8204, + "index": 1, + "text": "{ VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8205, + "index": 0, + "text": "{ VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8205, + "index": 1, + "text": "{ VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8206, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8206, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8207, + "index": 0, + "text": "{ VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8207, + "index": 1, + "text": "{ VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8208, + "index": 0, + "text": "{ VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8208, + "index": 1, + "text": "{ VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8209, + "index": 0, + "text": "{ VAR_0 } tank", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8209, + "index": 1, + "text": "{ VAR_0 } tanks", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8300, + "index": 0, + "text": "Record: { VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8300, + "index": 1, + "text": "Record: { VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8301, + "index": 0, + "text": "Record: { VAR_0 } level", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8301, + "index": 1, + "text": "Record: { VAR_0 } levels", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8302, + "index": 0, + "text": "Record: { VAR_0 } time", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8302, + "index": 1, + "text": "Record: { VAR_0 } times", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8303, + "index": 0, + "text": "Record: { VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8303, + "index": 1, + "text": "Record: { VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8304, + "index": 0, + "text": "Record: { VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8304, + "index": 1, + "text": "Record: { VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8305, + "index": 0, + "text": "Record: { VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8305, + "index": 1, + "text": "Record: { VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8306, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8306, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8307, + "index": 0, + "text": "Record: { VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8307, + "index": 1, + "text": "Record: { VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8308, + "index": 0, + "text": "Record: { VAR_0 } point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8308, + "index": 1, + "text": "Record: { VAR_0 } points", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8309, + "index": 0, + "text": "Record: { VAR_0 } tank", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 8309, + "index": 1, + "text": "Record: { VAR_0 } tanks", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 9000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9000, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9001, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9002, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9002, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9010, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9010, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9020, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9020, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9020, + "index": 10, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9020, + "index": 11, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9030, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9030, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9030, + "index": 10, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 9030, + "index": 11, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 9031, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9040, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 9090, + "index": 0, + "text": "Aim the Wii Remote at the screen.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x51 0x00 0x00" + }, + { + "group": 9090, + "index": 1, + "text": "P1: Aim the Wii Remote at the screen.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x51 0x00 0x00" + }, + { + "group": 9090, + "index": 2, + "text": "P2: Aim the Wii Remote at the screen.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x51 0x00 0x00" + }, + { + "group": 9091, + "index": 0, + "text": "Pause", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 9091, + "index": 1, + "text": "Pause", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 10000, + "index": 0, + "text": "Welcome to Wii Play.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 10001, + "index": 0, + "text": "Completed all stages!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 10002, + "index": 0, + "text": "Bronze Medal Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 10003, + "index": 0, + "text": "Silver Medal Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 10004, + "index": 0, + "text": "Gold Medal Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 10005, + "index": 0, + "text": "Platinum Medal Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 10006, + "index": 0, + "text": "All Bronze Medals Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 10007, + "index": 0, + "text": "All Silver Medals Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 10008, + "index": 0, + "text": "All Gold Medals Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 10009, + "index": 0, + "text": "All Platinum Medals Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11000, + "index": 0, + "text": "The following player has been\nadded to your Wii Play player\nlist: { VAR_1 }\n\nIf you erase this Mii from the\nMii Channel, it will be also\ndeleted from your Wii Play\nplayer list, so please be\ncareful.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11001, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11002, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11003, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11004, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11005, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11006, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11007, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11008, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11009, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11010, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11011, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11012, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11013, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11014, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11015, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11016, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11017, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11018, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11019, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11020, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11021, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11022, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11023, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11024, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11025, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11026, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11027, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11028, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11029, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11030, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11031, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11032, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11033, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11034, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11035, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11036, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11037, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11038, + "index": 0, + "text": "Congratulations!\n{ VAR_1 } has earned\na bronze medal in all of the\nminigames.\n\nYou\u0027re getting a hang of the\nWii Remote. Keep it up!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11039, + "index": 0, + "text": "Congratulations!\n{ VAR_1 } has earned\na silver medal in all of the\nminigames.\n\nYou\u0027ve got a good handle on\nusing the Wii Remote. You\u0027ve\nearned bragging rights, so go\non and tell all your friends!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11040, + "index": 0, + "text": "Congratulations!\n{ VAR_1 } has earned\na gold medal in all of the\nminigames.\n\nExcellent! You really are a\nWii Remote master now!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11041, + "index": 0, + "text": "Congratulations!\n{ VAR_1 } has earned\na platinum medal in all of the\nminigames.\n\nYou\u0027ve gone beyond mere master\nnow... It\u0027s like you and your\nWii Remote are one! Impressive!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11100, + "index": 0, + "text": "{ VAR_1 } has earned\na bronze medal in\nShooting Range. That makes\nyou a novice sharpshooter!\n\nHere\u0027s a tip: Don\u0027t just blast\neverything that moves. Instead,\ntry to chain five or more shots.\nIt\u0027s a great way to improve\nyour score--and your skills!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11100, + "index": 1, + "text": "{ VAR_1 } has earned\na silver medal in Shooting\nRange. That makes you a\nmaster sharpshooter!\n\nHere\u0027s a tip: The more targets\nyou hit in Level 2, the more\ntargets will fly out! This is\nyour chance to earn a ton of\npoints. Use it wisely.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11100, + "index": 2, + "text": "{ VAR_1 } has earned\na gold medal in Shooting\nRange. That makes you a\nsharpshooting wiz!\n\nHere\u0027s a tip: Focus on accuracy\ninstead of on peppering targets\nwith shots. You\u0027ll earn more\npoints for shots hit in a row.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11100, + "index": 3, + "text": "{ VAR_1 } has earned\na platinum medal in Shooting\nRange. That makes you an\nunrivaled sharpshooter!\n\nYou don\u0027t need any more advice.\nHowever, see how well you can\nscore with two Wii Remotes!\nImpress your friends and\nintimidate your enemies!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11101, + "index": 0, + "text": "{ VAR_1 } has earned\na bronze medal in Find Mii.\nYou\u0027ve got good eyes!\n\nHere\u0027s a tip: The more Miis\nyou make in the Mii Channel,\nthe more familiar the faces\nhere will be. Familiar faces\nmight make things easier...", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11101, + "index": 1, + "text": "{ VAR_1 } has earned\na silver medal in Find Mii.\nYou\u0027ve got sharp eyes!\n\nHere\u0027s a tip: Use your sharp\neyes in the real world to find\nlost keys and spare change!\nBus fare is never far away!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11101, + "index": 2, + "text": "{ VAR_1 } has earned\na gold medal in Find Mii.\nYou\u0027ve got eagle eyes!\n\nYou have good observation skills\nand a great memory...or maybe\nyou\u0027re just good at remembering\nfaces.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11101, + "index": 3, + "text": "{ VAR_1 } has earned\na platinum medal in Find\nMii. Are you...clairvoyant?\n\nWe\u0027ve got nothing but praise\nfor you...but you already knew\nthat, didn\u0027t you?", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11102, + "index": 0, + "text": "{ VAR_1 } has earned\na bronze medal in Table\nTennis. You\u0027ve got the makings\nof a master player!\n\nHere\u0027s a tip: The trick to\nimproving your game is to\nkeep your paddle movements\nsmall.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11102, + "index": 1, + "text": "{ VAR_1 } has earned\na silver medal in Table\nTennis. You\u0027re the team captain!\n\nYou\u0027ve improved quite a bit.\nNow, work on your reaction\ntime. With a little focus,\n100 rallies will be no problem\nat all!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11102, + "index": 2, + "text": "{ VAR_1 } has earned\na gold medal in Table\nTennis. You\u0027re a table-tennis\nterror!\n\nRemember back when 100 rallies\nseemed impossible? Now, you\ncan probably beat that in your\nsleep!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11102, + "index": 3, + "text": "{ VAR_1 } has earned\na platinum medal in Table\nTennis. You\u0027re a table-tennis\nwizard!\n\nYou need no more advice.\nNow, try to rally 999 times!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11103, + "index": 0, + "text": "{ VAR_1 } has earned\na bronze medal in Pose Mii.\nYou are now an apprentice Mii\nposer.\n\nJust relax and pop those\nbubbles one at a time.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11103, + "index": 1, + "text": "{ VAR_1 } has earned\na silver medal in Pose Mii.\nYou are now a true Mii poser.\n\nLearning to switch poses quickly\nis the key to improvement.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11103, + "index": 2, + "text": "{ VAR_1 } has earned\na gold medal in Pose Mii.\nYou are now a master poser.\n\nThe only way to improve is to\nmaster using both the A and B\nButtons to change your poses.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11103, + "index": 3, + "text": "{ VAR_1 } has earned\na platinum medal in Pose Mii.\nYou are now a Mii poser par\nexcellence.\n\nShow off your posing skills to\nyour friends, and be the envy\nof all who behold you!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11104, + "index": 0, + "text": "{ VAR_1 } has earned\na bronze medal in Laser\nHockey. This makes you a\nmember of the team!\n\nHere\u0027s a tip: Try to catch your\nopponent off guard by\nricocheting the puck off\nthe wall.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11104, + "index": 1, + "text": "{ VAR_1 } has earned\na silver medal in Laser\nHockey. This makes you captain\nof the team!\n\nHere\u0027s a tip: The back of the\npaddle bounces the puck less\nthan the front does. Make the\npuck travel faster by using the\nends of the paddle.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11104, + "index": 2, + "text": "{ VAR_1 } has earned\na gold medal in Laser\nHockey. This makes you\nmanager of the team!\n\nHere\u0027s a tip: Press the A and B\nButtons together during the\ncountdown to change the\npaddle\u0027s shape!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11104, + "index": 3, + "text": "{ VAR_1 } has earned\na platinum medal in Laser\nHockey. This makes you the\nowner of the team!\n\nYou have nothing more to learn!\nJust remember to wear your\nmouth guard--hockey can get\nrough...even Laser Hockey!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11105, + "index": 0, + "text": "{ VAR_1 } has earned\na bronze medal in Billiards.\nYou\u0027re a pool shark in training!\n\nHere\u0027s a tip: Strike near the\nbottom of the cue ball to give\nit backspin. Hit it near the\ntop to give it topspin.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11105, + "index": 1, + "text": "{ VAR_1 } has earned\na silver medal in Billiards.\nYou\u0027re a pool shark now!\n\nHere\u0027s a tip: Move the cursor\nwhile holding the B Button to\nchange where you aim. You\ncan jump the ball by aiming\nand hitting from the top.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11105, + "index": 2, + "text": "{ VAR_1 } has earned\na gold medal in Billiards.\nYou\u0027re not just a pool shark!\nYou\u0027re a great white!\n\nHere\u0027s a tip: Strike the cue ball\non its left or right side to\ngive it some spin. Try this\nwhen your target is at a tricky\nangle.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11105, + "index": 3, + "text": "{ VAR_1 } has earned\na platinum medal in Billiards.\nYou eat pool sharks for\nbreakfast!\n\nYou don\u0027t need any more advice.\nJust go show off for your\nfriends!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11106, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11106, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11106, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11106, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11107, + "index": 0, + "text": "{ VAR_1 } has earned\na bronze medal in Fishing.\nYou\u0027re a vacation fisher, aren\u0027t\nyou?\n\nHere\u0027s a tip: Small fries will\njust swim away if you don\u0027t\nreel them in. They\u0027ll disappear\nfrom the pond if you ignore\nthem.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11107, + "index": 1, + "text": "{ VAR_1 } has earned\na silver medal in Fishing.\nYou\u0027re a fishing fanatic!\n\nHere\u0027s a tip: The red touchy\nfish swim away if you move\nthe hook behind them. Move\nthe hook toward their heads.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11107, + "index": 2, + "text": "{ VAR_1 } has earned\na gold medal in Fishing.\nYou\u0027re a master angler!\n\nIf you want to improve, try\ncatching all the bonus fish.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11107, + "index": 3, + "text": "{ VAR_1 } has earned\na platinum medal in Fishing.\nWho\u0027s king of the pond now!?\n\nYou don\u0027t need any more advice.\nNo fish can escape your hook!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11108, + "index": 0, + "text": "{ VAR_1 } has earned\na bronze medal in Charge!\nThat makes you a tenderfoot!\n\nHere\u0027s a tip: The scarecrow\nkings (the ones with the crowns)\nare worth more points. Be sure\nyou don\u0027t leave a single one\nstanding!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11108, + "index": 1, + "text": "{ VAR_1 } has earned\na silver medal in Charge!\nYou\u0027re a regular rodeo clown!\n\nHere\u0027s a tip: When you see a\ngroup of scarecrows all in a\nrow, knock them all down to\nearn bonus points.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11108, + "index": 2, + "text": "{ VAR_1 } has earned\na gold medal in Charge!\nYou\u0027re an honest-to-goodness\ncowpoke, aren\u0027t you?\n\nHere\u0027s a tip: Tilt the Wii\nRemote forward right when you\nsee the word Start to get an\nextra boost of speed out of\nthe gate.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11108, + "index": 3, + "text": "{ VAR_1 } has earned\na platinum medal in Charge!\nI reckon you fancy yourself a\nregular bronco buster, huh?\n\nYou don\u0027t need any more advice.\nNow, it\u0027s time to show off for\nyour friends!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11109, + "index": 0, + "text": "{ VAR_1 } has earned\na bronze medal in Tanks!\nYou\u0027ve been promoted to private,\nfirst class!\n\nHere\u0027s a tip: You can destroy\ncertain walls with a mine. Use\nthis to create a shortcut or an\nescape route.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11109, + "index": 1, + "text": "{ VAR_1 } has earned\na silver medal in Tanks!\nYou\u0027ve been promoted to\nsergeant!\n\nHere\u0027s a tip: Some enemies can\u0027t\ndodge your shells very well, and\nsome drive right over mines.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11109, + "index": 2, + "text": "{ VAR_1 } has earned\na gold medal in Tanks!\nYou\u0027ve been promoted to\ngeneral!\n\nOutstanding battle results!\nYou will, no doubt, receive more\nmissions in the future.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 11109, + "index": 3, + "text": "{ VAR_1 } has earned\na platinum medal in Tanks!\nYou\u0027ve been promoted to five-\nstar general! Sir! Impressive\nwork, sir!\n\nYou have superior judgment,\nfocus, and fighting skills, sir!\nYou might have what it takes\nto clear Mission 100, sir!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + } + ] +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/sports_message.json b/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/sports_message.json new file mode 100644 index 0000000..ca21f57 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Data/JSystem/JMessage/MsgRes/sports_message.json @@ -0,0 +1,8408 @@ +{ + "encoding": "UTF16", + "group_id": 0, + "form": "MAIN", + "form_supplement": "GROUP24", + "messages": [ + { + "group": 0, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 1, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 999, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 1000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 1110, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 1300, + "index": 0, + "text": "Returning Balls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 1301, + "index": 0, + "text": "Return the ball inside\nthe court. Just relax\nand focus on hitting\nthe ball.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 1310, + "index": 0, + "text": "Timing Your Swing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 1311, + "index": 0, + "text": "Return the ball into\nthe orange bar. Watch\nyour timing, and aim\neach shot carefully.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 1320, + "index": 0, + "text": "Target Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 1321, + "index": 0, + "text": "Volley the ball off\nthe wall and hit the\ntargets. Controlling\nyour swing speed and\nstrength is essential\nin aiming your shots.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2100, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2101, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2101, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2101, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2101, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2102, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2300, + "index": 0, + "text": "Hitting Home Runs", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2301, + "index": 0, + "text": "Watch the ball, and\ntry to hit it out of\nthe park. Timing is\neverything!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2310, + "index": 0, + "text": "Swing Control", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2311, + "index": 0, + "text": "Hit into the target\nzones on the field.\nMaster this, and you\u0027ll\nbe a pro in no time!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 2320, + "index": 0, + "text": "Batting Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 2321, + "index": 0, + "text": "The pitcher will keep\nthrowing those balls,\nso focus on making\nfast, compact swings!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 3000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3001, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3002, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3002, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3003, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3100, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3101, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3200, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3201, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3300, + "index": 0, + "text": "Putting", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3301, + "index": 0, + "text": "Drop it in the cup with\na single putt. Check\nthe lay of the green\nby pressing \uE047.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 3310, + "index": 0, + "text": "Hitting the Green", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3311, + "index": 0, + "text": "Land the ball as close\nto the pin as possible.\nPractice your stroke\nto check the power of\nyour swing. Hold \uE042\nto approach the ball.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 3320, + "index": 0, + "text": "Target Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 3321, + "index": 0, + "text": "Hit the target with\nthe ball. Before you\ntake your swing, be\nsure to read the\nwind direction.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 4000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 4001, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 4100, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 4101, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 5000, + "index": 0, + "text": "Boxing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 5300, + "index": 0, + "text": "Throwing Punches", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 5301, + "index": 0, + "text": "Watch your trainer\u0027s\nmitts, and try to hit\nthem. You lose points\nif you hit your trainer.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 5310, + "index": 0, + "text": "Dodging", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 5311, + "index": 0, + "text": "Your trainer throws\nball after ball at you.\nMove left and right\nto avoid getting hit.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 5320, + "index": 0, + "text": "Working the Bag", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 5321, + "index": 0, + "text": "Throw punches at\nthe punching bags\nuntil you knock them\noff their chains.\nWell-aimed combo\npunches are key.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 6000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 6300, + "index": 0, + "text": "Picking Up Spares", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 6301, + "index": 0, + "text": "Knock down the pins\nwith a single throw.\nTwist your wrist to\ncurve the ball.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 6310, + "index": 0, + "text": "Spin Control", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 6311, + "index": 0, + "text": "Avoid the barriers in\nthe lane and knock\ndown the pin. You\u0027ll\nhave to balance speed\nand spin.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 6320, + "index": 0, + "text": "Power Throws", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 6321, + "index": 0, + "text": "Knock down as many\npins as you can. A\nnew row will be added\nafter each set. Strikes\ndouble your score!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 7000, + "index": 0, + "text": "Today\u0027s fitness test uses\nthe Nunchuk. Are you able to use\nthe Nunchuk?{ WINDOW_DEFAULT_CURSOR 00 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7001, + "index": 0, + "text": "Quit the Wii Fitness test?\n\nIf you quit, you can\u0027t do another\nWii Fitness test until tomorrow.{ WINDOW_DEFAULT_CURSOR 01 00 }{ WINDOW_CANCEL_SE 01 00 }", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7002, + "index": 0, + "text": "Quitting today\u0027s fitness test.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7003, + "index": 0, + "text": "", + "attributes": "0x00000002", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7004, + "index": 0, + "text": "", + "attributes": "0x00000001", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7005, + "index": 0, + "text": "", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7006, + "index": 0, + "text": "Selecting events that do\nnot use the Nunchuk.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7010, + "index": 0, + "text": "You can take only one Wii Fitness\ntest each day. You\u0027ve already\ntaken the test today, so please\ntry again tomorrow.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7020, + "index": 0, + "text": "", + "attributes": "0x000003E7", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 7030, + "index": 0, + "text": "Wii Fitness\n\nTest your speed, stamina, and\nstrength to determine your Wii\nFitness Age. Train every day to\nlower your Wii Fitness Age.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8000, + "index": 0, + "text": "{ VAR_1 }\ndebuted in Wii Sports on\n{ VAR_0 } at { VAR_0 }.", + "attributes": "0x00000001", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8010, + "index": 0, + "text": "You\u0027re a tennis pro!", + "attributes": "0x00000002", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8011, + "index": 0, + "text": "You\u0027re a baseball pro!", + "attributes": "0x00000001", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8012, + "index": 0, + "text": "You\u0027re a pro bowler!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8013, + "index": 0, + "text": "You\u0027re a pro golfer!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8014, + "index": 0, + "text": "You\u0027re a pro boxer!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8020, + "index": 0, + "text": "You\u0027ve lost your\ntennis pro status!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8021, + "index": 0, + "text": "You\u0027ve lost your\nbaseball pro status!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8022, + "index": 0, + "text": "You\u0027ve lost your\nbowling pro status!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8023, + "index": 0, + "text": "You\u0027ve lost your\ngolf pro status!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8024, + "index": 0, + "text": "You\u0027ve lost your\nboxing pro status!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8030, + "index": 0, + "text": "New personal best!\nGolf: Stroke play", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8030, + "index": 1, + "text": "Score: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8030, + "index": 2, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8031, + "index": 0, + "text": "New personal best!\nBowling: Score play", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8031, + "index": 1, + "text": "Score: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8031, + "index": 2, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8040, + "index": 0, + "text": "New personal best!\n{ VAR_0 }: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8040, + "index": 1, + "text": "Score: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8040, + "index": 2, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8040, + "index": 3, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8041, + "index": 0, + "text": "Home runs: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8041, + "index": 1, + "text": "{ VAR_0 } homer", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8041, + "index": 2, + "text": "Total distance: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8041, + "index": 3, + "text": "{ VAR_0 } foot", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8041, + "index": 4, + "text": "{ VAR_0 } feet", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8041, + "index": 5, + "text": "{ VAR_0 } homers", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8042, + "index": 0, + "text": "Hits: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8042, + "index": 1, + "text": "{ VAR_0 } hit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8042, + "index": 2, + "text": "{ VAR_0 } hits", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8043, + "index": 0, + "text": "Successful hits: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8043, + "index": 1, + "text": "{ VAR_0 } hit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8043, + "index": 2, + "text": "{ VAR_0 } hits", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8044, + "index": 0, + "text": "Pins knocked down: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8044, + "index": 1, + "text": "{ VAR_0 } pin", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8044, + "index": 2, + "text": "{ VAR_0 } pins", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8045, + "index": 0, + "text": "Cup-in: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8045, + "index": 1, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8045, + "index": 2, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8046, + "index": 0, + "text": "Total remaining: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8046, + "index": 1, + "text": "{ VAR_0 } yard", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8046, + "index": 2, + "text": "{ VAR_0 } yards", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8050, + "index": 0, + "text": "You got a { VAR_0 } medal in\n{ VAR_0 }: { VAR_0 }!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8060, + "index": 0, + "text": "Wii Fitness Results", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8060, + "index": 1, + "text": "{ VAR_0 } years old!\nYou\u0027ve taken off { VAR_0 } year!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8060, + "index": 2, + "text": "{ VAR_0 } years old!\nYou\u0027ve taken off { VAR_0 } years!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8070, + "index": 0, + "text": "Impressive! You hit a hole\nin one on hole { VAR_0 } in a\nnine-hole game of golf!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8070, + "index": 1, + "text": "Impressive! You hit a hole\nin one on hole { VAR_0 } in a\nthree-hole game of golf!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 8100, + "index": 0, + "text": "Wii Sports Debut", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8110, + "index": 0, + "text": "Pro Status Earned", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8111, + "index": 0, + "text": "Pro Status Lost", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8112, + "index": 0, + "text": "New Personal Best Set", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8113, + "index": 0, + "text": "A New Champion!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8114, + "index": 20, + "text": "Impressive!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8114, + "index": 30, + "text": "Impressive!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8120, + "index": 0, + "text": "New Personal Best Set", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8121, + "index": 0, + "text": "Platinum Medal Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8121, + "index": 1, + "text": "Gold Medal Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8121, + "index": 2, + "text": "Silver Medal Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8121, + "index": 3, + "text": "Bronzed Medal Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8122, + "index": 0, + "text": "All Gold Medals Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8123, + "index": 0, + "text": "All Platinum Medals Earned!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8130, + "index": 0, + "text": "Wii Fitness Results", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8200, + "index": 0, + "text": "Wii Sports Debut", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8210, + "index": 0, + "text": "Tennis Pro Status Reached!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8210, + "index": 10, + "text": "Baseball Pro Status Reached!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8210, + "index": 20, + "text": "Bowling Pro Status Reached!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8210, + "index": 30, + "text": "Golf Pro Status Reached!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8210, + "index": 40, + "text": "Boxing Pro Status Reached!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8211, + "index": 0, + "text": "Tennis Pro Status Lost!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8211, + "index": 10, + "text": "Baseball Pro Status Lost!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8211, + "index": 20, + "text": "Bowling Pro Status Lost!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8211, + "index": 30, + "text": "Golf Pro Status Lost!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8211, + "index": 40, + "text": "Boxing Pro Status Lost!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8212, + "index": 20, + "text": "Bowling\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8212, + "index": 30, + "text": "Golf\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8213, + "index": 0, + "text": "Tennis\n Beat the tennis champ!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8213, + "index": 10, + "text": "Baseball\n Beat the baseball champ!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8213, + "index": 40, + "text": "Boxing\n Beat the boxing champ!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 0, + "text": "Tennis: Target Practice\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 1, + "text": "Tennis: Timing Your Swing\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 2, + "text": "Tennis: Returning Balls\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 10, + "text": "Baseball: Hitting Home Runs\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 11, + "text": "Baseball: Swing Control\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 12, + "text": "Baseball: Batting Practice\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 20, + "text": "Bowling: Picking Up Spares\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 21, + "text": "Bowling: Power Throws\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 22, + "text": "Bowling: Spin Control\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 30, + "text": "Golf: Putting\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 31, + "text": "Golf: Hitting the Green\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 32, + "text": "Golf: Target Practice\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 40, + "text": "Boxing: Working the Bag\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 41, + "text": "Boxing: Dodging\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8220, + "index": 42, + "text": "Boxing: Throwing Punches\n New Personal Best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 0, + "text": "Tennis: Target Practice\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 1, + "text": "Tennis: Target Practice\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 2, + "text": "Tennis: Target Practice\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 3, + "text": "Tennis: Target Practice\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 4, + "text": "Tennis: Timing Your Swing\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 5, + "text": "Tennis: Timing Your Swing\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 6, + "text": "Tennis: Timing Your Swing\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 7, + "text": "Tennis: Timing Your Swing\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 8, + "text": "Tennis: Returning Balls\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 9, + "text": "Tennis: Returning Balls\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 10, + "text": "Tennis: Returning Balls\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 11, + "text": "Tennis: Returning Balls\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 20, + "text": "Baseball: Hitting Home Runs\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 21, + "text": "Baseball: Hitting Home Runs\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 22, + "text": "Baseball: Hitting Home Runs\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 23, + "text": "Baseball: Hitting Home Runs\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 24, + "text": "Baseball: Swing Control\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 25, + "text": "Baseball: Swing Control\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 26, + "text": "Baseball: Swing Control\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 27, + "text": "Baseball: Swing Control\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 28, + "text": "Baseball: Batting Practice\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 29, + "text": "Baseball: Batting Practice\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 30, + "text": "Baseball: Batting Practice\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 31, + "text": "Baseball: Batting Practice\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 40, + "text": "Bowling: Picking Up Spares\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 41, + "text": "Bowling: Picking Up Spares\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 42, + "text": "Bowling: Picking Up Spares\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 43, + "text": "Bowling: Picking Up Spares\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 44, + "text": "Bowling: Power Throws\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 45, + "text": "Bowling: Power Throws\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 46, + "text": "Bowling: Power Throws\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 47, + "text": "Bowling: Power Throws\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 48, + "text": "Bowling: Spin Control\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 49, + "text": "Bowling: Spin Control\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 50, + "text": "Bowling: Spin Control\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 51, + "text": "Bowling: Spin Control\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 60, + "text": "Golf: Putting \n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 61, + "text": "Golf: Putting \n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 62, + "text": "Golf: Putting \n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 63, + "text": "Golf: Putting \n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 64, + "text": "Golf: Hitting the Green\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 65, + "text": "Golf: Hitting the Green\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 66, + "text": "Golf: Hitting the Green\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 67, + "text": "Golf: Hitting the Green\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 68, + "text": "Golf: Target Practice\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 69, + "text": "Golf: Target Practice\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 70, + "text": "Golf: Target Practice\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 71, + "text": "Golf: Target Practice\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 80, + "text": "Boxing: Working the Bag\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 81, + "text": "Boxing: Working the Bag\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 82, + "text": "Boxing: Working the Bag\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 83, + "text": "Boxing: Working the Bag\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 84, + "text": "Boxing: Dodging\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 85, + "text": "Boxing: Dodging\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 86, + "text": "Boxing: Dodging\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 87, + "text": "Boxing: Dodging\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 88, + "text": "Boxing: Throwing Punches\n Earned a platinum medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 89, + "text": "Boxing: Throwing Punches\n Earned a gold medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 90, + "text": "Boxing: Throwing Punches\n Earned a silver medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8221, + "index": 91, + "text": "Boxing: Throwing Punches\n Earned a bronze medal!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8300, + "index": 0, + "text": "The following player has been\nadded to the player list:\n{ VAR_1 }{ VAR_0 }\n\nIf you erase this Mii from the\nMii Channel, it will be deleted\nfrom your player list, so be\ncareful.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8310, + "index": 0, + "text": "The following player has become\na tennis pro:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8310, + "index": 10, + "text": "The following player has become\na baseball pro:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8310, + "index": 20, + "text": "The following player has become\na bowling pro:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8310, + "index": 30, + "text": "The following player has become\na golf pro:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8310, + "index": 40, + "text": "The following player has become\na boxing pro:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8311, + "index": 0, + "text": "The following player has lost\nthe title of tennis pro:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8311, + "index": 10, + "text": "The following player has lost\nthe title of baseball pro:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8311, + "index": 20, + "text": "The following player has lost\nthe title of bowling pro:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8311, + "index": 30, + "text": "The following player has lost\nthe title of golf pro:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8311, + "index": 40, + "text": "The following player has lost\nthe title of boxing pro:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8312, + "index": 20, + "text": "The following player has set a\nnew personal best in bowling:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8312, + "index": 30, + "text": "The following player has set a\nnew personal best in three-hole\ngolf at the beginner level:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8312, + "index": 31, + "text": "The following player has set a\nnew personal best in three-hole\ngolf at the intermediate level:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8312, + "index": 32, + "text": "The following player has set a\nnew personal best in three-hole\ngolf at the expert level:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8312, + "index": 33, + "text": "The following player has set a\nnew personal best in nine-hole\ngolf:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8313, + "index": 0, + "text": "{ VAR_1 }{ VAR_0 } beat\ntennis pro { VAR_0 }.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8313, + "index": 10, + "text": "{ VAR_1 }{ VAR_0 } beat\nbaseball pro { VAR_0 }.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8313, + "index": 40, + "text": "{ VAR_1 }{ VAR_0 } beat\nboxing pro { VAR_0 }.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8314, + "index": 30, + "text": "The following player hit a hole\nin one on the first hole in golf:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8314, + "index": 31, + "text": "The following player hit a hole\nin one on the second hole in\ngolf:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8314, + "index": 32, + "text": "The following player hit a hole\nin one on the third hole in\ngolf:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8314, + "index": 33, + "text": "The following player hit a hole\nin one on the fourth hole in\ngolf:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8314, + "index": 34, + "text": "The following player hit a hole\nin one on the fifth hole in\ngolf:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8314, + "index": 35, + "text": "The following player hit a hole\nin one on the sixth hole in\ngolf:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8314, + "index": 36, + "text": "The following player hit a hole\nin one on the seventh hole in\ngolf:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8314, + "index": 37, + "text": "The following player hit a hole\nin one on the eighth hole in\ngolf:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8314, + "index": 38, + "text": "The following player hit a hole\nin one on the nine hole in golf:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8314, + "index": 50, + "text": "{ VAR_1 }{ VAR_0 } bowled\na perfect game.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8319, + "index": 0, + "text": "Score: { VAR_0 } \u21D2 { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 0, + "text": "The following player has set a\nnew personal best in Tennis:\nTarget Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 1, + "text": "The following player has set a\nnew personal best in Tennis:\nTiming Your Swing:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 2, + "text": "The following player has set a\nnew personal best in Tennis:\nReturning Balls:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 10, + "text": "The following player has set a\nnew personal best in Baseball:\nHitting Home Runs:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 11, + "text": "The following player has set a\nnew personal best in Baseball:\nSwing Control:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 12, + "text": "The following player has set a\nnew personal best in Baseball:\nBatting Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 20, + "text": "The following player has set a\nnew personal best in Bowling:\nPicking Up Spares:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 21, + "text": "The following player has set a\nnew personal best in Bowling:\nPower Throws:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 22, + "text": "The following player has set a\nnew personal best in Bowling:\nSpin Control:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 30, + "text": "The following player has set a\nnew personal best in Golf:\nPutting:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 31, + "text": "The following player has set a\nnew personal best in Golf:\nHitting the Green:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 32, + "text": "The following player has set a\nnew personal best in Golf:\nTarget Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 40, + "text": "The following player has set a\nnew personal best in Boxing:\nWorking the Bag:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 41, + "text": "The following player has set a\nnew personal best in Boxing:\nDodging:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8320, + "index": 42, + "text": "The following player has set a\nnew personal best in Boxing:\nThrowing Punches:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 0, + "text": "The following player has earned\na platinum medal in Tennis:\nTarget Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 1, + "text": "The following player has earned\na gold medal in Tennis:\nTarget Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 2, + "text": "The following player has earned\na silver medal in Tennis:\nTarget Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 3, + "text": "The following player has earned\na bronze medal in Tennis:\nTarget Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 4, + "text": "The following player has earned\na platinum medal in Tennis:\nTiming Your Swing:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 5, + "text": "The following player has earned\na gold medal in Tennis:\nTiming Your Swing:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 6, + "text": "The following player has earned\na silver medal in Tennis:\nTiming Your Swing:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 7, + "text": "The following player has earned\na bronze medal in Tennis:\nTiming Your Swing:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 8, + "text": "The following player has earned\na platinum medal in Tennis:\nReturning Balls:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 9, + "text": "The following player has earned\na gold medal in Tennis:\nReturning Balls:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 10, + "text": "The following player has earned\na silver medal in Tennis:\nReturning Balls:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 11, + "text": "The following player has earned\na bronze medal in Tennis:\nReturning Balls:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 20, + "text": "The following player has earned\na platinum medal in Baseball:\nHitting Home Runs:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 21, + "text": "The following player has earned\na gold medal in Baseball:\nHitting Home Runs:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 22, + "text": "The following player has earned\na silver medal in Baseball:\nHitting Home Runs:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 23, + "text": "The following player has earned\na bronze medal in Baseball:\nHitting Home Runs:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 24, + "text": "The following player has earned\na platinum medal in Baseball:\nSwing Control:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 25, + "text": "The following player has earned\na gold medal in Baseball:\nSwing Control:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 26, + "text": "The following player has earned\na silver medal in Baseball:\nSwing Control:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 27, + "text": "The following player has earned\na bronze medal in Baseball:\nSwing Control:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 28, + "text": "The following player has earned\na platinum medal in Baseball:\nBatting Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 29, + "text": "The following player has earned\na gold medal in Baseball:\nBatting Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 30, + "text": "The following player has earned\na silver medal in Baseball:\nBatting Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 31, + "text": "The following player has earned\na bronze medal in Baseball:\nBatting Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 40, + "text": "The following player has earned\na platinum medal in Bowling:\nPicking Up Spares:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 41, + "text": "The following player has earned\na gold medal in Bowling:\nPicking Up Spares:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 42, + "text": "The following player has earned\na silver medal in Bowling:\nPicking Up Spares:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 43, + "text": "The following player has earned\na bronze medal in Bowling:\nPicking Up Spares:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 44, + "text": "The following player has earned\na platinum medal in Bowling:\nPower Throws:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 45, + "text": "The following player has earned\na gold medal in Bowling:\nPower Throws:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 46, + "text": "The following player has earned\na silver medal in Bowling:\nPower Throws:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 47, + "text": "The following player has earned\na bronze medal in Bowling:\nPower Throws:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 48, + "text": "The following player has earned\na platinum medal in Bowling:\nSpin Control:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 49, + "text": "The following player has earned\na gold medal in Bowling:\nSpin Control:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 50, + "text": "The following player has earned\na silver medal in Bowling:\nSpin Control:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 51, + "text": "The following player has earned\na bronze medal in Bowling:\nSpin Control:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 60, + "text": "The following player has earned\na platinum medal in Golf:\nPutting:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 61, + "text": "The following player has earned\na gold medal in Golf:\nPutting:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 62, + "text": "The following player has earned\na silver medal in Golf:\nPutting:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 63, + "text": "The following player has earned\na bronze medal in Golf:\nPutting:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 64, + "text": "The following player has earned\na platinum medal in Golf:\nHitting the Green:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 65, + "text": "The following player has earned\na gold medal in Golf:\nHitting the Green:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 66, + "text": "The following player has earned\na silver medal in Golf:\nHitting the Green:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 67, + "text": "The following player has earned\na bronze medal in Golf:\nHitting the Green:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 68, + "text": "The following player has earned\na platinum medal in Golf:\nTarget Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 69, + "text": "The following player has earned\na gold medal in Golf:\nTarget Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 70, + "text": "The following player has earned\na silver medal in Golf:\nTarget Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 71, + "text": "The following player has earned\na bronze medal in Golf:\nTarget Practice:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 80, + "text": "The following player has earned\na platinum medal in Boxing:\nWorking the Bag:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 81, + "text": "The following player has earned\na gold medal in Boxing:\nWorking the Bag:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 82, + "text": "The following player has earned\na silver medal in Boxing:\nWorking the Bag:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 83, + "text": "The following player has earned\na bronze medal in Boxing:\nWorking the Bag:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 84, + "text": "The following player has earned\na platinum medal in Boxing:\nDodging:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 85, + "text": "The following player has earned\na gold medal in Boxing:\nDodging:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 86, + "text": "The following player has earned\na silver medal in Boxing:\nDodging:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 87, + "text": "The following player has earned\na bronze medal in Boxing:\nDodging:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 88, + "text": "The following player has earned\na platinum medal in Boxing:\nThrowing Punches:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 89, + "text": "The following player has earned\na gold medal in Boxing:\nThrowing Punches:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 90, + "text": "The following player has earned\na silver medal in Boxing:\nThrowing Punches:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8321, + "index": 91, + "text": "The following player has earned\na bronze medal in Boxing:\nThrowing Punches:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8329, + "index": 0, + "text": "Score: { VAR_0 } \u21D2 { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8329, + "index": 1, + "text": "Score:\n{ VAR_0 } { VAR_0 } ({ VAR_0 } { VAR_0 })\n\u21D2 { VAR_0 } { VAR_0 } ({ VAR_0 } { VAR_0 })", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8329, + "index": 2, + "text": "Score: { VAR_0 } ft \u21D2 { VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8330, + "index": 0, + "text": "The following player has earned\ngold medals in all training\ngames:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8331, + "index": 0, + "text": "The following player has earned\nplatinum medals in all training\ngames:\n{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8340, + "index": 0, + "text": "Today\u0027s Wii Fitness results for\n{ VAR_1 }{ VAR_0 }:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8341, + "index": 0, + "text": "\u3000\u3000\u3000\u3000\u3000\u3000\u3000{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8342, + "index": 0, + "text": "Wow! You\u0027ve taken off { VAR_0 } { VAR_0 }!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8342, + "index": 1, + "text": "Wow! You\u0027ve taken off { VAR_0 } { VAR_0 }!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8342, + "index": 2, + "text": "Oh, no! You\u0027ve added { VAR_0 } { VAR_0 }!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8342, + "index": 3, + "text": "Oh, no! You\u0027ve added { VAR_0 } { VAR_0 }!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 0, + "text": "Tennis Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 5, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 6, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 7, + "text": "Games played\n { VAR_0 } { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 10, + "text": "Baseball Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 15, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 16, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 17, + "text": "Games played\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 20, + "text": "Bowling Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 25, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 26, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 27, + "text": "Games played\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 30, + "text": "Golf Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 35, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 36, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 37, + "text": "Games played\n { VAR_0 } { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 40, + "text": "Boxing Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 45, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 46, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8510, + "index": 47, + "text": "Matches fought\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 0, + "text": "Tennis Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 5, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 6, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 7, + "text": "Games played\n { VAR_0 } { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 10, + "text": "Baseball Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 15, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 16, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 17, + "text": "Games played\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 20, + "text": "Bowling Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 25, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 26, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 27, + "text": "Games played\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 30, + "text": "Golf Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 35, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 36, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 37, + "text": "Games played\n { VAR_0 } { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 40, + "text": "Boxing Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 45, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 46, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8511, + "index": 47, + "text": "Matches fought\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8512, + "index": 20, + "text": "Bowling Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8512, + "index": 25, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8512, + "index": 26, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8512, + "index": 27, + "text": "Games played\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8512, + "index": 30, + "text": "Golf Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8512, + "index": 35, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8512, + "index": 36, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8512, + "index": 37, + "text": "Games played\n { VAR_0 } { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8513, + "index": 0, + "text": "Tennis Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8513, + "index": 5, + "text": "Skill level\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8513, + "index": 6, + "text": "Debuted on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8513, + "index": 7, + "text": "Matches played\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8513, + "index": 10, + "text": "Baseball Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8513, + "index": 40, + "text": "Boxing Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8514, + "index": 0, + "text": "Holes in one: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8514, + "index": 1, + "text": "Perfect games: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8520, + "index": 0, + "text": "Training Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8520, + "index": 1, + "text": "Medal earned\n Platinum", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8520, + "index": 2, + "text": "Medal earned\n Gold", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8520, + "index": 3, + "text": "Medal earned\n Silver", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8520, + "index": 4, + "text": "Medal earned\n Bronze", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8520, + "index": 5, + "text": "Began training on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8520, + "index": 6, + "text": "Total training sessions\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8521, + "index": 0, + "text": "Training Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8521, + "index": 1, + "text": "Personal best\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8521, + "index": 2, + "text": "Personal best\n { VAR_0 } { VAR_0 } ({ VAR_0 } { VAR_0 })", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8521, + "index": 3, + "text": "Personal best\n { VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8521, + "index": 5, + "text": "Began training on\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8521, + "index": 6, + "text": "Total training sessions\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8530, + "index": 0, + "text": "Wii Fitness Info", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8530, + "index": 1, + "text": "Date of this Wii Fitness test:\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8530, + "index": 2, + "text": "Date of first Wii Fitness test:\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8530, + "index": 3, + "text": "Total tests completed:\n { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8530, + "index": 4, + "text": "Wii Fitness\n\nMeasure your skill in Wii\nSports. Your test results appear\nas a Wii Fitness Age, with 20\nbeing the best possible age.\n\nBecause these tests are designed\nfor adults, children may not\nget accurate test results.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8900, + "index": 0, + "text": "Wii Sports News\n", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8901, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8902, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8903, + "index": 0, + "text": "\u3010PRO\u3011", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8910, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8910, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8911, + "index": 0, + "text": "set", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8911, + "index": 1, + "text": "sets", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8912, + "index": 0, + "text": "hole", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8912, + "index": 1, + "text": "holes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8913, + "index": 0, + "text": "homer", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8913, + "index": 1, + "text": "homers", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8914, + "index": 0, + "text": "ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8915, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8916, + "index": 0, + "text": "years", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 8916, + "index": 1, + "text": "year", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x56 0x00 0x00" + }, + { + "group": 9999, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 0, + "text": "Saburo", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 1, + "text": "Hiroshi", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 2, + "text": "Daisuke", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 3, + "text": "Shinnosuke", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 4, + "text": "Akira", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 5, + "text": "Tatsuaki", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 6, + "text": "Shouta", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 7, + "text": "Ren", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 8, + "text": "Kentaro", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 9, + "text": "Takumi", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 10, + "text": "Haru", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 11, + "text": "Yoshi", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 12, + "text": "Fumiko", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 13, + "text": "Keiko", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 14, + "text": "Yoko", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 15, + "text": "Miyu", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 16, + "text": "Ai", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 17, + "text": "Misaki", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 18, + "text": "Rin", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 19, + "text": "Sakura", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 20, + "text": "Andy", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 21, + "text": "Chris", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 22, + "text": "Ryan", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 23, + "text": "Jake", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 24, + "text": "Matt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 25, + "text": "Mike", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 26, + "text": "Nick", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 27, + "text": "Oscar", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 28, + "text": "Theo", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 29, + "text": "Tyrone", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 30, + "text": "Abby", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 31, + "text": "Ashley", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 32, + "text": "Emily", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 33, + "text": "Hayley", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 34, + "text": "Jackie", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 35, + "text": "Jessie", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 36, + "text": "Maria", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 37, + "text": "Naomi", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 38, + "text": "Rachel", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 39, + "text": "Steph", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 40, + "text": "James", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 41, + "text": "Steve", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 42, + "text": "Michael", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 43, + "text": "Martin", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 44, + "text": "Pierre", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 45, + "text": "Alex", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 46, + "text": "Luca", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 47, + "text": "Marco", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 48, + "text": "David", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 49, + "text": "V\u00EDctor", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 50, + "text": "Sarah", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 51, + "text": "Helen", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 52, + "text": "Kathrin", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 53, + "text": "Silke", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 54, + "text": "Emma", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 55, + "text": "Julie", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 56, + "text": "Anna", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 57, + "text": "Elisa", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 58, + "text": "Eva", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 19000, + "index": 59, + "text": "Luc\u00EDa", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20000, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20000, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20001, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20001, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20001, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20001, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20002, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20010, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20010, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20020, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20020, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20020, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20020, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20020, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20020, + "index": 5, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20020, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 5, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 7, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 8, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 9, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 10, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20021, + "index": 11, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20022, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20022, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20022, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20022, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20030, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20030, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20030, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20030, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20030, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20030, + "index": 5, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20030, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20030, + "index": 7, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20031, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20031, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20031, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20031, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20031, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20040, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20050, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20051, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20060, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20061, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20061, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20061, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20062, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20063, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20063, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20063, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20063, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20063, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20064, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20070, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20071, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20072, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20080, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 20080, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21010, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21010, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21010, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21010, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21010, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21011, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21011, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21020, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21020, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21020, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21030, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21100, + "index": 0, + "text": "Server", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x43 0x00 0x00" + }, + { + "group": 21110, + "index": 0, + "text": "Miss", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x43 0x00 0x00" + }, + { + "group": 21120, + "index": 0, + "text": "Let", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21120, + "index": 1, + "text": "Out", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21120, + "index": 2, + "text": "Miss", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21120, + "index": 3, + "text": "2nd Bounce", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21130, + "index": 0, + "text": "00", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x58 0x00 0x00" + }, + { + "group": 21130, + "index": 1, + "text": "15", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x58 0x00 0x00" + }, + { + "group": 21130, + "index": 2, + "text": "30", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x58 0x00 0x00" + }, + { + "group": 21130, + "index": 3, + "text": "40", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x58 0x00 0x00" + }, + { + "group": 21130, + "index": 4, + "text": "Adv.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x58 0x00 0x00" + }, + { + "group": 21131, + "index": 0, + "text": "-", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 21132, + "index": 0, + "text": "Deuce", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x58 0x00 0x00" + }, + { + "group": 21132, + "index": 1, + "text": "Game", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x58 0x00 0x00" + }, + { + "group": 21140, + "index": 0, + "text": "Advantage", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21141, + "index": 0, + "text": "Deuce", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21141, + "index": 1, + "text": "Game Point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21141, + "index": 2, + "text": "Break Point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21141, + "index": 3, + "text": "Match Point", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21150, + "index": 0, + "text": "{ VAR_1 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x2D 0x00 0x00" + }, + { + "group": 21200, + "index": 0, + "text": "Choose positions and press \uE042.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21210, + "index": 0, + "text": "Single Game", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4D 0x00 0x00" + }, + { + "group": 21211, + "index": 0, + "text": "Best of 3", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4D 0x00 0x00" + }, + { + "group": 21212, + "index": 0, + "text": "Best of 5", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4D 0x00 0x00" + }, + { + "group": 21220, + "index": 0, + "text": "Start", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x43 0x00 0x00" + }, + { + "group": 21230, + "index": 0, + "text": "{ VAR_1 }{ VAR_0 }\nSkill Level: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3B 0x00 0x00" + }, + { + "group": 21240, + "index": 0, + "text": "?", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 21300, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 21310, + "index": 0, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4E 0x00 0x00" + }, + { + "group": 21310, + "index": 1, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4E 0x00 0x00" + }, + { + "group": 21500, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 21510, + "index": 0, + "text": "Targets left", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4E 0x00 0x00" + }, + { + "group": 21520, + "index": 0, + "text": "Balls left", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4E 0x00 0x00" + }, + { + "group": 22000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22000, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22001, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22001, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22001, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22001, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22010, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22010, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22010, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22010, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22010, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22010, + "index": 5, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22010, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22010, + "index": 7, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22010, + "index": 8, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22011, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22011, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22011, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22100, + "index": 0, + "text": "Play Ball!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22101, + "index": 0, + "text": "Mercy Rule", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22110, + "index": 0, + "text": "Strike", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22110, + "index": 1, + "text": "Ball", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22110, + "index": 2, + "text": "Ball Four", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22110, + "index": 3, + "text": "Strikeout", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22120, + "index": 0, + "text": "Foul Ball", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22120, + "index": 1, + "text": "Single", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22120, + "index": 2, + "text": "Double", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22120, + "index": 3, + "text": "Triple", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22120, + "index": 4, + "text": "Home Run", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22120, + "index": 5, + "text": "Out of the Park", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22130, + "index": 0, + "text": "Out", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22130, + "index": 1, + "text": "Double Play", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22130, + "index": 2, + "text": "Error", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22130, + "index": 3, + "text": "Change", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22130, + "index": 4, + "text": "Mercy Rule", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22140, + "index": 0, + "text": "Fastball", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 22140, + "index": 1, + "text": "Curveball", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 22140, + "index": 2, + "text": "Screwball", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 22140, + "index": 3, + "text": "Splitter", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 22150, + "index": 0, + "text": "mph", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22151, + "index": 0, + "text": "ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 22151, + "index": 1, + "text": "ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x78 0x00 0x00" + }, + { + "group": 22160, + "index": 0, + "text": "1ST", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22160, + "index": 1, + "text": "2ND", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22160, + "index": 2, + "text": "3RD", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22170, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22180, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22180, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22180, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22190, + "index": 0, + "text": "Vs.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22191, + "index": 0, + "text": "1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22191, + "index": 1, + "text": "2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22191, + "index": 2, + "text": "3", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22191, + "index": 3, + "text": "R", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22192, + "index": 0, + "text": "B", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x40 0x00 0x00" + }, + { + "group": 22192, + "index": 1, + "text": "S", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x40 0x00 0x00" + }, + { + "group": 22193, + "index": 2, + "text": "O", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x40 0x00 0x00" + }, + { + "group": 22200, + "index": 0, + "text": "{ VAR_1 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 22201, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22210, + "index": 0, + "text": "Strikeout", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22210, + "index": 1, + "text": "Ball Four", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22210, + "index": 2, + "text": "Out", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22210, + "index": 3, + "text": "Single", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22210, + "index": 4, + "text": "Double", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22210, + "index": 5, + "text": "Triple", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22210, + "index": 6, + "text": "Home Run", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22210, + "index": 7, + "text": "Out of the Park", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22210, + "index": 8, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22220, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22220, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22220, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22230, + "index": 0, + "text": "That\u0027s the Game!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22240, + "index": 0, + "text": "R", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22250, + "index": 0, + "text": "Play again", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 22251, + "index": 0, + "text": "Quit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 22252, + "index": 0, + "text": "Next", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x6E 0x00 0x00" + }, + { + "group": 22300, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22301, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22350, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22400, + "index": 0, + "text": "10 balls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22400, + "index": 1, + "text": "30 balls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22410, + "index": 0, + "text": "You swung too early!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22410, + "index": 1, + "text": "You\u0027re a tad early!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22410, + "index": 2, + "text": "You swung too late!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22410, + "index": 3, + "text": "You\u0027re a tad late!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22420, + "index": 0, + "text": "Home run", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22420, + "index": 1, + "text": "Out of the park", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22450, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22451, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22500, + "index": 0, + "text": "10 pitches", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22510, + "index": 0, + "text": "{ VAR_0 } runs", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22520, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22600, + "index": 0, + "text": "Left", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22601, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22610, + "index": 0, + "text": "Hits", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22611, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22611, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22612, + "index": 0, + "text": "Hit!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22620, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22621, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22650, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22651, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22700, + "index": 0, + "text": "Vs.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 22710, + "index": 0, + "text": "{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22711, + "index": 0, + "text": "Skill Level: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 22720, + "index": 0, + "text": "{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22721, + "index": 0, + "text": "Skill Level: { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 22800, + "index": 0, + "text": "Batting", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 22801, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 22810, + "index": 0, + "text": "How to Hold", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22811, + "index": 0, + "text": "Hold the Wii Remote so that the side\nwith the buttons is facing you.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22820, + "index": 0, + "text": "Batting", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22821, + "index": 0, + "text": "Hold the Wii Remote like a bat. Swing at\npitches at the right time to hit them.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22830, + "index": 0, + "text": "Pitching", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 22831, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 22840, + "index": 0, + "text": "Pitching", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22841, + "index": 0, + "text": "Swing the Wii Remote overhand to pitch.\nAim your pitch with \uE041.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22850, + "index": 0, + "text": "Breaking Balls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 22851, + "index": 0, + "text": "Pitch while pressing \uE042 for a screwball,\n\uE043 for a curveball, and \uE042\u002B\uE043 for a splitter.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22851, + "index": 1, + "text": "Pitch while pressing \uE042 for a curveball,\n\uE043 for a screwball, and \uE042\u002B\uE043 for a splitter.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 22860, + "index": 0, + "text": "Swing to pitch.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3E 0x00 0x00" + }, + { + "group": 23000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23001, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23010, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23011, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23011, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23012, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23012, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23012, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23012, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23012, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23020, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23020, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23020, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23020, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23020, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23030, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23030, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23100, + "index": 0, + "text": "Select a course", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 23101, + "index": 0, + "text": "9-Hole Game", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23102, + "index": 0, + "text": "3-Hole Game", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 23103, + "index": 0, + "text": "Beginner", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23103, + "index": 1, + "text": "Holes 1 to 3", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23104, + "index": 0, + "text": "Intermediate", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23104, + "index": 1, + "text": "Holes 4 to 5", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23105, + "index": 0, + "text": "Expert", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23105, + "index": 1, + "text": "Holes 6 to 9", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23106, + "index": 0, + "text": "Main menu", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23110, + "index": 0, + "text": "Hole { VAR_0 }: Par { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 23111, + "index": 0, + "text": "{ VAR_1 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23112, + "index": 0, + "text": "Best", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23113, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23114, + "index": 0, + "text": "Skill Level", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23115, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23116, + "index": 0, + "text": "Score", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23117, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23120, + "index": 0, + "text": "Stroke { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23121, + "index": 0, + "text": "{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23130, + "index": 0, + "text": "Hole { VAR_0 }: Par { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23131, + "index": 0, + "text": "{ VAR_0 } yd left", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23131, + "index": 1, + "text": "{ VAR_0 } yds left", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23131, + "index": 2, + "text": "{ VAR_0 } ft left", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23131, + "index": 3, + "text": "{ VAR_0 } ft left", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23132, + "index": 0, + "text": "{ VAR_0 } mph", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 23132, + "index": 1, + "text": "Wind", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23132, + "index": 2, + "text": "mph", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3B 0x00 0x00" + }, + { + "group": 23133, + "index": 0, + "text": "Driver", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x2D 0x00 0x00" + }, + { + "group": 23133, + "index": 1, + "text": "Iron", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x2D 0x00 0x00" + }, + { + "group": 23133, + "index": 2, + "text": "Wedge", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x2D 0x00 0x00" + }, + { + "group": 23133, + "index": 3, + "text": "Putter", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x2D 0x00 0x00" + }, + { + "group": 23134, + "index": 0, + "text": "To hit the ball, hold down \uE042 and swing.\n\u330D\uE041\u3357: Aim, \u3326\uE041\u3323: Change clubs", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5F 0x00 0x00" + }, + { + "group": 23135, + "index": 0, + "text": "To hit the ball, hold down \uE042 and swing.\n\u330D\uE041\u3357: Aim, \uE047: Read green\n\uE048: Change camera", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5F 0x00 0x00" + }, + { + "group": 23136, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23140, + "index": 0, + "text": "Green", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23140, + "index": 1, + "text": "Edge of Green", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23140, + "index": 2, + "text": "Fairway", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23140, + "index": 3, + "text": "Rough", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23140, + "index": 4, + "text": "Bunker", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23140, + "index": 5, + "text": "Out of Bounds", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23140, + "index": 6, + "text": "Water Hazard", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23140, + "index": 7, + "text": "Off the Green", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23141, + "index": 0, + "text": "{ VAR_0 } yard to go", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23141, + "index": 1, + "text": "{ VAR_0 } yards to go", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23142, + "index": 0, + "text": "{ VAR_0 } foot to go", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23142, + "index": 1, + "text": "{ VAR_0 } feet to go", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23150, + "index": 0, + "text": "Hole in One", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23150, + "index": 1, + "text": "Double Eagle", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23150, + "index": 2, + "text": "Eagle", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23150, + "index": 3, + "text": "Birdie", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23150, + "index": 4, + "text": "Par", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23150, + "index": 5, + "text": "Bogey", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23150, + "index": 6, + "text": "Double Bogey", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23150, + "index": 7, + "text": "Triple Bogey", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23150, + "index": 8, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23160, + "index": 0, + "text": "Give up", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 23161, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23170, + "index": 0, + "text": "Scorecard", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23180, + "index": 0, + "text": "New personal best!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23181, + "index": 0, + "text": "Next", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23182, + "index": 0, + "text": "Hole", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23183, + "index": 0, + "text": "Total", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23184, + "index": 0, + "text": "Par", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23185, + "index": 0, + "text": "{ VAR_1 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23200, + "index": 0, + "text": "Round { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23210, + "index": 0, + "text": "Distance left: { VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23210, + "index": 1, + "text": "Distance left: { VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23220, + "index": 0, + "text": "Try again", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 23300, + "index": 0, + "text": "Total: { VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 23300, + "index": 1, + "text": "Total: { VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 23310, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23311, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23311, + "index": 1, + "text": "Score: { VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 23400, + "index": 0, + "text": "Total: { VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 23400, + "index": 1, + "text": "Total: { VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 23401, + "index": 0, + "text": "Miss", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23401, + "index": 1, + "text": "\u002B10", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23401, + "index": 2, + "text": "\u002B25", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23401, + "index": 3, + "text": "\u002B50", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23401, + "index": 4, + "text": "\u002B100", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23401, + "index": 5, + "text": "\u002B75", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 23500, + "index": 0, + "text": "High", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23501, + "index": 0, + "text": "Low", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 23600, + "index": 0, + "text": "Hold the Wii Remote down, like a club.\nSwing as though you are hitting the\nball with the side of the Wii Remote.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23601, + "index": 0, + "text": "Check the strength of your swing\nwith the power gauge.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23602, + "index": 0, + "text": "If you swing too hard and max out the\ngauge, your shot will slice or hook.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23603, + "index": 0, + "text": "Try some practice swings before you\nstep up to hit the ball.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 23604, + "index": 0, + "text": "Let\u0027s take a swing at the ball.\nAim the Wii Remote down and hold\ndown \uE042 to swing.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 24000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 24001, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 24002, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 24002, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 25000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 25001, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 25002, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 25003, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 25010, + "index": 0, + "text": "Decision", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 25011, + "index": 0, + "text": "Decision", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 25020, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 25021, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 25030, + "index": 0, + "text": "R\uFF11", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 25030, + "index": 1, + "text": "R\uFF12", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 25030, + "index": 2, + "text": "R\uFF13", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 25040, + "index": 0, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 25040, + "index": 1, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 25100, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 25101, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 25200, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 25201, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 25300, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 25301, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 25400, + "index": 0, + "text": "Guard your face!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 25401, + "index": 0, + "text": "Hold the Wii Remote and Nunchuk\nup in front of your face.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 25410, + "index": 0, + "text": "Punch the face!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 25411, + "index": 0, + "text": "Jab with the Wii Remote to punch\nyour opponent\u0027s head.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 25420, + "index": 0, + "text": "Guard your body!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 25421, + "index": 0, + "text": "Hold the Wii Remote and Nunchuk in front\nof your torso and tilt them inward.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 25430, + "index": 0, + "text": "Punch the Body", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 25431, + "index": 0, + "text": "Jab with the Wii Remote to punch\nyour opponent\u0027s body.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 25440, + "index": 0, + "text": "Dodge Punches", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 25441, + "index": 0, + "text": "Hold the Wii Remote and Nunchuk and tilt\nyour body forward, back, left, or right.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 25550, + "index": 0, + "text": "Fighting Stance", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 25551, + "index": 0, + "text": "Hold the Wii Remote in your dominant\nhand and the Nunchuk in the other hand.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26000, + "index": 0, + "text": "Raise the Wii Remote and hold \uE043.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26001, + "index": 0, + "text": "Take a swing while\nholding \uE043. Release \uE043\nas you roll the ball.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 26002, + "index": 0, + "text": "Swing your arm while\nholding down \uE043, and\nrelease it to roll the ball.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26010, + "index": 0, + "text": "Strike", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 26010, + "index": 1, + "text": "Spare", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 26010, + "index": 2, + "text": "{ VAR_0 } pin", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 26010, + "index": 3, + "text": "{ VAR_0 } pins", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 26011, + "index": 0, + "text": "Double", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26011, + "index": 1, + "text": "Turkey", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26011, + "index": 2, + "text": "Fourth", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26011, + "index": 3, + "text": "Fifth", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26011, + "index": 4, + "text": "Six-pack", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26011, + "index": 5, + "text": "Seven-pack", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26011, + "index": 6, + "text": "Eight in a row", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26011, + "index": 7, + "text": "Nine in a row", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26011, + "index": 8, + "text": "Ten in a row", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26011, + "index": 9, + "text": "Eleven in a row", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26011, + "index": 10, + "text": "Perfect", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26012, + "index": 0, + "text": "Missed", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 26020, + "index": 0, + "text": "Scorecard", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 26021, + "index": 0, + "text": "Record!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x26 0x00 0x00" + }, + { + "group": 26022, + "index": 0, + "text": "-", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 26023, + "index": 0, + "text": "\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 26030, + "index": 0, + "text": "Next", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 26040, + "index": 0, + "text": "Move", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 26040, + "index": 1, + "text": "Turn", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 26041, + "index": 0, + "text": "Switch", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 26042, + "index": 0, + "text": "Back", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 26050, + "index": 0, + "text": "Game Finished", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26060, + "index": 0, + "text": "Replay", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 26100, + "index": 0, + "text": "Stage { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 26101, + "index": 0, + "text": "{ VAR_0 } pins", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 26102, + "index": 0, + "text": "Stage { VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 26110, + "index": 0, + "text": "Missed", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 26120, + "index": 0, + "text": "Challenge cleared", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x55 0x00 0x00" + }, + { + "group": 26200, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 26300, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 26400, + "index": 0, + "text": "{ VAR_0 } pin", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 26400, + "index": 1, + "text": "{ VAR_0 } pins", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 26401, + "index": 0, + "text": "\u00D7", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x32 0x00 0x00" + }, + { + "group": 26500, + "index": 0, + "text": "Perfect!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 27000, + "index": 0, + "text": "{ VAR_1 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 27001, + "index": 0, + "text": "Wii Fitness", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 27010, + "index": 0, + "text": "Wii Fitness Age: ", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 27011, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 27020, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 27021, + "index": 0, + "text": "Sun", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 27021, + "index": 1, + "text": "Mon", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 27021, + "index": 2, + "text": "Tues", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 27021, + "index": 3, + "text": "Wed", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 27021, + "index": 4, + "text": "Thurs", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 27021, + "index": 5, + "text": "Fri", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 27021, + "index": 6, + "text": "Sat", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 27030, + "index": 0, + "text": "Start", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 27031, + "index": 0, + "text": "Done", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 27100, + "index": 0, + "text": "Speed", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 27101, + "index": 0, + "text": "Balance", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 27102, + "index": 0, + "text": "Stamina", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x41 0x00 0x00" + }, + { + "group": 27200, + "index": 0, + "text": "Results", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 27210, + "index": 0, + "text": "{ VAR_1 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 27210, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 27210, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 27220, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 27230, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 27250, + "index": 0, + "text": "Wow! It\u0027s like you\u0027re { VAR_0 } years younger!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 27251, + "index": 0, + "text": "It\u0027s like you\u0027re a whole year younger!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 27251, + "index": 1, + "text": "It\u0027s like you\u0027re { VAR_0 } years younger!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 27252, + "index": 0, + "text": "No change", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 27253, + "index": 0, + "text": "A bit lower than before", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 27254, + "index": 0, + "text": "A big decline", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 27255, + "index": 0, + "text": "Good job!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 27400, + "index": 0, + "text": "JAN", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 1, + "text": "FEB", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 2, + "text": "MAR", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 3, + "text": "APR", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 4, + "text": "MAY", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 5, + "text": "JUN", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 6, + "text": "JUL", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 7, + "text": "AUG", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 8, + "text": "SEP", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 9, + "text": "OCT", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 10, + "text": "NOV", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27400, + "index": 11, + "text": "DEC", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27500, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0xA0 0x00 0x00" + }, + { + "group": 27600, + "index": 0, + "text": "Testing...", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 27601, + "index": 0, + "text": "Wii Fitness Age", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 28000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 1, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 5, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 7, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 8, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 9, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 10, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 11, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 12, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 13, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29000, + "index": 14, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29010, + "index": 0, + "text": "Start", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29010, + "index": 1, + "text": "Finished", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29100, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 29111, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29112, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29113, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29114, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29115, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29120, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29121, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29122, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29123, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29124, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29125, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29130, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29131, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29140, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29200, + "index": 0, + "text": "Training", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29201, + "index": 0, + "text": "Main menu", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29202, + "index": 0, + "text": "Wii Fitness", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29210, + "index": 0, + "text": "Tennis", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 29211, + "index": 0, + "text": "Baseball", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 29212, + "index": 0, + "text": "Bowling", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 29213, + "index": 0, + "text": "Golf", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 29214, + "index": 0, + "text": "Boxing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 29230, + "index": 0, + "text": "Returning Balls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29231, + "index": 0, + "text": "Timing Your Swing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29232, + "index": 0, + "text": "Target Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29233, + "index": 0, + "text": "Hitting Home Runs", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29234, + "index": 0, + "text": "Batting Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29235, + "index": 0, + "text": "Swing Control", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29236, + "index": 0, + "text": "Picking Up Spares", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29237, + "index": 0, + "text": "Spin Control", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29238, + "index": 0, + "text": "Power Throws", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29239, + "index": 0, + "text": "Putting", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29240, + "index": 0, + "text": "Hitting the Green", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29241, + "index": 0, + "text": "Target Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29242, + "index": 0, + "text": "Throwing Punches", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29243, + "index": 0, + "text": "Dodging", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29244, + "index": 0, + "text": "Working the Bag", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29300, + "index": 0, + "text": "\uE042: Start", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29310, + "index": 0, + "text": "???", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29400, + "index": 0, + "text": "First event", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29400, + "index": 1, + "text": "Second event", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29400, + "index": 2, + "text": "Third event", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29500, + "index": 0, + "text": "Skill Level", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x37 0x00 0x00" + }, + { + "group": 29501, + "index": 0, + "text": "PRO", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29502, + "index": 0, + "text": "Play again", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29503, + "index": 0, + "text": "Quit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29510, + "index": 0, + "text": "{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 29511, + "index": 0, + "text": "{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0xFE 0x00" + }, + { + "group": 29600, + "index": 0, + "text": "{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x4B 0x00 0x00" + }, + { + "group": 29601, + "index": 0, + "text": "Pause", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29610, + "index": 0, + "text": "Record: { VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29610, + "index": 1, + "text": "Record: { VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29611, + "index": 0, + "text": "Record: { VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29611, + "index": 1, + "text": "Record: { VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29612, + "index": 0, + "text": "Record: { VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29612, + "index": 1, + "text": "Record: { VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29620, + "index": 0, + "text": "Record: { VAR_0 } homer ({ VAR_0 } ft)", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 29620, + "index": 1, + "text": "Record: { VAR_0 } homers ({ VAR_0 } ft)", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5E 0x00 0x00" + }, + { + "group": 29621, + "index": 0, + "text": "Record: { VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29621, + "index": 1, + "text": "Record: { VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29622, + "index": 0, + "text": "Record: { VAR_0 } hit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29622, + "index": 1, + "text": "Record: { VAR_0 } hits", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29630, + "index": 0, + "text": "Record: { VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29630, + "index": 1, + "text": "Record: { VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29631, + "index": 0, + "text": "Record: { VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29631, + "index": 1, + "text": "Record: { VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29632, + "index": 0, + "text": "Record: { VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29632, + "index": 1, + "text": "Record: { VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29640, + "index": 0, + "text": "Record: { VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29640, + "index": 1, + "text": "Record: { VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29641, + "index": 0, + "text": "Record: { VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29641, + "index": 1, + "text": "Record: { VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29642, + "index": 0, + "text": "Record: { VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29642, + "index": 1, + "text": "Record: { VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29650, + "index": 0, + "text": "Record: { VAR_0 } lane", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29650, + "index": 1, + "text": "Record: { VAR_0 } lanes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29651, + "index": 0, + "text": "Record: { VAR_0 } lane", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29651, + "index": 1, + "text": "Record: { VAR_0 } lanes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29652, + "index": 0, + "text": "Record: { VAR_0 } pin", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29652, + "index": 1, + "text": "Record: { VAR_0 } pins", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29700, + "index": 0, + "text": "{ VAR_1 }{ VAR_0 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5F 0x00 0x00" + }, + { + "group": 29701, + "index": 0, + "text": "Record!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x1E 0x00 0x00" + }, + { + "group": 29702, + "index": 0, + "text": "Try again", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29703, + "index": 0, + "text": "Quit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29710, + "index": 0, + "text": "Returning Balls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29710, + "index": 1, + "text": "Score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29710, + "index": 2, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29710, + "index": 3, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29711, + "index": 0, + "text": "Timing Your Swing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29711, + "index": 1, + "text": "Score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29711, + "index": 2, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29711, + "index": 3, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29712, + "index": 0, + "text": "Target Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29712, + "index": 1, + "text": "Score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29712, + "index": 2, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29712, + "index": 3, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29720, + "index": 0, + "text": "Hitting Home Runs", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29720, + "index": 1, + "text": "Home runs:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29720, + "index": 2, + "text": "run", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29720, + "index": 3, + "text": "runs", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29720, + "index": 4, + "text": "Total distance:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29720, + "index": 5, + "text": "ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29720, + "index": 6, + "text": "ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29721, + "index": 0, + "text": "Swing Control", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29721, + "index": 1, + "text": "Score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29721, + "index": 2, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29721, + "index": 3, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29722, + "index": 0, + "text": "Batting Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29722, + "index": 1, + "text": "Score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29722, + "index": 2, + "text": "hit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29722, + "index": 3, + "text": "hits", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29730, + "index": 0, + "text": "Putting", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29730, + "index": 1, + "text": "Cup-in:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29730, + "index": 2, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29730, + "index": 3, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29731, + "index": 0, + "text": "Hitting the Green", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29731, + "index": 1, + "text": "Total left:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29731, + "index": 2, + "text": "ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29731, + "index": 3, + "text": "ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29732, + "index": 0, + "text": "Target Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29732, + "index": 1, + "text": "Score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29732, + "index": 2, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29732, + "index": 3, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29740, + "index": 0, + "text": "Throwing Punches", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29740, + "index": 1, + "text": "Score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29740, + "index": 2, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29740, + "index": 3, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29740, + "index": 4, + "text": "Hit score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29740, + "index": 5, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29740, + "index": 6, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29740, + "index": 7, + "text": "Trainer penalty:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29740, + "index": 8, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29740, + "index": 9, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29741, + "index": 0, + "text": "Dodging", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29741, + "index": 1, + "text": "Score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29741, + "index": 2, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29741, + "index": 3, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29741, + "index": 4, + "text": "Balls dodged:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29741, + "index": 5, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29741, + "index": 6, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29741, + "index": 7, + "text": "Balls hit:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29741, + "index": 8, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29741, + "index": 9, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29742, + "index": 0, + "text": "Working the Bag", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29742, + "index": 1, + "text": "Score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29742, + "index": 2, + "text": "pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29742, + "index": 3, + "text": "pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29742, + "index": 4, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29742, + "index": 5, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29742, + "index": 6, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29742, + "index": 7, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29742, + "index": 8, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29742, + "index": 9, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29750, + "index": 0, + "text": "Picking Up Spares", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29750, + "index": 1, + "text": "Cleared:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29750, + "index": 2, + "text": "lane", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29750, + "index": 3, + "text": "lanes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29751, + "index": 0, + "text": "Spin Control", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29751, + "index": 1, + "text": "Cleared:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29751, + "index": 2, + "text": "lane", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29751, + "index": 3, + "text": "lanes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29752, + "index": 0, + "text": "Power Throws", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29752, + "index": 1, + "text": "Score:", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29752, + "index": 2, + "text": "pin", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29752, + "index": 3, + "text": "pins", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29800, + "index": 0, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29801, + "index": 0, + "text": "1", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 29802, + "index": 0, + "text": "2", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 29803, + "index": 0, + "text": "3", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 29804, + "index": 0, + "text": "4", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x46 0x00 0x00" + }, + { + "group": 29805, + "index": 0, + "text": "{ VAR_1 }", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x50 0x00 0x00" + }, + { + "group": 29810, + "index": 0, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29810, + "index": 1, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29811, + "index": 0, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29811, + "index": 1, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29812, + "index": 0, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29812, + "index": 1, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29820, + "index": 0, + "text": "{ VAR_0 } homer { COMMON_FONT_SIZE 00 3C }({ VAR_0 } ft)", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29820, + "index": 1, + "text": "{ VAR_0 } homers { COMMON_FONT_SIZE 00 3C }({ VAR_0 } ft)", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29820, + "index": 2, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29820, + "index": 3, + "text": "", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29821, + "index": 0, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29821, + "index": 1, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29822, + "index": 0, + "text": "{ VAR_0 } hit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29822, + "index": 1, + "text": "{ VAR_0 } hits", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29830, + "index": 0, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29830, + "index": 1, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29831, + "index": 0, + "text": "{ VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29831, + "index": 1, + "text": "{ VAR_0 } ft", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29832, + "index": 0, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29832, + "index": 1, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29840, + "index": 0, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29840, + "index": 1, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29841, + "index": 0, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29841, + "index": 1, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29842, + "index": 0, + "text": "{ VAR_0 } pt", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29842, + "index": 1, + "text": "{ VAR_0 } pts", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29850, + "index": 0, + "text": "{ VAR_0 } lane", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29850, + "index": 1, + "text": "{ VAR_0 } lanes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29851, + "index": 0, + "text": "{ VAR_0 } lane", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29851, + "index": 1, + "text": "{ VAR_0 } lanes", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29852, + "index": 0, + "text": "{ VAR_0 } pin", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29852, + "index": 1, + "text": "{ VAR_0 } pins", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29860, + "index": 0, + "text": "Returning Balls", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29861, + "index": 0, + "text": "Timing Your Swing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29862, + "index": 0, + "text": "Target Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29863, + "index": 0, + "text": "Hitting Home Runs", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29864, + "index": 0, + "text": "Batting Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29865, + "index": 0, + "text": "Swing Control", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29866, + "index": 0, + "text": "Picking Up Spares", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29867, + "index": 0, + "text": "Spin Control", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29868, + "index": 0, + "text": "Power Throws", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29869, + "index": 0, + "text": "Putting", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29870, + "index": 0, + "text": "Hitting the Green", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29871, + "index": 0, + "text": "Target Practice", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29872, + "index": 0, + "text": "Throwing Punches", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29873, + "index": 0, + "text": "Dodging", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29874, + "index": 0, + "text": "Working the Bag", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29880, + "index": 0, + "text": "Again", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29881, + "index": 0, + "text": "Quit", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29890, + "index": 0, + "text": "Platinum", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x37 0x00 0x00" + }, + { + "group": 29891, + "index": 0, + "text": "Gold", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 29892, + "index": 0, + "text": "Silver", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 29893, + "index": 0, + "text": "Bronze", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x3C 0x00 0x00" + }, + { + "group": 29900, + "index": 0, + "text": "Tennis", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29901, + "index": 0, + "text": "Baseball", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29902, + "index": 0, + "text": "Bowling", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29903, + "index": 0, + "text": "Golf", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29904, + "index": 0, + "text": "Boxing", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29910, + "index": 0, + "text": "Training", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 29911, + "index": 0, + "text": "Wii Fitness", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x82 0x00 0x00" + }, + { + "group": 29920, + "index": 0, + "text": "\u3303\u3336\u3351", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x96 0x00 0x00" + }, + { + "group": 29930, + "index": 0, + "text": "Please press \uE042 and \uE043.", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x5A 0x00 0x00" + }, + { + "group": 29940, + "index": 0, + "text": "Wii Sports", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + }, + { + "group": 29941, + "index": 0, + "text": "Play like a pro!", + "attributes": "0x00000000", + "ex_attributes": "0x00 0x64 0x00 0x00" + } + ] +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBenchTests/Data/NW4R/LayoutLib/Layout/60200_general_opening_score.json b/tools/workbench/LibWorkBenchTests/Data/NW4R/LayoutLib/Layout/60200_general_opening_score.json new file mode 100644 index 0000000..e900394 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Data/NW4R/LayoutLib/Layout/60200_general_opening_score.json @@ -0,0 +1,23607 @@ +{ + "version": 10, + "origin_type": "CENTER", + "size": { + "width": 608, + "height": 456 + }, + "root_pane": { + "kind": "pane", + "name": "RootPane", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 608, + "height": 456 + }, + "children": [ + { + "kind": "pane", + "name": "N_cell_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": true, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -10, + "y": -185, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_4P_center_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 139, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_4P_Base_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "window", + "content": { + "material_name": "W_4P_Base_00C ", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ] + }, + "inflation": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "frames": [ + { + "material_name": "W_4P_Base_00LT", + "texture_flip": "NONE" + } + ], + "name": "W_4P_Base_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "TOP" + }, + "alpha": 120, + "translate": { + "x": -5, + "y": 27, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 535, + "height": 183 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -26, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "pane", + "name": "N_4P_name_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -255, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_nameW_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 7.3, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 7.3, + "y": 1 + } + } + ], + "name": "P_4P_nameW_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_4P_name_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 6.6, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 6.6, + "y": 1 + } + } + ], + "name": "P_4P_name_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_score_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_score_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.9, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.9, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_4P_score_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": -0, + "y": -0.5, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 194, + "height": 29 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_skill_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 127, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_skill_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 1, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_4P_skill_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 4.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_stamp_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_stamp_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 11.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 11.4, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_4P_stamp_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 11.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -61, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "pane", + "name": "N_4P_name_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -257, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_nameW_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 6.6, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 6.6, + "y": 1 + } + } + ], + "name": "P_4P_nameW_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 0, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 183.7, + "height": 28 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_4P_name_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 7.3, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 7.3, + "y": 1 + } + } + ], + "name": "P_4P_name_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 183.7, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_score_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -69.6, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_score_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.9, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.9, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_4P_score_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 194, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_skill_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 127, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_skill_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 1, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_4P_skill_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 122, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_stamp_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -69.6, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_stamp_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 10.7, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 10.7, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_4P_stamp_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 319, + "height": 28 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -94, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "pane", + "name": "N_4P_name_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -257, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_nameW_B_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 6.6, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 6.6, + "y": 1 + } + } + ], + "name": "P_4P_nameW_B_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 183.7, + "height": 28 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_4P_name_B_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 6.6, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 6.6, + "y": 1 + } + } + ], + "name": "P_4P_name_B_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 183.7, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_score_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_score_B_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.9, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.9, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_4P_score_B_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 194, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_skill_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 127, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_skill_B_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 1, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_4P_skill_B_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 122, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_stamp_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_stamp_B_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 10.7, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 10.7, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_4P_stamp_B_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 319, + "height": 28 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -128, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "pane", + "name": "N_4P_name_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -255, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_nameW_B_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 1 + }, + "right_top": { + "x": 6.6, + "y": 1 + }, + "left_bottom": { + "x": 0, + "y": 0 + }, + "right_bottom": { + "x": 6.6, + "y": 0 + } + } + ], + "name": "P_4P_nameW_B_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_4P_name_B_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 1 + }, + "right_top": { + "x": 6.6, + "y": 1 + }, + "left_bottom": { + "x": 0, + "y": 0 + }, + "right_bottom": { + "x": 6.6, + "y": 0 + } + } + ], + "name": "P_4P_name_B_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_score_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_score_B_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.9, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.9, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_4P_score_B_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0.5, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 194, + "height": 29 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_skill_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 127, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_skill_B_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.4, + "y": 1 + }, + "right_top": { + "x": 0, + "y": 1 + }, + "left_bottom": { + "x": 4.4, + "y": 0 + }, + "right_bottom": { + "x": 0, + "y": 0 + } + } + ], + "name": "P_4P_skill_B_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 4.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_4P_stamp_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_4P_stamp_B_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 11.4, + "y": 1 + }, + "right_top": { + "x": 0, + "y": 1 + }, + "left_bottom": { + "x": 11.4, + "y": 0 + }, + "right_bottom": { + "x": 0, + "y": 0 + } + } + ], + "name": "P_4P_stamp_B_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 11.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_center_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": 139, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_3P_Base_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "window", + "content": { + "material_name": "W_3P_Base_00C ", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ] + }, + "inflation": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "frames": [ + { + "material_name": "W_3P_Base_00LT", + "texture_flip": "NONE" + } + ], + "name": "W_3P_Base_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "TOP" + }, + "alpha": 120, + "translate": { + "x": -5, + "y": 27, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 535, + "height": 149 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -26, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "pane", + "name": "N_3P_name_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -255, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_nameW_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 7.3, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 7.3, + "y": 1 + } + } + ], + "name": "P_3P_nameW_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_3P_name_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 6.6, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 6.6, + "y": 1 + } + } + ], + "name": "P_3P_name_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_score_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_score_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.9, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.9, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_3P_score_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": -0, + "y": -0.5, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 194, + "height": 29 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_skill_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 127, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_skill_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 1, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_3P_skill_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 4.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_stamp_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_stamp_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 11.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 11.4, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_3P_stamp_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 11.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -61, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "pane", + "name": "N_3P_name_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -257, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_nameW_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 6.6, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 6.6, + "y": 1 + } + } + ], + "name": "P_3P_nameW_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 0, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 183.7, + "height": 28 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_3P_name_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_3P_name_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 183.7, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_score_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -69.6, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_score_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.9, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.9, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_3P_score_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 194, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_skill_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 127, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_skill_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 1, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_3P_skill_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 122, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_stamp_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -69.6, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_stamp_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 10.7, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 10.7, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_3P_stamp_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 11.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -94, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "pane", + "name": "N_3P_name_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -255, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_nameW_B_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 1 + }, + "right_top": { + "x": 6.6, + "y": 1 + }, + "left_bottom": { + "x": 0, + "y": 0 + }, + "right_bottom": { + "x": 6.6, + "y": 0 + } + } + ], + "name": "P_3P_nameW_B_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_3P_name_B_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 1 + }, + "right_top": { + "x": 6.6, + "y": 1 + }, + "left_bottom": { + "x": 0, + "y": 0 + }, + "right_bottom": { + "x": 6.6, + "y": 0 + } + } + ], + "name": "P_3P_name_B_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_score_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_score_B_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.9, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.9, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_3P_score_B_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0.5, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 194, + "height": 29 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_skill_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 127, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_skill_B_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.4, + "y": 1 + }, + "right_top": { + "x": 0, + "y": 1 + }, + "left_bottom": { + "x": 4.4, + "y": 0 + }, + "right_bottom": { + "x": 0, + "y": 0 + } + } + ], + "name": "P_3P_skill_B_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 4.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_3P_stamp_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_3P_stamp_B_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 11.4, + "y": 1 + }, + "right_top": { + "x": 0, + "y": 1 + }, + "left_bottom": { + "x": 11.4, + "y": 0 + }, + "right_bottom": { + "x": 0, + "y": 0 + } + } + ], + "name": "P_3P_stamp_B_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 11.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_2P_center_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 139, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_2P_Base_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "window", + "content": { + "material_name": "W_2P_Base_00C ", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ] + }, + "inflation": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "frames": [ + { + "material_name": "W_2P_Base_00LT", + "texture_flip": "NONE" + } + ], + "name": "W_2P_Base_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "TOP" + }, + "alpha": 120, + "translate": { + "x": -5, + "y": 27, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 535, + "height": 115 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_2P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -26, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "pane", + "name": "N_2P_name_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -255, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_2P_nameW_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 7.3, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 7.3, + "y": 1 + } + } + ], + "name": "P_2P_nameW_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_2P_name_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 6.6, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 6.6, + "y": 1 + } + } + ], + "name": "P_2P_name_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_2P_score_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_2P_score_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.9, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.9, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_2P_score_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": -0, + "y": -0.5, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 194, + "height": 29 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_2P_skill_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 127, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_2P_skill_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 1, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_2P_skill_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 4.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_2P_stamp_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_2P_stamp_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 11.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 11.4, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_2P_stamp_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 11.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_2P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -61, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "pane", + "name": "N_2P_name_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -255, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_2P_nameW_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 1 + }, + "right_top": { + "x": 6.6, + "y": 1 + }, + "left_bottom": { + "x": 0, + "y": 0 + }, + "right_bottom": { + "x": 6.6, + "y": 0 + } + } + ], + "name": "P_2P_nameW_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_2P_name_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 1 + }, + "right_top": { + "x": 6.6, + "y": 1 + }, + "left_bottom": { + "x": 0, + "y": 0 + }, + "right_bottom": { + "x": 6.6, + "y": 0 + } + } + ], + "name": "P_2P_name_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_2P_score_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -69.6, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_2P_score_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.9, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.9, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_2P_score_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 194, + "height": 29 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_2P_skill_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 127, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_2P_skill_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.4, + "y": 1 + }, + "right_top": { + "x": 0, + "y": 1 + }, + "left_bottom": { + "x": 4.4, + "y": 0 + }, + "right_bottom": { + "x": 0, + "y": 0 + } + } + ], + "name": "P_2P_skill_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 4.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_2P_stamp_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -69.6, + "y": 1, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_2P_stamp_B_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 11.4, + "y": 1 + }, + "right_top": { + "x": 0, + "y": 1 + }, + "left_bottom": { + "x": 11.4, + "y": 0 + }, + "right_bottom": { + "x": 0, + "y": 0 + } + } + ], + "name": "P_2P_stamp_B_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 11.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_1P_center_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": 139, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_1P_Base_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "window", + "content": { + "material_name": "W_1P_Base_00C ", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ] + }, + "inflation": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "frames": [ + { + "material_name": "W_1P_Base_00LT", + "texture_flip": "NONE" + } + ], + "name": "W_1P_Base_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "TOP" + }, + "alpha": 120, + "translate": { + "x": -5, + "y": 27, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 535, + "height": 80 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_1P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -26, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "pane", + "name": "N_1P_name_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -255, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_1P_nameW_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 7.3, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 7.3, + "y": 1 + } + } + ], + "name": "P_1P_nameW_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_1P_name_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 6.6, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 6.6, + "y": 1 + } + } + ], + "name": "P_1P_name_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": -3, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 6.6, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_1P_score_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_1P_score_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.9, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.9, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_1P_score_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1.1 + }, + "size": { + "width": 194, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_1P_skill_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 127, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_1P_skill_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 4.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 4.4, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_1P_skill_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 120, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 4.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_1P_stamp_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -69.6, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_1P_stamp_B_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 11.4, + "y": 0 + }, + "right_top": { + "x": 0, + "y": 0 + }, + "left_bottom": { + "x": 11.4, + "y": 1 + }, + "right_bottom": { + "x": 0, + "y": 1 + } + } + ], + "name": "P_1P_stamp_B_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 140, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 11.4, + "y": 1.1 + }, + "size": { + "width": 28, + "height": 28 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_text_center_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 140.3527, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_text_Base_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 26, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_score_B_00", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 28.8, + "height": 28.8 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u30D9\u30B9\u30C8", + "text_capacity": 8, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_score_B_00", + "user_data": "#00", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 1, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 95, + "height": 32 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_skill_B_00", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 28.8, + "height": 28.8 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u719F\u7DF4\u5EA6", + "text_capacity": 8, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_skill_B_00", + "user_data": "#01", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 160, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 95, + "height": 32 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_stamp_B_00", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 28.8, + "height": 28.8 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u30B9\u30BF\u30F3\u30D7", + "text_capacity": 10, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_stamp_B_00", + "user_data": "#03", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": 62, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 150, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 26, + "y": -132, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_miiFace_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -268, + "y": 4, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.35, + "y": 0.35 + }, + "size": { + "width": 128, + "height": 128 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_miiFace_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_miiFace_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 128, + "height": 128 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_name_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -177, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_name_03", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 25.6, + "height": 25.6 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u304A\u304B\u3060\u3060\u3055\u3068\u3053", + "text_capacity": 16, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_name_03", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 145, + "height": 30 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_score_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -3, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_score_03", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "444444", + "text_capacity": 14, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_score_03", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 140, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_skill_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 156, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_skill_03", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "4444", + "text_capacity": 10, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_skill_03", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 80, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_crown_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 83, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_crown_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_crown_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.3, + "y": 0.3 + }, + "size": { + "width": 105, + "height": 105 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_medal_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 209, + "y": 2, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_medal_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_medal_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 24, + "height": 24 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_noDate_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -1, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_noDate_03", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "---", + "text_capacity": 8, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_noDate_03", + "user_data": "#02", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 3, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 140, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_stampRoot_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -39, + "y": 2.7999878, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_stamp_Base_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_stamp_B_4P_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_4P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_4P_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_4P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 50, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_4P_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_4P_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 100, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_4P_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_4P_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 150, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_4P_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_4P_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 200, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_stamp_03", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -0, + "y": 0.2000122, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_stamp_4P_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_4P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_4P_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_4P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 50, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_4P_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_4P_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 100, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_4P_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_4P_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 150, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_4P_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_4P_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 200, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_text_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 26, + "y": -98, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_miiFace_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -268, + "y": 4, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.35, + "y": 0.35 + }, + "size": { + "width": 128, + "height": 128 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_miiFace_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_miiFace_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 128, + "height": 128 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_name_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -177, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_name_02", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 25.6, + "height": 25.6 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u304A\u304B\u3060\u3060\u3055\u3068\u3053", + "text_capacity": 16, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_name_02", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 145, + "height": 30 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_score_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -3, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_score_02", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "444444", + "text_capacity": 14, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_score_02", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 140, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_skill_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 156, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_skill_02", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "4444", + "text_capacity": 10, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_skill_02", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 80, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_crown_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 83, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_crown_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_crown_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.3, + "y": 0.3 + }, + "size": { + "width": 105, + "height": 105 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_medal_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 209, + "y": 2, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_medal_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_medal_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 24, + "height": 24 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_noDate_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -1, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_noDate_02", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "---", + "text_capacity": 8, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_noDate_02", + "user_data": "#02", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 3, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 140, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_stampRoot_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -39, + "y": 2.7999954, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_stamp_Base_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_stamp_B_3P_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_3P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_3P_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_3P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 50, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_3P_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_3P_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 100, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_3P_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_3P_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 150, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_3P_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_3P_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 200, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_stamp_02", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -0, + "y": 0.20000458, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_stamp_3P_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_3P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_3P_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_3P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 50, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_3P_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_3P_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 100, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_3P_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_3P_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 150, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_3P_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_3P_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 200, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_text_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 27, + "y": -65, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_miiFace_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -268, + "y": 5, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.35, + "y": 0.35 + }, + "size": { + "width": 128, + "height": 128 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_miiFace_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_miiFace_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 128, + "height": 128 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_name_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -177, + "y": 4, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_name_01", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 25.6, + "height": 25.6 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u304A\u304B\u3060\u3060\u3055\u3068\u3053", + "text_capacity": 16, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_name_01", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 145, + "height": 30 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_score_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -3, + "y": 4, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_score_01", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "444444", + "text_capacity": 14, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_score_01", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 140, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_skill_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 156, + "y": 4, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_skill_01", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "4444", + "text_capacity": 10, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_skill_01", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -1, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 80, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_crown_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 83, + "y": 4, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_crown_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_crown_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.3, + "y": 0.3 + }, + "size": { + "width": 105, + "height": 105 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_medal_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 209, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_medal_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_medal_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 24, + "height": 24 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_noDate_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -1, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_noDate_01", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "---", + "text_capacity": 8, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_noDate_01", + "user_data": "#02", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 3, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 140, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_stampRoot_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -39, + "y": 3.2999954, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_stamp_Base_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_stamp_B_2P_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_2P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_2P_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_2P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 50, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_2P_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_2P_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 100, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_2P_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_2P_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 150, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_2P_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_2P_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 200, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_stamp_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_stamp_2P_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_2P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_2P_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_2P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 50, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_2P_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_2P_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 100, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_2P_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_2P_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 150, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_2P_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_2P_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 200, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_text_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 26, + "y": -31, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_miiFace_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -268, + "y": 4, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.35, + "y": 0.35 + }, + "size": { + "width": 128, + "height": 128 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_miiFace_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_miiFace_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 128, + "height": 128 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_name_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -177, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_name_00", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 25.6, + "height": 25.6 + }, + "char_space": -2, + "line_space": 0, + "text_content": "\u304A\u304B\u3060\u3060\u3055\u3068\u3053\u3053", + "text_capacity": 18, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_name_00", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 145, + "height": 30 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_score_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -3, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_score_00", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "444444", + "text_capacity": 14, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_score_00", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 140, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_skill_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 156, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_skill_00", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "4444", + "text_capacity": 10, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_skill_00", + "user_data": "!", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 80, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_crown_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 83, + "y": 4, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_crown_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_crown_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.3, + "y": 0.3 + }, + "size": { + "width": 105, + "height": 105 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_medal_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 209, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_medal_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_medal_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 24, + "height": 24 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_text_noDate_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 1, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_noDate_00", + "font_name": "00_WS2_nRodB_32_IA4.brfnt", + "font_size": { + "width": 32, + "height": 32 + }, + "char_space": -2, + "line_space": 0, + "text_content": "---", + "text_capacity": 8, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "RIGHT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_noDate_00", + "user_data": "#02", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 140, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_stampRoot_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -39, + "y": 3.399998, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_stamp_Base_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_stamp_B_1P_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_1P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_1P_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_1P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 50, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_1P_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_1P_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 100, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_1P_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_1P_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 150, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_B_1P_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_B_1P_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 60, + "translate": { + "x": 200, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.6, + "y": 0.6 + }, + "size": { + "width": 52, + "height": 52 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_stamp_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -0, + "y": -0.099998474, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_stamp_1P_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_1P_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_1P_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_1P_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 50, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_1P_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_1P_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 100, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_1P_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_1P_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 150, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_stamp_1P_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_stamp_1P_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 200, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 62, + "height": 62 + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + "root_group": { + "name": "RootGroup", + "pane_names": [], + "children": [ + { + "name": "G_in_out", + "pane_names": [ + "N_cell_00" + ], + "children": [] + }, + { + "name": "G_medal_00", + "pane_names": [ + "P_medal_00" + ], + "children": [] + }, + { + "name": "G_medal_01", + "pane_names": [ + "P_medal_01" + ], + "children": [] + }, + { + "name": "G_medal_02", + "pane_names": [ + "P_medal_02" + ], + "children": [] + }, + { + "name": "G_medal_03", + "pane_names": [ + "P_medal_03" + ], + "children": [] + }, + { + "name": "G_change_00", + "pane_names": [ + "T_score_B_00", + "T_skill_B_00", + "T_stamp_B_00", + "N_miiFace_00", + "N_text_name_00", + "N_text_score_00", + "N_text_skill_00", + "N_crown_00", + "N_medal_00", + "N_text_noDate_00", + "N_stamp_Base_00", + "N_stamp_00", + "N_miiFace_01", + "N_text_name_01", + "N_text_score_01", + "N_text_skill_01", + "N_crown_01", + "N_medal_01", + "N_text_noDate_01", + "N_stamp_Base_01", + "N_stamp_01", + "N_miiFace_02", + "N_text_name_02", + "N_text_score_02", + "N_text_skill_02", + "N_crown_02", + "N_medal_02", + "N_text_noDate_02", + "N_stamp_Base_02", + "N_stamp_02", + "N_miiFace_03", + "N_text_name_03", + "N_text_score_03", + "N_text_skill_03", + "N_crown_03", + "N_medal_03", + "N_text_noDate_03", + "N_stamp_Base_03", + "N_stamp_03", + "N_4P_score_00", + "N_4P_skill_00", + "N_4P_stamp_00", + "N_4P_01", + "N_4P_score_01", + "N_4P_skill_01", + "N_4P_stamp_01", + "N_4P_02", + "N_4P_score_02", + "N_4P_skill_02", + "N_4P_stamp_02", + "N_4P_03", + "N_4P_score_03", + "N_4P_skill_03", + "N_4P_stamp_03", + "N_3P_score_00", + "N_3P_skill_00", + "N_3P_stamp_00", + "N_3P_score_01", + "N_3P_skill_01", + "N_3P_stamp_01", + "N_3P_score_02", + "N_3P_skill_02", + "N_3P_stamp_02", + "N_2P_stamp_00", + "N_2P_skill_00", + "N_2P_score_00", + "N_2P_score_01", + "N_2P_skill_01", + "N_2P_stamp_01", + "N_1P_00", + "N_1P_skill_00", + "N_1P_score_00", + "N_1P_stamp_00" + ], + "children": [] + }, + { + "name": "G_stampPos_00", + "pane_names": [ + "N_stampRoot_01", + "N_stampRoot_02", + "N_stampRoot_03", + "N_stampRoot_00" + ], + "children": [] + } + ] + }, + "materials": [ + { + "name": "W_4P_Base_00C ", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 255, + "a": 255 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "st_W_glassA_B_LT_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_4P_Base_00LT", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_marukado_beta_36.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_score_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_nameW_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_nameW_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_nameW_B_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_nameW_B_03", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_score_B_00", + "tev_colors": { + "reg0": { + "r": 12, + "g": 32, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_miiFace_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "oy_common_miiFaceDammy.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_name_00", + "tev_colors": { + "reg0": { + "r": 45, + "g": 45, + "b": 100, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_score_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_miiFace_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "oy_common_miiFaceDammy.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_name_01", + "tev_colors": { + "reg0": { + "r": 45, + "g": 45, + "b": 100, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_score_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_miiFace_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "oy_common_miiFaceDammy.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_name_02", + "tev_colors": { + "reg0": { + "r": 45, + "g": 45, + "b": 100, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_score_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_miiFace_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "oy_common_miiFaceDammy.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_name_03", + "tev_colors": { + "reg0": { + "r": 45, + "g": 45, + "b": 100, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_score_03", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_name_B_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 140, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_name_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 56, + "b": 56, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_name_B_02", + "tev_colors": { + "reg0": { + "r": 16, + "g": 189, + "b": 13, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_name_B_03", + "tev_colors": { + "reg0": { + "r": 255, + "g": 200, + "b": 25, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_3P_Base_00C ", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 255, + "a": 255 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "st_W_glassA_B_LT_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_3P_Base_00LT", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_marukado_beta_36.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_2P_Base_00C ", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 255, + "a": 255 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "st_W_glassA_B_LT_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_2P_Base_00LT", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_marukado_beta_36.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_1P_Base_00C ", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 255, + "a": 255 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "st_W_glassA_B_LT_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_1P_Base_00LT", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_marukado_beta_36.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_skill_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_score_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_score_B_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_score_B_03", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_skill_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_skill_B_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_skill_B_03", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_nameW_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_name_B_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 140, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_score_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_skill_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_nameW_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_name_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 56, + "b": 56, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_score_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_skill_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_nameW_B_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_name_B_02", + "tev_colors": { + "reg0": { + "r": 16, + "g": 189, + "b": 13, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_score_B_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_skill_B_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_2P_nameW_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_2P_name_B_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 140, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_2P_score_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_2P_skill_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_2P_nameW_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_2P_name_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 56, + "b": 56, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_2P_score_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_2P_skill_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_1P_nameW_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_1P_name_B_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 140, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_1P_score_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_1P_skill_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_skill_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_skill_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_skill_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_skill_03", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_skill_B_00", + "tev_colors": { + "reg0": { + "r": 12, + "g": 32, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_medal_00", + "tev_colors": { + "reg0": { + "r": 23, + "g": 88, + "b": 121, + "a": 0 + }, + "reg1": { + "r": 232, + "g": 255, + "b": 245, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_common_medal_mini_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_medal_01", + "tev_colors": { + "reg0": { + "r": 23, + "g": 88, + "b": 121, + "a": 0 + }, + "reg1": { + "r": 232, + "g": 255, + "b": 245, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_common_medal_mini_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_medal_02", + "tev_colors": { + "reg0": { + "r": 23, + "g": 88, + "b": 121, + "a": 0 + }, + "reg1": { + "r": 232, + "g": 255, + "b": 245, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_common_medal_mini_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_medal_03", + "tev_colors": { + "reg0": { + "r": 23, + "g": 88, + "b": 121, + "a": 0 + }, + "reg1": { + "r": 232, + "g": 255, + "b": 245, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_common_medal_mini_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_crown_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "crown_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_crown_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "crown_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_crown_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "crown_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_crown_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "crown_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_noDate_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_noDate_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_noDate_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_noDate_03", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 70, + "g": 70, + "b": 70, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_stamp_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_stamp_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_stamp_B_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_4P_stamp_B_03", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_stamp_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_stamp_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_3P_stamp_B_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_2P_stamp_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_2P_stamp_B_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_1P_stamp_B_00", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "os_table_cell_hw28_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_stamp_B_00", + "tev_colors": { + "reg0": { + "r": 12, + "g": 32, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_1P_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_1P_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_1P_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_1P_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_1P_04", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_1P_00", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_1P_01", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_1P_02", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_1P_03", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_1P_04", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_2P_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_2P_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_2P_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_2P_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_2P_04", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_2P_00", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_2P_01", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_2P_02", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_2P_03", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_2P_04", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_3P_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_3P_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_3P_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_3P_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_3P_04", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_3P_00", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_3P_01", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_3P_02", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_3P_03", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_3P_04", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_4P_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_4P_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_4P_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_4P_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_B_4P_04", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_4P_00", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_4P_01", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_4P_02", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_4P_03", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_stamp_4P_04", + "tev_colors": { + "reg0": { + "r": 240, + "g": 90, + "b": 60, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 180, + "b": 90, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "tt_Stamp_Flower_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": null, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + } + ] +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBenchTests/Data/NW4R/LayoutLib/Layout/golf_00.json b/tools/workbench/LibWorkBenchTests/Data/NW4R/LayoutLib/Layout/golf_00.json new file mode 100644 index 0000000..6352b88 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Data/NW4R/LayoutLib/Layout/golf_00.json @@ -0,0 +1,18314 @@ +{ + "version": 8, + "origin_type": "CENTER", + "size": { + "width": 608, + "height": 456 + }, + "root_pane": { + "kind": "pane", + "name": "RootPane", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 608, + "height": 456 + }, + "children": [ + { + "kind": "pane", + "name": "N_golf_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_indRT_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": true, + "base_position": { + "h": "CENTER", + "v": "BOTTOM" + }, + "alpha": 255, + "translate": { + "x": 276, + "y": 169, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 80 + }, + "children": [ + { + "kind": "pane", + "name": "N_holePin_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 44, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_LineHolePin_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -170, + "y": 2, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_LineHolePin_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_LineHolePin_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -2.170273, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 80, + "height": 2 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_LineHolePin_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_LineHolePin_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -2.170242, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 170, + "height": 2 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_tHole_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -45, + "y": 14, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_hole_01", + "font_name": "pac_nRodDb_32_IA4.brfnt", + "font_size": { + "width": 24.5, + "height": 24.5 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u30DB\u30FC\u30EB4\u3000 \u30D1\u30FC4", + "text_capacity": 20, + "text_position": { + "h": "RIGHT", + "v": "TOP" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_hole_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 3, + "y": -3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 168, + "height": 25 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_hole_00", + "font_name": "pac_nRodDb_32_IA4.brfnt", + "font_size": { + "width": 24.5, + "height": 24.5 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u30DB\u30FC\u30EB4\u3000 \u30D1\u30FC4", + "text_capacity": 20, + "text_position": { + "h": "RIGHT", + "v": "TOP" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_hole_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 168, + "height": 25 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_tPin_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -45, + "y": 14, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_pin_01", + "font_name": "pac_nRodDb_32_IA4.brfnt", + "font_size": { + "width": 24.5, + "height": 24.5 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u306E\u3053\u308A\u300044.4m", + "text_capacity": 20, + "text_position": { + "h": "RIGHT", + "v": "TOP" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_pin_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 3, + "y": -3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 168, + "height": 25 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_pin_00", + "font_name": "pac_nRodDb_32_IA4.brfnt", + "font_size": { + "width": 24.5, + "height": 24.5 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u306E\u3053\u308A\u300044.4m", + "text_capacity": 20, + "text_position": { + "h": "RIGHT", + "v": "TOP" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_pin_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 168, + "height": 25 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_wind_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 44, + "y": -35, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 29, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_windBase_08", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 130 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 130 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 7, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 7, + "y": 1 + } + } + ], + "name": "P_windBase_08", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 224, + "height": -32 + }, + "children": [] + }, + { + "kind": "pane", + "name": "N_LineWind_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -118, + "y": -8, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_LineWind_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 50 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 50 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_LineWind_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -2, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 80, + "height": 2 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_LineWind_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_LineWind_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -2, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 120, + "height": 2 + }, + "children": [] + }, + { + "kind": "pane", + "name": "N_3dWindPo_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 32, + "y": 6, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_windW3d_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -19, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_windW3d_01", + "font_name": "pac_nRodDb_32_IA4.brfnt", + "font_size": { + "width": 24.5, + "height": 24.5 + }, + "char_space": 0, + "line_space": 0, + "text_content": "Wind", + "text_capacity": 10, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_windW3d_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 2, + "y": -2, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 78, + "height": 28 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_windW3d_00", + "font_name": "pac_nRodDb_32_IA4.brfnt", + "font_size": { + "width": 24.5, + "height": 24.5 + }, + "char_space": 0, + "line_space": 0, + "text_content": "Wind", + "text_capacity": 10, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_windW3d_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 78, + "height": 28 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_tWind_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -161, + "y": 3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_uWind_01", + "font_name": "pac_nRodDb_32_I4.brfnt", + "font_size": { + "width": 19.2, + "height": 19.2 + }, + "char_space": 0, + "line_space": 0, + "text_content": "mph", + "text_capacity": 8, + "text_position": { + "h": "LEFT", + "v": "BOTTOM" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_uWind_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 2, + "y": -2, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 36, + "height": 25 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_uWind_00", + "font_name": "pac_nRodDb_32_I4.brfnt", + "font_size": { + "width": 19.2, + "height": 19.2 + }, + "char_space": 0, + "line_space": 0, + "text_content": "mph", + "text_capacity": 8, + "text_position": { + "h": "LEFT", + "v": "BOTTOM" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_uWind_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 2, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 36, + "height": 25 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_nWind_01", + "font_name": "pac_nRodDb_32_I4.brfnt", + "font_size": { + "width": 25.6, + "height": 25.6 + }, + "char_space": 0, + "line_space": 0, + "text_content": "34", + "text_capacity": 6, + "text_position": { + "h": "RIGHT", + "v": "BOTTOM" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_nWind_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -2, + "y": -2, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 34, + "height": 25 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_nWind_00", + "font_name": "pac_nRodDb_32_I4.brfnt", + "font_size": { + "width": 25.6, + "height": 25.6 + }, + "char_space": 0, + "line_space": 0, + "text_content": "34", + "text_capacity": 6, + "text_position": { + "h": "RIGHT", + "v": "BOTTOM" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_nWind_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -2, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 34, + "height": 25 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_contourPoAd_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": true, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 276, + "y": 115, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_contour_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -30, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 10 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_contour_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_contour_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 14, + "height": 60 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_contour_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_contour_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 12, + "height": 58 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_contour_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_contour_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 8, + "height": 56 + }, + "children": [] + }, + { + "kind": "pane", + "name": "N_tHigh_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 42, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_high_01", + "font_name": "pac_nRodDb_32_IA4.brfnt", + "font_size": { + "width": 21, + "height": 21 + }, + "char_space": 0, + "line_space": 0, + "text_content": "High", + "text_capacity": 10, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_high_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -2, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 58, + "height": 16 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_high_00", + "font_name": "pac_nRodDb_32_IA4.brfnt", + "font_size": { + "width": 21, + "height": 21 + }, + "char_space": 0, + "line_space": 0, + "text_content": "High", + "text_capacity": 10, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_high_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 58, + "height": 16 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_tLow_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -40, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_low_01", + "font_name": "pac_nRodDb_32_IA4.brfnt", + "font_size": { + "width": 21, + "height": 21 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u3072\u304F\u3044", + "text_capacity": 8, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_low_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -2, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 58, + "height": 16 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_low_00", + "font_name": "pac_nRodDb_32_IA4.brfnt", + "font_size": { + "width": 21, + "height": 21 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u3072\u304F\u3044", + "text_capacity": 8, + "text_position": { + "h": "CENTER", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_low_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 58, + "height": 16 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_ballsTotal_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": true, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -276, + "y": 140.5981, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_ballsBase_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 164, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_ballsBase_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 50 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 50 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 7, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 7, + "y": 1 + } + } + ], + "name": "P_ballsBase_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "BOTTOM" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 2.598099, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": -224, + "height": 48 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballsBase_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 7, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 7, + "y": 1 + } + } + ], + "name": "P_ballsBase_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "BOTTOM" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 2.598099, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": -224, + "height": -32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballsLine_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballsLine_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 2.598099, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 220, + "height": 1 + }, + "children": [] + }, + { + "kind": "window", + "content": { + "material_name": "W_ballsFrame_00C ", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ] + }, + "inflation": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "frames": [ + { + "material_name": "W_ballsFrame_00LT", + "texture_flip": "NONE" + } + ], + "name": "W_ballsFrame_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 10.4068, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 222, + "height": 80 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_total_00", + "font_name": "pac_nRodDb_32_I4.brfnt", + "font_size": { + "width": 20.8, + "height": 20.8 + }, + "char_space": 0, + "line_space": 0, + "text_content": "Gesamt 444.4 ft\n", + "text_capacity": 34, + "text_position": { + "h": "LEFT", + "v": "TOP" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_total_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -163.94305, + "y": -14.680809, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 154, + "height": 23 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_ballsTBase_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 164, + "y": 35.4019, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_ballsTBase_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 50 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 50 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 8, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 8, + "y": 1 + } + } + ], + "name": "P_ballsTBase_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": -224, + "height": 28 + }, + "children": [] + }, + { + "kind": "window", + "content": { + "material_name": "W_ballsTFrame_00C ", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ] + }, + "inflation": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "frames": [ + { + "material_name": "W_ballsTFrame_00LT", + "texture_flip": "NONE" + } + ], + "name": "W_ballsTFrame_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 224, + "height": 28 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_balls_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 11.976288, + "y": 35.870804, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_ball_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 4, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_gradeH_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_gradeH_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 40, + "height": 40 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_grade_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_grade_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballOff_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballOff_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 180, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballMiss_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballMiss_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 200, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0, + "y": 0 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ball_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ball_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_ball_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 34, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_gradeH_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_gradeH_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 40, + "height": 40 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_grade_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_grade_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballOff_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballOff_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballMiss_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballMiss_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ball_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ball_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_ball_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 64, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_gradeH_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_gradeH_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 40, + "height": 40 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_grade_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_grade_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballOff_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballOff_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballMiss_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballMiss_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ball_02", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ball_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_ball_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 94, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_gradeH_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_gradeH_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 40, + "height": 40 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_grade_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_grade_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballOff_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballOff_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballMiss_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballMiss_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ball_03", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ball_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_ball_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 124, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_gradeH_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_gradeH_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 40, + "height": 40 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_grade_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_grade_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballOff_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballOff_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballMiss_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballMiss_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ball_04", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ball_04", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_balls_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 11.976288, + "y": 14.870804, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_ball_05", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 4, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_gradeH_05", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_gradeH_05", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 40, + "height": 40 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_grade_05", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_grade_05", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballOff_05", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballOff_05", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballMiss_05", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballMiss_05", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ball_05", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ball_05", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_ball_06", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 34, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_gradeH_06", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_gradeH_06", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 40, + "height": 40 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_grade_06", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_grade_06", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballOff_06", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballOff_06", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballMiss_06", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballMiss_06", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ball_06", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ball_06", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_ball_07", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 64, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_gradeH_07", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_gradeH_07", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 40, + "height": 40 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_grade_07", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_grade_07", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballOff_07", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballOff_07", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballMiss_07", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballMiss_07", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ball_07", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ball_07", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_ball_08", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 94, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_gradeH_08", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_gradeH_08", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 40, + "height": 40 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_grade_08", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_grade_08", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballOff_08", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballOff_08", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballMiss_08", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballMiss_08", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ball_08", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ball_08", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + } + ] + }, + { + "kind": "pane", + "name": "N_ball_09", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 124, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_gradeH_09", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_gradeH_09", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 40, + "height": 40 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_grade_09", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_grade_09", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballOff_09", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballOff_09", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ballMiss_09", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ballMiss_09", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_ball_09", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_ball_09", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_club_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": true, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -276, + "y": -180, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_clubBase_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 30 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 30 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 21, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 21, + "y": 1 + } + } + ], + "name": "P_clubBase_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -44, + "y": -4, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": -502, + "height": 24 + }, + "children": [] + }, + { + "kind": "pane", + "name": "N_cPad_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 180, + "translate": { + "x": 9, + "y": 22.999985, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_cPad_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_cPad_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_dotB_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_dotB_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -8, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 6, + "height": 6 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_dotT_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_dotT_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 8, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 6, + "height": 6 + }, + "children": [] + } + ] + }, + { + "kind": "picture", + "material_name": "P_clubIcon_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_clubIcon_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 47, + "y": 10, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.45, + "y": 0.45 + }, + "size": { + "width": 99, + "height": 149 + }, + "children": [] + }, + { + "kind": "pane", + "name": "N_tClub_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 61, + "y": 6, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_club_01", + "font_name": "pac_nRodEb_70_IA4.brfnt", + "font_size": { + "width": 28, + "height": 28 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u30C9\u30E9\u30A4\u30D0\u30FC", + "text_capacity": 12, + "text_position": { + "h": "LEFT", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_club_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 100, + "height": 23 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_club_00", + "font_name": "pac_nRodEb_70_IA4.brfnt", + "font_size": { + "width": 28, + "height": 28 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u30C9\u30E9\u30A4\u30D0\u30FC", + "text_capacity": 12, + "text_position": { + "h": "LEFT", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 195, + "b": 0, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 113, + "a": 255 + } + }, + "name": "T_club_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "LEFT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 100, + "height": 23 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_club_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": true, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 276, + "y": -180, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_clubBase_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 30 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 30 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 21, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 21, + "y": 1 + } + } + ], + "name": "P_clubBase_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 44, + "y": -4, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.5, + "y": 0.5 + }, + "size": { + "width": 502, + "height": 24 + }, + "children": [] + }, + { + "kind": "pane", + "name": "N_cPad_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 180, + "translate": { + "x": -9, + "y": 23, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_cPad_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_cPad_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 32, + "height": 32 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_dotB_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_dotB_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -8, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 6, + "height": 6 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_dotT_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_dotT_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 8, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 6, + "height": 6 + }, + "children": [] + } + ] + }, + { + "kind": "picture", + "material_name": "P_clubIcon_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_clubIcon_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -47, + "y": 10, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 0.45, + "y": 0.45 + }, + "size": { + "width": -99, + "height": 149 + }, + "children": [] + }, + { + "kind": "pane", + "name": "N_tClub_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -61, + "y": 6, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "textbox", + "material_name": "T_club_03", + "font_name": "pac_nRodEb_70_IA4.brfnt", + "font_size": { + "width": 28, + "height": 28 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u30C9\u30E9\u30A4\u30D0\u30FC", + "text_capacity": 12, + "text_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "name": "T_club_03", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -3, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 100, + "height": 23 + }, + "children": [] + }, + { + "kind": "textbox", + "material_name": "T_club_02", + "font_name": "pac_nRodEb_70_IA4.brfnt", + "font_size": { + "width": 28, + "height": 28 + }, + "char_space": 0, + "line_space": 0, + "text_content": "\u30C9\u30E9\u30A4\u30D0\u30FC", + "text_capacity": 12, + "text_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "text_alignment": "LEFT", + "text_colors": { + "top": { + "r": 255, + "g": 195, + "b": 0, + "a": 255 + }, + "bottom": { + "r": 255, + "g": 255, + "b": 113, + "a": 255 + } + }, + "name": "T_club_02", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "RIGHT", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 100, + "height": 23 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_mapWiPoAd_00", + "user_data": "43", + "visible": true, + "influenced_alpha": false, + "location_adjust": true, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 276, + "y": -197.07, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_mapWindow_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "TOP" + }, + "alpha": 255, + "translate": { + "x": -100, + "y": 131.0723, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_mapWiBg_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_mapWiBg_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 192, + "height": 248 + }, + "children": [] + }, + { + "kind": "window", + "content": { + "material_name": "W_mapWiFrame_00C ", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ] + }, + "inflation": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "frames": [ + { + "material_name": "W_mapWiFrame_00LT", + "texture_flip": "NONE" + }, + { + "material_name": "W_mapWiFrame_00RT", + "texture_flip": "NONE" + }, + { + "material_name": "W_mapWiFrame_00LB", + "texture_flip": "NONE" + }, + { + "material_name": "W_mapWiFrame_00RB", + "texture_flip": "NONE" + } + ], + "name": "W_mapWiFrame_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 212, + "height": 266 + }, + "children": [] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_mapWiPoAd_01", + "user_data": "43", + "visible": true, + "influenced_alpha": false, + "location_adjust": true, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -276, + "y": -197.07, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "pane", + "name": "N_mapWindow_01", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "TOP" + }, + "alpha": 255, + "translate": { + "x": 100, + "y": 131.0723, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_mapWiBg_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_mapWiBg_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 194, + "height": 248 + }, + "children": [] + }, + { + "kind": "window", + "content": { + "material_name": "W_mapWiFrame_01C ", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ] + }, + "inflation": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "frames": [ + { + "material_name": "W_mapWiFrame_01LT", + "texture_flip": "NONE" + }, + { + "material_name": "W_mapWiFrame_01RT", + "texture_flip": "NONE" + }, + { + "material_name": "W_mapWiFrame_01LB", + "texture_flip": "NONE" + }, + { + "material_name": "W_mapWiFrame_01RB", + "texture_flip": "NONE" + } + ], + "name": "W_mapWiFrame_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": 0, + "y": 0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 212, + "height": 266 + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "kind": "pane", + "name": "N_AButton_00", + "user_data": "", + "visible": true, + "influenced_alpha": true, + "location_adjust": true, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 0, + "translate": { + "x": -0, + "y": -176, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 40 + }, + "children": [ + { + "kind": "picture", + "material_name": "P_AButton_01", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_AButton_01", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 30, + "height": 30 + }, + "children": [] + }, + { + "kind": "picture", + "material_name": "P_AButton_00", + "vertex_colors": { + "left_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_top": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "left_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "right_bottom": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_coords": [ + { + "left_top": { + "x": 0, + "y": 0 + }, + "right_top": { + "x": 1, + "y": 0 + }, + "left_bottom": { + "x": 0, + "y": 1 + }, + "right_bottom": { + "x": 1, + "y": 1 + } + } + ], + "name": "P_AButton_00", + "user_data": "", + "visible": true, + "influenced_alpha": false, + "location_adjust": false, + "base_position": { + "h": "CENTER", + "v": "CENTER" + }, + "alpha": 255, + "translate": { + "x": -0, + "y": -0, + "z": 0 + }, + "rotate": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": { + "x": 1, + "y": 1 + }, + "size": { + "width": 26, + "height": 26 + }, + "children": [] + } + ] + } + ] + }, + "root_group": { + "name": "RootGroup", + "pane_names": [], + "children": [] + }, + "materials": [ + { + "name": "T_nWind_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_club_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 0, + "b": 128, + "a": 150 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_club_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 128, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_LineHolePin_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 255, + "b": 255, + "a": 155 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_LineHolePin_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 255, + "b": 255, + "a": 155 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_pin_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 0, + "b": 0, + "a": 100 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_pin_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_LineWind_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_LineWind_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_hole_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 0, + "b": 0, + "a": 100 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_hole_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_clubBase_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_triangle24_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_total_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ball_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBall_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_mapWiBg_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 120 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_ballsFrame_00C ", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_ballsFrame_00LT", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfScoreBgLine_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballsLine_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 100 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballsBase_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 150 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfScoreBgL_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballsBase_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfScoreBgL_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_clubIcon_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_club1W_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballOff_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallOff_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_grade_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 0, + "a": 0 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_gradeH_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 100, + "b": 0, + "a": 0 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballMiss_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallMiss_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballMiss_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallMiss_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballOff_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 180 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallOff_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ball_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBall_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_grade_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_gradeH_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 100, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballMiss_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallMiss_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballOff_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 180 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallOff_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ball_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBall_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_grade_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_gradeH_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 100, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballMiss_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallMiss_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballOff_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 180 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallOff_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ball_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBall_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_grade_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_gradeH_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 100, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballMiss_04", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallMiss_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballOff_04", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 180 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallOff_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ball_04", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBall_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_grade_04", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_gradeH_04", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 100, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballMiss_05", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallMiss_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballOff_05", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 180 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallOff_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ball_05", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBall_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_grade_05", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_gradeH_05", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 100, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballMiss_06", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallMiss_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballOff_06", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 180 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallOff_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ball_06", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBall_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_grade_06", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_gradeH_06", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 100, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballMiss_07", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallMiss_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballOff_07", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 180 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallOff_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ball_07", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBall_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_grade_07", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_gradeH_07", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 100, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballMiss_08", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallMiss_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballOff_08", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 180 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallOff_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ball_08", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBall_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_grade_08", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_gradeH_08", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 100, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballMiss_09", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallMiss_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballOff_09", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 180 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallOff_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ball_09", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBall_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_grade_09", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_gradeH_09", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 119, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfBallGrade_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_ballsTFrame_00C ", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_ballsTFrame_00LT", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfScoreBgLine_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_ballsTBase_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfScoreBg_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_clubBase_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_triangle24_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_clubIcon_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_club1W_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_club_03", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 0, + "b": 128, + "a": 150 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_club_02", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 128, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_windBase_08", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 1, + "g": 176, + "b": 183, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_triangle32_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_mapWiBg_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 120 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_mapWiFrame_01C ", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_mapWiFrame_01LT", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfMapWindow_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_mapWiFrame_01RT", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfMapWindow_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_mapWiFrame_01LB", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfMapWindow_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_mapWiFrame_01RB", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfMapWindow_03.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_AButton_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "stm_aButton_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_AButton_01", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "stm_aButton_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_mapWiFrame_00C ", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_mapWiFrame_00LT", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfMapWindow_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_mapWiFrame_00RT", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfMapWindow_01.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_mapWiFrame_00LB", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfMapWindow_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "W_mapWiFrame_00RB", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_glfMapWindow_03.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_cPad_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "stm_plusButton_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_dotB_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 0, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "stm_circle_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_dotT_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 0, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "stm_circle_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_cPad_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "stm_plusButton_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_dotB_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 0, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "stm_circle_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_dotT_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 0, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "stm_circle_02.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_contour_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_contour_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_contour_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 0, + "b": 0, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_windW3d_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_windW3d_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 0, + "b": 0, + "a": 100 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_low_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 0, + "b": 0, + "a": 100 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_low_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_high_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 0, + "b": 0, + "a": 100 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_high_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "P_contour_02", + "tev_colors": { + "reg0": { + "r": 255, + "g": 255, + "b": 255, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 200 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [ + { + "texture_name": "te_squareWhite_00.tpl", + "wrap_s": "GX_CLAMP", + "wrap_t": "GX_CLAMP" + } + ], + "tex_srts": [ + { + "translate": { + "x": 0, + "y": 0 + }, + "rotate": 0, + "scale": { + "x": 1, + "y": 1 + } + } + ], + "tex_coord_gens": [ + { + "type": "GX_TG_MTX2X4", + "src": "GX_TG_TEX0", + "mtx": "GX_TEXMTX0" + } + ], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_uWind_00", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_uWind_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + }, + { + "name": "T_nWind_01", + "tev_colors": { + "reg0": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "reg1": { + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "reg2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tev_k_colors": { + "color0": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color1": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color2": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "color3": { + "r": 255, + "g": 255, + "b": 255, + "a": 255 + } + }, + "tex_maps": [], + "tex_srts": [], + "tex_coord_gens": [], + "tev_swap_table": null, + "ind_tex_srts": [], + "ind_stages": [], + "tev_stages": [], + "alpha_compare": { + "compare0": "GX_ALWAYS", + "ref0": 0, + "compare1": "GX_ALWAYS", + "ref1": 0, + "op": "GX_AOP_AND" + }, + "blend_mode": null, + "chan_ctrl": null, + "material_color": null + } + ] +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBenchTests/Data/Pack/Party/Pnp/LevelTable/leveltable.json b/tools/workbench/LibWorkBenchTests/Data/Pack/Party/Pnp/LevelTable/leveltable.json new file mode 100644 index 0000000..b47ae77 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Data/Pack/Party/Pnp/LevelTable/leveltable.json @@ -0,0 +1,70 @@ +{ + "version": 0, + "levels": [ + { + "easy_chance": 1, + "medium_chance": 0, + "hard_chance": 0 + }, + { + "easy_chance": 0, + "medium_chance": 1, + "hard_chance": 0 + }, + { + "easy_chance": 5, + "medium_chance": 4, + "hard_chance": 1 + }, + { + "easy_chance": 4, + "medium_chance": 5, + "hard_chance": 1 + }, + { + "easy_chance": 3, + "medium_chance": 6, + "hard_chance": 1 + }, + { + "easy_chance": 3, + "medium_chance": 5, + "hard_chance": 2 + }, + { + "easy_chance": 2, + "medium_chance": 5, + "hard_chance": 3 + }, + { + "easy_chance": 2, + "medium_chance": 4, + "hard_chance": 4 + }, + { + "easy_chance": 2, + "medium_chance": 3, + "hard_chance": 5 + }, + { + "easy_chance": 1, + "medium_chance": 3, + "hard_chance": 6 + }, + { + "easy_chance": 3, + "medium_chance": 0, + "hard_chance": 7 + }, + { + "easy_chance": 1, + "medium_chance": 0, + "hard_chance": 9 + }, + { + "easy_chance": 0, + "medium_chance": 0, + "hard_chance": 1 + } + ] +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBenchTests/Data/Pack/Party/Pnp/RallyLevelUpTable/rallyleveluptable.json b/tools/workbench/LibWorkBenchTests/Data/Pack/Party/Pnp/RallyLevelUpTable/rallyleveluptable.json new file mode 100644 index 0000000..30b07b2 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Data/Pack/Party/Pnp/RallyLevelUpTable/rallyleveluptable.json @@ -0,0 +1,1089 @@ +{ + "levels": [ + { + "rally": 0, + "level_index": 0, + "power": 0.65 + }, + { + "rally": 1, + "level_index": 0, + "power": 0.7 + }, + { + "rally": 2, + "level_index": 1, + "power": 0.75 + }, + { + "rally": 3, + "level_index": 2, + "power": 0.8 + }, + { + "rally": 5, + "level_index": 3, + "power": 0.85 + }, + { + "rally": 7, + "level_index": 4, + "power": 0.9 + }, + { + "rally": 10, + "level_index": 1, + "power": 0.75 + }, + { + "rally": 11, + "level_index": 2, + "power": 0.8 + }, + { + "rally": 13, + "level_index": 3, + "power": 0.85 + }, + { + "rally": 17, + "level_index": 4, + "power": 0.9 + }, + { + "rally": 22, + "level_index": 5, + "power": 0.95 + }, + { + "rally": 25, + "level_index": 3, + "power": 0.85 + }, + { + "rally": 28, + "level_index": 4, + "power": 0.9 + }, + { + "rally": 32, + "level_index": 5, + "power": 0.95 + }, + { + "rally": 35, + "level_index": 6, + "power": 1 + }, + { + "rally": 40, + "level_index": 7, + "power": 1.05 + }, + { + "rally": 45, + "level_index": 8, + "power": 1.1 + }, + { + "rally": 50, + "level_index": 9, + "power": 1.15 + }, + { + "rally": 70, + "level_index": 9, + "power": 1.2 + }, + { + "rally": 90, + "level_index": 9, + "power": 1.25 + }, + { + "rally": 100, + "level_index": 4, + "power": 0.9 + }, + { + "rally": 103, + "level_index": 5, + "power": 0.95 + }, + { + "rally": 108, + "level_index": 6, + "power": 1 + }, + { + "rally": 111, + "level_index": 7, + "power": 1.05 + }, + { + "rally": 115, + "level_index": 8, + "power": 1.1 + }, + { + "rally": 120, + "level_index": 9, + "power": 1.15 + }, + { + "rally": 125, + "level_index": 6, + "power": 1.2 + }, + { + "rally": 130, + "level_index": 7, + "power": 1.25 + }, + { + "rally": 135, + "level_index": 8, + "power": 1.3 + }, + { + "rally": 140, + "level_index": 9, + "power": 1.35 + }, + { + "rally": 145, + "level_index": 10, + "power": 1.4 + }, + { + "rally": 150, + "level_index": 5, + "power": 1.1 + }, + { + "rally": 152, + "level_index": 6, + "power": 1.15 + }, + { + "rally": 155, + "level_index": 8, + "power": 1.2 + }, + { + "rally": 157, + "level_index": 7, + "power": 1.25 + }, + { + "rally": 160, + "level_index": 8, + "power": 1.3 + }, + { + "rally": 165, + "level_index": 9, + "power": 1.35 + }, + { + "rally": 170, + "level_index": 10, + "power": 1.4 + }, + { + "rally": 177, + "level_index": 10, + "power": 1.45 + }, + { + "rally": 185, + "level_index": 11, + "power": 1.5 + }, + { + "rally": 188, + "level_index": 11, + "power": 1.55 + }, + { + "rally": 190, + "level_index": 11, + "power": 1.6 + }, + { + "rally": 193, + "level_index": 12, + "power": 1.65 + }, + { + "rally": 195, + "level_index": 12, + "power": 1.7 + }, + { + "rally": 200, + "level_index": 4, + "power": 0.93 + }, + { + "rally": 202, + "level_index": 5, + "power": 0.98 + }, + { + "rally": 207, + "level_index": 6, + "power": 1.03 + }, + { + "rally": 210, + "level_index": 7, + "power": 1.08 + }, + { + "rally": 214, + "level_index": 8, + "power": 1.13 + }, + { + "rally": 219, + "level_index": 9, + "power": 1.18 + }, + { + "rally": 224, + "level_index": 6, + "power": 1.23 + }, + { + "rally": 229, + "level_index": 7, + "power": 1.28 + }, + { + "rally": 234, + "level_index": 8, + "power": 1.33 + }, + { + "rally": 239, + "level_index": 9, + "power": 1.38 + }, + { + "rally": 244, + "level_index": 10, + "power": 1.43 + }, + { + "rally": 250, + "level_index": 5, + "power": 1.13 + }, + { + "rally": 252, + "level_index": 6, + "power": 1.18 + }, + { + "rally": 254, + "level_index": 8, + "power": 1.23 + }, + { + "rally": 256, + "level_index": 7, + "power": 1.28 + }, + { + "rally": 259, + "level_index": 8, + "power": 1.33 + }, + { + "rally": 264, + "level_index": 9, + "power": 1.38 + }, + { + "rally": 269, + "level_index": 10, + "power": 1.43 + }, + { + "rally": 276, + "level_index": 10, + "power": 1.48 + }, + { + "rally": 284, + "level_index": 11, + "power": 1.53 + }, + { + "rally": 287, + "level_index": 11, + "power": 1.58 + }, + { + "rally": 289, + "level_index": 11, + "power": 1.63 + }, + { + "rally": 292, + "level_index": 12, + "power": 1.68 + }, + { + "rally": 294, + "level_index": 12, + "power": 1.73 + }, + { + "rally": 300, + "level_index": 4, + "power": 0.96 + }, + { + "rally": 301, + "level_index": 5, + "power": 1.01 + }, + { + "rally": 306, + "level_index": 6, + "power": 1.06 + }, + { + "rally": 309, + "level_index": 7, + "power": 1.11 + }, + { + "rally": 313, + "level_index": 8, + "power": 1.16 + }, + { + "rally": 318, + "level_index": 9, + "power": 1.21 + }, + { + "rally": 323, + "level_index": 6, + "power": 1.26 + }, + { + "rally": 328, + "level_index": 7, + "power": 1.31 + }, + { + "rally": 333, + "level_index": 8, + "power": 1.36 + }, + { + "rally": 338, + "level_index": 9, + "power": 1.41 + }, + { + "rally": 343, + "level_index": 10, + "power": 1.46 + }, + { + "rally": 350, + "level_index": 6, + "power": 1.21 + }, + { + "rally": 353, + "level_index": 8, + "power": 1.26 + }, + { + "rally": 355, + "level_index": 7, + "power": 1.31 + }, + { + "rally": 358, + "level_index": 8, + "power": 1.36 + }, + { + "rally": 363, + "level_index": 9, + "power": 1.41 + }, + { + "rally": 368, + "level_index": 10, + "power": 1.46 + }, + { + "rally": 375, + "level_index": 10, + "power": 1.51 + }, + { + "rally": 383, + "level_index": 11, + "power": 1.56 + }, + { + "rally": 386, + "level_index": 11, + "power": 1.61 + }, + { + "rally": 388, + "level_index": 11, + "power": 1.66 + }, + { + "rally": 391, + "level_index": 12, + "power": 1.71 + }, + { + "rally": 393, + "level_index": 12, + "power": 1.76 + }, + { + "rally": 400, + "level_index": 5, + "power": 1.04 + }, + { + "rally": 405, + "level_index": 6, + "power": 1.09 + }, + { + "rally": 408, + "level_index": 7, + "power": 1.14 + }, + { + "rally": 412, + "level_index": 8, + "power": 1.19 + }, + { + "rally": 417, + "level_index": 9, + "power": 1.24 + }, + { + "rally": 422, + "level_index": 6, + "power": 1.29 + }, + { + "rally": 427, + "level_index": 7, + "power": 1.34 + }, + { + "rally": 432, + "level_index": 8, + "power": 1.39 + }, + { + "rally": 437, + "level_index": 9, + "power": 1.44 + }, + { + "rally": 442, + "level_index": 10, + "power": 1.49 + }, + { + "rally": 450, + "level_index": 6, + "power": 1.24 + }, + { + "rally": 452, + "level_index": 8, + "power": 1.29 + }, + { + "rally": 454, + "level_index": 7, + "power": 1.34 + }, + { + "rally": 457, + "level_index": 8, + "power": 1.39 + }, + { + "rally": 462, + "level_index": 9, + "power": 1.44 + }, + { + "rally": 467, + "level_index": 10, + "power": 1.49 + }, + { + "rally": 474, + "level_index": 10, + "power": 1.54 + }, + { + "rally": 482, + "level_index": 11, + "power": 1.59 + }, + { + "rally": 485, + "level_index": 11, + "power": 1.64 + }, + { + "rally": 487, + "level_index": 11, + "power": 1.69 + }, + { + "rally": 490, + "level_index": 12, + "power": 1.74 + }, + { + "rally": 492, + "level_index": 12, + "power": 1.79 + }, + { + "rally": 500, + "level_index": 5, + "power": 1.07 + }, + { + "rally": 504, + "level_index": 6, + "power": 1.12 + }, + { + "rally": 507, + "level_index": 7, + "power": 1.17 + }, + { + "rally": 511, + "level_index": 8, + "power": 1.22 + }, + { + "rally": 516, + "level_index": 9, + "power": 1.27 + }, + { + "rally": 521, + "level_index": 6, + "power": 1.32 + }, + { + "rally": 526, + "level_index": 7, + "power": 1.37 + }, + { + "rally": 531, + "level_index": 8, + "power": 1.42 + }, + { + "rally": 536, + "level_index": 9, + "power": 1.47 + }, + { + "rally": 541, + "level_index": 10, + "power": 1.52 + }, + { + "rally": 550, + "level_index": 6, + "power": 1.27 + }, + { + "rally": 551, + "level_index": 8, + "power": 1.32 + }, + { + "rally": 553, + "level_index": 7, + "power": 1.37 + }, + { + "rally": 556, + "level_index": 8, + "power": 1.42 + }, + { + "rally": 561, + "level_index": 9, + "power": 1.47 + }, + { + "rally": 566, + "level_index": 10, + "power": 1.52 + }, + { + "rally": 573, + "level_index": 10, + "power": 1.57 + }, + { + "rally": 581, + "level_index": 11, + "power": 1.62 + }, + { + "rally": 584, + "level_index": 11, + "power": 1.67 + }, + { + "rally": 586, + "level_index": 11, + "power": 1.72 + }, + { + "rally": 589, + "level_index": 12, + "power": 1.77 + }, + { + "rally": 591, + "level_index": 12, + "power": 1.82 + }, + { + "rally": 600, + "level_index": 5, + "power": 1.1 + }, + { + "rally": 603, + "level_index": 6, + "power": 1.15 + }, + { + "rally": 606, + "level_index": 7, + "power": 1.2 + }, + { + "rally": 610, + "level_index": 8, + "power": 1.25 + }, + { + "rally": 615, + "level_index": 9, + "power": 1.3 + }, + { + "rally": 620, + "level_index": 6, + "power": 1.35 + }, + { + "rally": 625, + "level_index": 7, + "power": 1.4 + }, + { + "rally": 630, + "level_index": 8, + "power": 1.45 + }, + { + "rally": 635, + "level_index": 9, + "power": 1.5 + }, + { + "rally": 640, + "level_index": 10, + "power": 1.55 + }, + { + "rally": 650, + "level_index": 8, + "power": 1.35 + }, + { + "rally": 652, + "level_index": 7, + "power": 1.4 + }, + { + "rally": 655, + "level_index": 8, + "power": 1.45 + }, + { + "rally": 660, + "level_index": 9, + "power": 1.5 + }, + { + "rally": 665, + "level_index": 10, + "power": 1.55 + }, + { + "rally": 672, + "level_index": 10, + "power": 1.6 + }, + { + "rally": 680, + "level_index": 11, + "power": 1.65 + }, + { + "rally": 683, + "level_index": 11, + "power": 1.7 + }, + { + "rally": 685, + "level_index": 11, + "power": 1.75 + }, + { + "rally": 688, + "level_index": 12, + "power": 1.8 + }, + { + "rally": 690, + "level_index": 12, + "power": 1.85 + }, + { + "rally": 700, + "level_index": 5, + "power": 1.13 + }, + { + "rally": 702, + "level_index": 6, + "power": 1.18 + }, + { + "rally": 705, + "level_index": 7, + "power": 1.23 + }, + { + "rally": 709, + "level_index": 8, + "power": 1.28 + }, + { + "rally": 714, + "level_index": 9, + "power": 1.33 + }, + { + "rally": 719, + "level_index": 6, + "power": 1.38 + }, + { + "rally": 724, + "level_index": 7, + "power": 1.43 + }, + { + "rally": 729, + "level_index": 8, + "power": 1.48 + }, + { + "rally": 734, + "level_index": 9, + "power": 1.53 + }, + { + "rally": 739, + "level_index": 10, + "power": 1.58 + }, + { + "rally": 750, + "level_index": 8, + "power": 1.38 + }, + { + "rally": 751, + "level_index": 7, + "power": 1.43 + }, + { + "rally": 754, + "level_index": 8, + "power": 1.48 + }, + { + "rally": 759, + "level_index": 9, + "power": 1.53 + }, + { + "rally": 764, + "level_index": 10, + "power": 1.58 + }, + { + "rally": 771, + "level_index": 10, + "power": 1.63 + }, + { + "rally": 779, + "level_index": 11, + "power": 1.68 + }, + { + "rally": 782, + "level_index": 11, + "power": 1.73 + }, + { + "rally": 784, + "level_index": 11, + "power": 1.78 + }, + { + "rally": 787, + "level_index": 12, + "power": 1.83 + }, + { + "rally": 789, + "level_index": 12, + "power": 1.88 + }, + { + "rally": 800, + "level_index": 5, + "power": 1.16 + }, + { + "rally": 801, + "level_index": 6, + "power": 1.21 + }, + { + "rally": 804, + "level_index": 7, + "power": 1.26 + }, + { + "rally": 808, + "level_index": 8, + "power": 1.31 + }, + { + "rally": 813, + "level_index": 9, + "power": 1.36 + }, + { + "rally": 818, + "level_index": 6, + "power": 1.41 + }, + { + "rally": 823, + "level_index": 7, + "power": 1.46 + }, + { + "rally": 828, + "level_index": 8, + "power": 1.51 + }, + { + "rally": 833, + "level_index": 9, + "power": 1.56 + }, + { + "rally": 838, + "level_index": 10, + "power": 1.61 + }, + { + "rally": 850, + "level_index": 7, + "power": 1.46 + }, + { + "rally": 853, + "level_index": 8, + "power": 1.51 + }, + { + "rally": 858, + "level_index": 9, + "power": 1.56 + }, + { + "rally": 863, + "level_index": 10, + "power": 1.61 + }, + { + "rally": 870, + "level_index": 10, + "power": 1.66 + }, + { + "rally": 878, + "level_index": 11, + "power": 1.71 + }, + { + "rally": 881, + "level_index": 11, + "power": 1.76 + }, + { + "rally": 883, + "level_index": 11, + "power": 1.81 + }, + { + "rally": 886, + "level_index": 12, + "power": 1.86 + }, + { + "rally": 888, + "level_index": 12, + "power": 1.91 + }, + { + "rally": 900, + "level_index": 6, + "power": 1.24 + }, + { + "rally": 903, + "level_index": 7, + "power": 1.29 + }, + { + "rally": 907, + "level_index": 8, + "power": 1.34 + }, + { + "rally": 912, + "level_index": 9, + "power": 1.39 + }, + { + "rally": 917, + "level_index": 6, + "power": 1.44 + }, + { + "rally": 922, + "level_index": 7, + "power": 1.49 + }, + { + "rally": 927, + "level_index": 8, + "power": 1.54 + }, + { + "rally": 932, + "level_index": 9, + "power": 1.59 + }, + { + "rally": 937, + "level_index": 10, + "power": 1.64 + }, + { + "rally": 950, + "level_index": 7, + "power": 1.49 + }, + { + "rally": 952, + "level_index": 8, + "power": 1.54 + }, + { + "rally": 957, + "level_index": 9, + "power": 1.59 + }, + { + "rally": 962, + "level_index": 10, + "power": 1.64 + }, + { + "rally": 969, + "level_index": 10, + "power": 1.69 + }, + { + "rally": 977, + "level_index": 11, + "power": 1.74 + }, + { + "rally": 980, + "level_index": 11, + "power": 1.79 + }, + { + "rally": 982, + "level_index": 11, + "power": 1.84 + }, + { + "rally": 985, + "level_index": 12, + "power": 1.89 + }, + { + "rally": 987, + "level_index": 12, + "power": 1.94 + }, + { + "rally": 1000, + "level_index": 4, + "power": 1.17 + } + ] +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBenchTests/Data/Pack/Party/Pnp/RallyLevelUpTable/rallyleveluptable2.json b/tools/workbench/LibWorkBenchTests/Data/Pack/Party/Pnp/RallyLevelUpTable/rallyleveluptable2.json new file mode 100644 index 0000000..ccdef35 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Data/Pack/Party/Pnp/RallyLevelUpTable/rallyleveluptable2.json @@ -0,0 +1,509 @@ +{ + "levels": [ + { + "rally": 0, + "level_index": 0, + "power": 0.65 + }, + { + "rally": 1, + "level_index": 0, + "power": 0.69 + }, + { + "rally": 2, + "level_index": 0, + "power": 0.72 + }, + { + "rally": 3, + "level_index": 0, + "power": 0.76 + }, + { + "rally": 4, + "level_index": 0, + "power": 0.79 + }, + { + "rally": 5, + "level_index": 0, + "power": 0.83 + }, + { + "rally": 6, + "level_index": 0, + "power": 0.86 + }, + { + "rally": 7, + "level_index": 0, + "power": 0.9 + }, + { + "rally": 8, + "level_index": 0, + "power": 0.93 + }, + { + "rally": 9, + "level_index": 0, + "power": 0.97 + }, + { + "rally": 10, + "level_index": 0, + "power": 1 + }, + { + "rally": 11, + "level_index": 0, + "power": 1.02 + }, + { + "rally": 12, + "level_index": 0, + "power": 1.03 + }, + { + "rally": 13, + "level_index": 0, + "power": 1.05 + }, + { + "rally": 14, + "level_index": 0, + "power": 1.07 + }, + { + "rally": 15, + "level_index": 0, + "power": 1.08 + }, + { + "rally": 16, + "level_index": 0, + "power": 1.1 + }, + { + "rally": 17, + "level_index": 0, + "power": 1.12 + }, + { + "rally": 18, + "level_index": 0, + "power": 1.13 + }, + { + "rally": 19, + "level_index": 0, + "power": 1.15 + }, + { + "rally": 20, + "level_index": 0, + "power": 1.17 + }, + { + "rally": 21, + "level_index": 0, + "power": 1.18 + }, + { + "rally": 22, + "level_index": 0, + "power": 1.2 + }, + { + "rally": 23, + "level_index": 0, + "power": 1.22 + }, + { + "rally": 24, + "level_index": 0, + "power": 1.23 + }, + { + "rally": 25, + "level_index": 0, + "power": 1.25 + }, + { + "rally": 26, + "level_index": 0, + "power": 1.27 + }, + { + "rally": 27, + "level_index": 0, + "power": 1.28 + }, + { + "rally": 28, + "level_index": 0, + "power": 1.3 + }, + { + "rally": 29, + "level_index": 0, + "power": 1.32 + }, + { + "rally": 30, + "level_index": 0, + "power": 1.33 + }, + { + "rally": 31, + "level_index": 0, + "power": 1.35 + }, + { + "rally": 32, + "level_index": 0, + "power": 1.37 + }, + { + "rally": 33, + "level_index": 0, + "power": 1.38 + }, + { + "rally": 34, + "level_index": 0, + "power": 1.4 + }, + { + "rally": 35, + "level_index": 0, + "power": 1.42 + }, + { + "rally": 36, + "level_index": 0, + "power": 1.43 + }, + { + "rally": 37, + "level_index": 0, + "power": 1.45 + }, + { + "rally": 38, + "level_index": 0, + "power": 1.47 + }, + { + "rally": 39, + "level_index": 0, + "power": 1.48 + }, + { + "rally": 40, + "level_index": 0, + "power": 1.5 + }, + { + "rally": 41, + "level_index": 0, + "power": 1.51 + }, + { + "rally": 42, + "level_index": 0, + "power": 1.52 + }, + { + "rally": 43, + "level_index": 0, + "power": 1.53 + }, + { + "rally": 44, + "level_index": 0, + "power": 1.53 + }, + { + "rally": 45, + "level_index": 0, + "power": 1.54 + }, + { + "rally": 46, + "level_index": 0, + "power": 1.55 + }, + { + "rally": 47, + "level_index": 0, + "power": 1.56 + }, + { + "rally": 48, + "level_index": 0, + "power": 1.57 + }, + { + "rally": 49, + "level_index": 0, + "power": 1.58 + }, + { + "rally": 50, + "level_index": 0, + "power": 1.58 + }, + { + "rally": 51, + "level_index": 0, + "power": 1.59 + }, + { + "rally": 52, + "level_index": 0, + "power": 1.6 + }, + { + "rally": 53, + "level_index": 0, + "power": 1.61 + }, + { + "rally": 54, + "level_index": 0, + "power": 1.62 + }, + { + "rally": 55, + "level_index": 0, + "power": 1.63 + }, + { + "rally": 56, + "level_index": 0, + "power": 1.63 + }, + { + "rally": 57, + "level_index": 0, + "power": 1.64 + }, + { + "rally": 58, + "level_index": 0, + "power": 1.65 + }, + { + "rally": 59, + "level_index": 0, + "power": 1.66 + }, + { + "rally": 60, + "level_index": 0, + "power": 1.67 + }, + { + "rally": 61, + "level_index": 0, + "power": 1.68 + }, + { + "rally": 62, + "level_index": 0, + "power": 1.68 + }, + { + "rally": 63, + "level_index": 0, + "power": 1.69 + }, + { + "rally": 64, + "level_index": 0, + "power": 1.7 + }, + { + "rally": 65, + "level_index": 0, + "power": 1.71 + }, + { + "rally": 66, + "level_index": 0, + "power": 1.72 + }, + { + "rally": 67, + "level_index": 0, + "power": 1.73 + }, + { + "rally": 68, + "level_index": 0, + "power": 1.73 + }, + { + "rally": 69, + "level_index": 0, + "power": 1.74 + }, + { + "rally": 70, + "level_index": 0, + "power": 1.75 + }, + { + "rally": 71, + "level_index": 0, + "power": 1.76 + }, + { + "rally": 72, + "level_index": 0, + "power": 1.77 + }, + { + "rally": 73, + "level_index": 0, + "power": 1.78 + }, + { + "rally": 74, + "level_index": 0, + "power": 1.78 + }, + { + "rally": 75, + "level_index": 0, + "power": 1.79 + }, + { + "rally": 76, + "level_index": 0, + "power": 1.8 + }, + { + "rally": 77, + "level_index": 0, + "power": 1.81 + }, + { + "rally": 78, + "level_index": 0, + "power": 1.82 + }, + { + "rally": 79, + "level_index": 0, + "power": 1.83 + }, + { + "rally": 80, + "level_index": 0, + "power": 1.83 + }, + { + "rally": 81, + "level_index": 0, + "power": 1.84 + }, + { + "rally": 82, + "level_index": 0, + "power": 1.85 + }, + { + "rally": 83, + "level_index": 0, + "power": 1.86 + }, + { + "rally": 84, + "level_index": 0, + "power": 1.87 + }, + { + "rally": 85, + "level_index": 0, + "power": 1.88 + }, + { + "rally": 86, + "level_index": 0, + "power": 1.88 + }, + { + "rally": 87, + "level_index": 0, + "power": 1.89 + }, + { + "rally": 88, + "level_index": 0, + "power": 1.9 + }, + { + "rally": 89, + "level_index": 0, + "power": 1.91 + }, + { + "rally": 90, + "level_index": 0, + "power": 1.92 + }, + { + "rally": 91, + "level_index": 0, + "power": 1.93 + }, + { + "rally": 92, + "level_index": 0, + "power": 1.93 + }, + { + "rally": 93, + "level_index": 0, + "power": 1.94 + }, + { + "rally": 94, + "level_index": 0, + "power": 1.95 + }, + { + "rally": 95, + "level_index": 0, + "power": 1.96 + }, + { + "rally": 96, + "level_index": 0, + "power": 1.97 + }, + { + "rally": 97, + "level_index": 0, + "power": 1.98 + }, + { + "rally": 98, + "level_index": 0, + "power": 1.98 + }, + { + "rally": 99, + "level_index": 0, + "power": 1.99 + }, + { + "rally": 100, + "level_index": 0, + "power": 2 + } + ] +} \ No newline at end of file diff --git a/tools/workbench/LibWorkBenchTests/Integrity/Details/IntegrityTestImpl.cs b/tools/workbench/LibWorkBenchTests/Integrity/Details/IntegrityTestImpl.cs new file mode 100644 index 0000000..6c7b932 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Integrity/Details/IntegrityTestImpl.cs @@ -0,0 +1,115 @@ +using LibWorkBench.Core.Models.Details; +using LibWorkBench.IO.Streams; + +namespace LibWorkBenchTests.Integrity.Details +{ + /// + /// Base class for integrity tests + /// + /// Resource class type + /// Test file class type + public abstract class IntegrityTestImpl + where TResource : ResourceImpl, new() + where TTestFile : TestFile + { + /// + /// Performs any logic necessary before running the current test + /// + /// WorkBench resource + /// Test case file + public virtual void BeforeTest(TResource resource, TTestFile file) + { + } + + /// + /// Performs any logic necessary after running the current test + /// + /// WorkBench resource + /// Test case file + public virtual void AfterTest(TResource resource, TTestFile file) + { + } + + /// + /// Runs through the provided list of test case files + /// + /// Test case files + public void Run(List files) + { + foreach (var it in files) + { + TTestFile test = (TTestFile)it; + + // Test artifact paths + string binaryPath = $"{it.Path}.testbin"; + string jsonPath = $"{it.Path}.testjson"; + + // Encoding test (JSON -> binary) + { + TResource resource = new(); + BeforeTest(resource, test); + + // JSON decode + using (JsonFileReader reader = new(it.Path)) + { + resource.Load(reader); + } + + // Binary encode + using (BinaryFileWriter writer = new(binaryPath, it.Endian)) + { + resource.Write(writer); + } + + Assert.AreEqual( + it.Hash, + IntegrityUtil.GetSha256Hash(binaryPath), + ignoreCase: true, + message: $"Binary encoding is wrong: {it.Path}" + ); + + AfterTest(resource, test); + } + + // Decoding test (binary -> JSON -> binary) + { + TResource resource = new(); + BeforeTest(resource, test); + + // Binary decode + using (BinaryFileReader reader = new(binaryPath, it.Endian)) + { + resource.Read(reader); + } + + // JSON encode + using (JsonFileWriter writer = new(jsonPath)) + { + resource.Dump(writer); + } + + // JSON decode + using (JsonFileReader reader = new(jsonPath)) + { + resource.Load(reader); + } + + // Binary encode + using (BinaryFileWriter writer = new(binaryPath, it.Endian)) + { + resource.Write(writer); + } + + Assert.AreEqual( + it.Hash, + IntegrityUtil.GetSha256Hash(binaryPath), + ignoreCase: true, + message: $"Binary encoding is wrong: {it.Path}" + ); + + AfterTest(resource, test); + } + } + } + } +} diff --git a/tools/workbench/LibWorkBenchTests/Integrity/IntegrityUtil.cs b/tools/workbench/LibWorkBenchTests/Integrity/IntegrityUtil.cs new file mode 100644 index 0000000..0a949ef --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Integrity/IntegrityUtil.cs @@ -0,0 +1,30 @@ +using System.Security.Cryptography; +using System.Text; + +namespace LibWorkBenchTests.Integrity +{ + /// + /// Integrity test utilities + /// + internal static class IntegrityUtil + { + /// + /// Computes the SHA-256 hash of the specified file + /// + /// File path + /// SHA-256 hash hex digest + public static string GetSha256Hash(string path) + { + SHA256 sha = SHA256.Create(); + byte[] digest = sha.ComputeHash(File.ReadAllBytes(path)); + + StringBuilder builder = new(); + foreach (var it in digest) + { + builder.Append(it.ToString("x2")); + } + + return builder.ToString(); + } + } +} diff --git a/tools/workbench/LibWorkBenchTests/Integrity/JSystem/JMessage/MsgResIntegrityTest.cs b/tools/workbench/LibWorkBenchTests/Integrity/JSystem/JMessage/MsgResIntegrityTest.cs new file mode 100644 index 0000000..f274ecc --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Integrity/JSystem/JMessage/MsgResIntegrityTest.cs @@ -0,0 +1,93 @@ +using LibWorkBench.API.JSystem.JMessage; +using LibWorkBench.API.Pack; +using LibWorkBench.Formats.JSystem.JMessage.Tag; +using LibWorkBench.Utility; +using LibWorkBenchTests.Integrity.Details; + +namespace LibWorkBenchTests.Integrity.JSystem.JMessage +{ + /// + /// File for use in a MsgRes integrity test + /// + public class MsgResTestFile : TestFile + { + /// + /// Message tag processor + /// + public TagProcessorBase TagProcessor { get; init; } + + /// + /// Constructor + /// + /// Path to the JSON file + /// Endianness in which to save the binary file + /// Expected SHA-256 hash of the binary file + /// Message tag processor + public MsgResTestFile(string path, EndianUtil.Type endian, string hash, + TagProcessorBase tagProcessor) + : base(path, endian, hash) + { + TagProcessor = tagProcessor; + } + } + + /// + /// MsgRes resource integrity test + /// + [TestClass] + public sealed class MsgResIntegrityTest : IntegrityTestImpl + { + /// + /// Test case files + /// + private static readonly List TEST_FILES = [ + // Pack Project common messages + new MsgResTestFile( + path: "Data/JSystem/JMessage/MsgRes/common_message.json", + endian: EndianUtil.Type.Big, + hash: "6a4e4873d0c4bd5964fd0f284cfa8bdfb1673b892c1b812b2e1485cee7c9a32c", + tagProcessor: new RPSysTagProcessor() + ), + + // Wii Sports messages + new MsgResTestFile( + path: "Data/JSystem/JMessage/MsgRes/sports_message.json", + endian: EndianUtil.Type.Big, + hash: "8b96a50108e624318be6f48b2214e1b237ce0e3c52825e7f1014d7459ce6597b", + tagProcessor: new RPSysTagProcessor() + ), + + // Wii Play messages + new MsgResTestFile( + path: "Data/JSystem/JMessage/MsgRes/party_message.json", + endian: EndianUtil.Type.Big, + hash: "6d56cc3685e793ee7b24ac9240b1926ef83e36938bd050081c2da0b5e0a87b46", + tagProcessor: new RPSysTagProcessor() + ), + + // Wii Sports Resort messages + new MsgResTestFile( + path: "Data/JSystem/JMessage/MsgRes/Sports2.json", + endian: EndianUtil.Type.Big, + hash: "74431582ab8e45d665700dd3925a8775ad1f83533d20deaccea252c0a0299930", + tagProcessor: new WS2TagProcessor() + ), + ]; + + /// + /// Performs any logic necessary before running the current test + /// + /// WorkBench resource + /// Test case file + public override void BeforeTest(MsgResFile resource, MsgResTestFile file) + { + resource.TagProcessor = file.TagProcessor; + } + + [TestMethod] + public void TestMethod() + { + Run(TEST_FILES); + } + } +} diff --git a/tools/workbench/LibWorkBenchTests/Integrity/NW4R/LayoutLib/LayoutIntegrityTest.cs b/tools/workbench/LibWorkBenchTests/Integrity/NW4R/LayoutLib/LayoutIntegrityTest.cs new file mode 100644 index 0000000..5feca56 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Integrity/NW4R/LayoutLib/LayoutIntegrityTest.cs @@ -0,0 +1,38 @@ +using LibWorkBench.API.NW4R.LayoutLib; +using LibWorkBench.Utility; +using LibWorkBenchTests.Integrity.Details; + +namespace LibWorkBenchTests.Integrity.NW4R.LayoutLib +{ + /// + /// Layout resource integrity test + /// + [TestClass] + public sealed class LayoutIntegrityTest : IntegrityTestImpl + { + /// + /// Test case files + /// + private static readonly List TEST_FILES = [ + // Version 8 layout (Wii Sports) + new TestFile( + path: "Data/NW4R/LayoutLib/Layout/golf_00.json", + endian: EndianUtil.Type.Big, + hash: "53bfd5b4cf8099edf2341f4b57e572481798faa1e64589685e2cc21dee79b0fa" + ), + + // Version 10 layout (Wii Sports Resort) + new TestFile( + path: "Data/NW4R/LayoutLib/Layout/60200_general_opening_score.json", + endian: EndianUtil.Type.Big, + hash: "5038f83465421e7265d758c64849c6204af875d6d705eacd448abcf8422e5f0e" + ), + ]; + + [TestMethod] + public void TestMethod() + { + Run(TEST_FILES); + } + } +} diff --git a/tools/workbench/LibWorkBenchTests/Integrity/Pack/Party/Pnp/LevelTableIntegrityTest.cs b/tools/workbench/LibWorkBenchTests/Integrity/Pack/Party/Pnp/LevelTableIntegrityTest.cs new file mode 100644 index 0000000..f3cfae1 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Integrity/Pack/Party/Pnp/LevelTableIntegrityTest.cs @@ -0,0 +1,30 @@ +using LibWorkBench.API.Pack.Party.Pnp; +using LibWorkBench.Utility; +using LibWorkBenchTests.Integrity.Details; + +namespace LibWorkBenchTests.Integrity.Pack.Party.Pnp +{ + /// + /// Table Tennis level table resource integrity test + /// + [TestClass] + public sealed class LevelTableIntegrityTest : IntegrityTestImpl + { + /// + /// Test case files + /// + private static readonly List TEST_FILES = [ + new TestFile( + path: "Data/Pack/Party/Pnp/LevelTable/leveltable.json", + endian: EndianUtil.Type.Big, + hash: "40b79c6031397d7316f794064d1aec48187f9abc668ad44910b45f684d316b58" + ), + ]; + + [TestMethod] + public void TestMethod() + { + Run(TEST_FILES); + } + } +} diff --git a/tools/workbench/LibWorkBenchTests/Integrity/Pack/Party/Pnp/RallyLevelUpTableIntegrityTest.cs b/tools/workbench/LibWorkBenchTests/Integrity/Pack/Party/Pnp/RallyLevelUpTableIntegrityTest.cs new file mode 100644 index 0000000..a8dbdc4 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Integrity/Pack/Party/Pnp/RallyLevelUpTableIntegrityTest.cs @@ -0,0 +1,36 @@ +using LibWorkBench.API.Pack.Party.Pnp; +using LibWorkBench.Utility; +using LibWorkBenchTests.Integrity.Details; + +namespace LibWorkBenchTests.Integrity.Pack.Party.Pnp +{ + /// + /// Table Tennis rally level-up table resource integrity test + /// + [TestClass] + public sealed class RallyLevelUpTableIntegrityTest : IntegrityTestImpl + { + /// + /// Test case files + /// + private static readonly List TEST_FILES = [ + new TestFile( + path: "Data/Pack/Party/Pnp/RallyLevelUpTable/rallyleveluptable.json", + endian: EndianUtil.Type.Big, + hash: "76fe4ad9cf2478aa169e6ab411ec14520a1f6d16a06a1033d7e9817e12698d40" + ), + + new TestFile( + path: "Data/Pack/Party/Pnp/RallyLevelUpTable/rallyleveluptable2.json", + endian: EndianUtil.Type.Big, + hash: "5ba3c4d8fcc211606713b8bb77497fdd5cf8a979b96ac09c0ad406b3bee24103" + ), + ]; + + [TestMethod] + public void TestMethod() + { + Run(TEST_FILES); + } + } +} diff --git a/tools/workbench/LibWorkBenchTests/Integrity/TestFile.cs b/tools/workbench/LibWorkBenchTests/Integrity/TestFile.cs new file mode 100644 index 0000000..512daf4 --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/Integrity/TestFile.cs @@ -0,0 +1,38 @@ +using LibWorkBench.Utility; + +namespace LibWorkBenchTests.Integrity +{ + /// + /// File for use in an integrity test + /// + public class TestFile + { + /// + /// Path to the JSON file + /// + public string Path { get; init; } = ""; + + /// + /// Endianness in which to save the binary file + /// + public EndianUtil.Type Endian { get; set; } = EndianUtil.Type.Big; + + /// + /// Expected SHA-256 hash of the binary file + /// + public string Hash { get; init; } = ""; + + /// + /// Constructor + /// + /// Path to the JSON file + /// Endianness in which to save the binary file + /// Expected SHA-256 hash of the binary file + public TestFile(string path, EndianUtil.Type endian, string hash) + { + Path = path; + Endian = endian; + Hash = hash; + } + } +} diff --git a/tools/workbench/LibWorkBenchTests/LibWorkBenchTests.csproj b/tools/workbench/LibWorkBenchTests/LibWorkBenchTests.csproj new file mode 100644 index 0000000..0917b7c --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/LibWorkBenchTests.csproj @@ -0,0 +1,78 @@ + + + + net9.0 + latest + enable + enable + true + Exe + true + + true + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/workbench/LibWorkBenchTests/MSTestSettings.cs b/tools/workbench/LibWorkBenchTests/MSTestSettings.cs new file mode 100644 index 0000000..aaf278c --- /dev/null +++ b/tools/workbench/LibWorkBenchTests/MSTestSettings.cs @@ -0,0 +1 @@ +[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] diff --git a/tools/workbench/WorkBench.sln b/tools/workbench/WorkBench.sln new file mode 100644 index 0000000..0937a24 --- /dev/null +++ b/tools/workbench/WorkBench.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36623.8 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkBench", "WorkBench\WorkBench.csproj", "{FEE54CE6-0CB7-496F-B4A7-1AA545730AF8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibWorkBench", "LibWorkBench\LibWorkBench.csproj", "{7FDD1ED0-CBE2-4543-8C91-24C05F31E31B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibWorkBenchTests", "LibWorkBenchTests\LibWorkBenchTests.csproj", "{5B47322A-730F-44CE-8D42-616E5AB2E827}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FEE54CE6-0CB7-496F-B4A7-1AA545730AF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FEE54CE6-0CB7-496F-B4A7-1AA545730AF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEE54CE6-0CB7-496F-B4A7-1AA545730AF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FEE54CE6-0CB7-496F-B4A7-1AA545730AF8}.Release|Any CPU.Build.0 = Release|Any CPU + {7FDD1ED0-CBE2-4543-8C91-24C05F31E31B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7FDD1ED0-CBE2-4543-8C91-24C05F31E31B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7FDD1ED0-CBE2-4543-8C91-24C05F31E31B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7FDD1ED0-CBE2-4543-8C91-24C05F31E31B}.Release|Any CPU.Build.0 = Release|Any CPU + {5B47322A-730F-44CE-8D42-616E5AB2E827}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B47322A-730F-44CE-8D42-616E5AB2E827}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B47322A-730F-44CE-8D42-616E5AB2E827}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B47322A-730F-44CE-8D42-616E5AB2E827}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {07E26E36-BB23-492D-BAB6-28B3E87E78E5} + EndGlobalSection +EndGlobal diff --git a/tools/workbench/WorkBench/Program.cs b/tools/workbench/WorkBench/Program.cs new file mode 100644 index 0000000..0332597 --- /dev/null +++ b/tools/workbench/WorkBench/Program.cs @@ -0,0 +1,38 @@ +using LibWorkBench.API.Pack.Common; +using LibWorkBench.IO.Streams; +using LibWorkBench.Utility; + +namespace WorkBench +{ + public class Program + { + static void Main(string[] args) + { + MapDataFile res = new(); + + using (BinaryFileReader f = new("D:/Downloads/mapdata/cow_field1P.pmp", + EndianUtil.Type.Big)) + { + res.Read(f); + } + + using (JsonFileWriter f = new("D:/Downloads/pnprally/cow_field1P.json")) + { + res.Dump(f); + } + + //res = new(); + + //using (JsonFileReader f = new("D:/Downloads/lyt/dummy.json")) + //{ + // res.Load(f); + //} + + //using (BinaryFileWriter f = new("D:/Downloads/lyt/dummy.brlyt", + // EndianUtil.Type.Big)) + //{ + // res.Write(f); + //} + } + } +} diff --git a/tools/workbench/WorkBench/WorkBench.csproj b/tools/workbench/WorkBench/WorkBench.csproj new file mode 100644 index 0000000..188860e --- /dev/null +++ b/tools/workbench/WorkBench/WorkBench.csproj @@ -0,0 +1,14 @@ + + + + Exe + net9.0 + enable + enable + + + + + + +