diff --git a/Codes.xml b/Codes.xml index 25277ec..1a4c296 100644 --- a/Codes.xml +++ b/Codes.xml @@ -1244,12 +1244,9 @@ Quarterframe Timer QFタイマー Noki Doki, sup39(サポミク) - 1.4 - Dec 16, 2022 - drawText - drawText - drawText - drawText + 1.5 + Jan 28, 2023 + drawText Adds an in-game timer to every level, starting on the last black frame of the loading screen and ending as soon as the 'Shine Get' animation starts @@ -1267,8 +1264,8 @@ 41820010 B00700B2 3800FFFC 900700B4 60000000 00000000 - C2206738 0000001F - 3C60817F 6064011C + C22069E0 0000001B + 3C60817F 60640120 38630094 3D808020 398C1EA8 7D8803A6 4E800021 3C60817F @@ -1284,20 +1281,16 @@ 40A00010 7CE83B78 98E300B2 90E300B4 1D0803E9 38000078 - 7D080396 9421FFF0 - 380003E8 7CE80396 - 7C0701D6 7D004050 - 91010008 3800003C - 7D270396 7C0901D6 - 7D403850 80E30118 - 390300A4 80C30114 - 3D80817F 80A30110 - 618C0238 808300A0 - 7D8803A6 80630094 - 4E800021 38210010 - 38610E90 3D808003 - 398C5228 7D8803A6 - 4E800021 881F0046 + 7D080396 380003E8 + 7D280396 7C0901D6 + 7CE04050 3800003C + 7CA90396 7C0501D6 + 7CC04850 3D80817F + 618C0238 7D8803A6 + 388300A4 38630110 + 4E800021 38610E90 + 3D808003 398C5228 + 7D8803A6 4E800021 60000000 00000000 C20EFA30 00000005 3CA0817F A00500B2 @@ -1344,8 +1337,8 @@ 41820010 B00700B2 3800FFFC 900700B4 60000000 00000000 - C2143F18 0000001F - 3C60817F 6064011C + C21441C0 0000001B + 3C60817F 60640120 38630094 3D808014 398C0390 7D8803A6 4E800021 3C60817F @@ -1361,20 +1354,16 @@ 40A00010 7CE83B78 98E300B2 90E300B4 1D0803E9 38000078 - 7D080396 9421FFF0 - 380003E8 7CE80396 - 7C0701D6 7D004050 - 91010008 3800003C - 7D270396 7C0901D6 - 7D403850 80E30118 - 390300A4 80C30114 - 3D80817F 80A30110 - 618C0238 808300A0 - 7D8803A6 80630094 - 4E800021 38210010 - 38610BD0 3D80802F - 398CB6BC 7D8803A6 - 4E800021 881F0046 + 7D080396 380003E8 + 7D280396 7C0901D6 + 7CE04050 3800003C + 7CA90396 7C0501D6 + 7CC04850 3D80817F + 618C0238 7D8803A6 + 388300A4 38630110 + 4E800021 38610BD0 + 3D80802F 398CB6BC + 7D8803A6 4E800021 60000000 00000000 C229C520 00000005 3CA0817F A00500B2 @@ -1421,8 +1410,8 @@ 41820010 B00700B2 3800FFFC 900700B4 60000000 00000000 - C2138B54 0000001F - 3C60817F 6064011C + C2138DFC 0000001B + 3C60817F 60640120 38630094 3D808013 398C4F0C 7D8803A6 4E800021 3C60817F @@ -1438,20 +1427,16 @@ 40A00010 7CE83B78 98E300B2 90E300B4 1D0803E9 38000078 - 7D080396 9421FFF0 - 380003E8 7CE80396 - 7C0701D6 7D004050 - 91010008 3800003C - 7D270396 7C0901D6 - 7D403850 80E30118 - 390300A4 80C30114 - 3D80817F 80A30110 - 618C0238 808300A0 - 7D8803A6 80630094 - 4E800021 38210010 - 38610BE4 3D80802E - 398C3864 7D8803A6 - 4E800021 881F0046 + 7D080396 380003E8 + 7D280396 7C0901D6 + 7CE04050 3800003C + 7CA90396 7C0501D6 + 7CC04850 3D80817F + 618C0238 7D8803A6 + 388300A4 38630110 + 4E800021 38610BE4 + 3D80802E 398C3864 + 7D8803A6 4E800021 60000000 00000000 C22943FC 00000005 3CA0817F A00500B2 @@ -1498,8 +1483,8 @@ 41820010 B00700B2 3800FFFC 900700B4 60000000 00000000 - C21252A4 0000001F - 3C60817F 6064011C + C212554C 0000001B + 3C60817F 60640120 38630094 3D808012 398C1660 7D8803A6 4E800021 3C60817F @@ -1515,20 +1500,16 @@ 40A00010 7CE83B78 98E300B2 90E300B4 1D0803E9 38000078 - 7D080396 9421FFF0 - 380003E8 7CE80396 - 7C0701D6 7D004050 - 91010008 3800003C - 7D270396 7C0901D6 - 7D403850 80E30118 - 390300A4 80C30114 - 3D80817F 80A30110 - 618C0238 808300A0 - 7D8803A6 80630094 - 4E800021 38210010 - 38610BEC 3D80802D - 398CAECC 7D8803A6 - 4E800021 881F0046 + 7D080396 380003E8 + 7D280396 7C0901D6 + 7CE04050 3800003C + 7CA90396 7C0501D6 + 7CC04850 3D80817F + 618C0238 7D8803A6 + 388300A4 38630110 + 4E800021 38610BEC + 3D80802D 398CAECC + 7D8803A6 4E800021 60000000 00000000 C227C214 00000005 3CA0817F A00500B2 @@ -1576,8 +1557,8 @@ Sélecteur de niveau レベルセレクト Psychonauter, Dan Salvato, Noki Doki - 1.15 - Jul 5, 2021 + 1.16 + Jul 9, 2023 Allows warping to other levels when starting a file or when exiting a level by holding the combination until the screen turns black. @@ -1694,12 +1675,12 @@ 48000134 2C060002 4082000C 39000105 48000124 2C060006 - 4082000C 39000107 + 4082000C 39000106 48000114 2C060004 - 4082000C 39000108 + 4082000C 39000107 48000104 2C060005 - 4082000C 39000109 - 480000F4 39000102 + 4082000C 39000108 + 480000F4 39000109 480000EC 2C070040 40820010 39001400 39202E00 480000C4 @@ -1822,12 +1803,12 @@ 48000134 2C060002 4082000C 39000105 48000124 2C060006 - 4082000C 39000107 + 4082000C 39000106 48000114 2C060004 - 4082000C 39000108 + 4082000C 39000107 48000104 2C060005 - 4082000C 39000109 - 480000F4 39000102 + 4082000C 39000108 + 480000F4 39000109 480000EC 2C070040 40820010 39001400 39202E00 480000C4 @@ -1950,12 +1931,12 @@ 48000134 2C060002 4082000C 39000105 48000124 2C060006 - 4082000C 39000107 + 4082000C 39000106 48000114 2C060004 - 4082000C 39000108 + 4082000C 39000107 48000104 2C060005 - 4082000C 39000109 - 480000F4 39000102 + 4082000C 39000108 + 480000F4 39000109 480000EC 2C070040 40820010 39001400 39202E00 480000C4 @@ -2078,12 +2059,12 @@ 48000134 2C060002 4082000C 39000105 48000124 2C060006 - 4082000C 39000107 + 4082000C 39000106 48000114 2C060004 - 4082000C 39000108 + 4082000C 39000107 48000104 2C060005 - 4082000C 39000109 - 480000F4 39000102 + 4082000C 39000108 + 480000F4 39000109 480000EC 2C070040 40820010 39001400 39202E00 480000C4 @@ -2800,447 +2781,18 @@ 60000000 00000000 - - metadata - PASDisplay - Position/angle/speed display - Position/Winkel/Geschw. Display - Affichage de position/angle/vitesse - 位置/角度/速度表示 - Noki Doki, sup39(サポミク) - 1.4 - Mar 24, 2022 - drawText - drawText - - Shows Mario's position, angle and speed at any given time. - - ::: warning - This code is not compatible with the Speed Display code. - ::: - - - Zeigt Mario's Position, Winkel und Geschwindigkeit jederzeit auf dem Bildschirm an. - - ::: warning - Dieser Code ist nicht kompatibel mit dem Geschwindigkeits-Display Code - ::: - - Affiche la position, l'angle et la vitesse de Mario à tout moment. - 常に「マリオの位置」「マリオの角度」「マリオの速度」を表示します。 - - 062A6160 00000010 - 49553F19 60000000 - 60000000 60000000 - 042998B8 49560749 - 04143F14 496B6209 - 077FA000 000001E8 - 9421FFE0 7C0802A6 - 90010024 93E1001C - 4AABD6E5 38E00200 - 38C00320 38A0FFD8 - 3880000A 38610008 - 4AAD01B9 814D9FC8 - 3FE08180 3BFFA1EC - 39200000 39000002 - 3CE08180 38E7A164 - 80CA0048 38A10008 - 38800000 7FE3FB78 - 4AAD67F1 39200001 - 913F01B0 80010024 - 7C0803A6 83E1001C - 38210020 4E800020 - 9421FFE8 7C0802A6 - 9001001C 93A1000C - 93C10010 93E10014 - 7C7F1B78 81230000 - 83A90064 3D208180 - 8129A39C 2F890000 - 409E002C 7FE3FB78 - 7FA903A6 4E800421 - 8001001C 7C0803A6 - 83A1000C 83C10010 - 83E10014 38210018 - 4E800020 3D208040 - 6129E0E8 83C90000 - 3C608180 3863A1EC - 4AAD6B79 C0BE00A8 - C09E00B0 A0DE0096 - C07E0018 C05E0014 - C03E0010 3CA08180 - 38A5A164 38800080 - 4CC63242 4AB3F691 - 4BFFFF94 9421FFF0 - 7C0802A6 90010014 - 93E1000C 7C7F1B78 - 4AAF158D 38E00081 - 7FE6FB78 38A00000 - 38800000 3C608180 - 3863A1EC 4AAD5C5D - 80010014 7C0803A6 - 83E1000C 38210010 - 4E800020 5820506F - 7320252E 30660A59 - 20506F73 20252E30 - 660A5A20 506F7320 - 252E3066 0A416E67 - 6C652025 68750A48 - 20537064 20252E32 - 660A5620 53706420 - 252E3266 20202020 - 20202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202000 00000000 - C22A66F4 00000003 - 38600000 3D808180 - 906CA39C 807F0040 - 60000000 00000000 - - - 04206734 495F38CD - 077FA000 000000B5 - 9421FFF0 7C0802A6 - 90010014 93E1000C - 7C7F1B78 4A83B215 - 3D208041 8149A378 - 3D008180 38600010 - 3908A074 C0AA00A8 - 38E0FFFF C08A00B0 - 38C0FFFF A12A0096 - 38A00014 C06A0018 - 388000C8 C04A0014 - C02A0010 4CC63242 - 4BFF61E1 80010014 - 7FE3FB78 83E1000C - 7C0803A6 38210010 - 4A83B1B8 5820506F - 7320252E 30660A59 - 20506F73 20252E30 - 660A5A20 506F7320 - 252E3066 0A416E67 - 6C652025 68750A48 - 20537064 20252E32 - 660A5620 53706420 - 252E3266 00000000 - - - 041252A0 496D4D61 - 077FA000 000000B5 - 9421FFF0 7C0802A6 - 90010014 93E1000C - 7C7F1B78 4AAD0EB9 - 3D208040 8149EF88 - 3D008180 38600010 - 3908A074 C0AA00A8 - 38E0FFFF C08A00B0 - 38C0FFFF A12A0096 - 38A00014 C06A0018 - 388000C8 C04A0014 - C02A0010 4CC63242 - 4BFF61E1 80010014 - 7FE3FB78 83E1000C - 7C0803A6 38210010 - 4AAD0E5C 5820506F - 7320252E 30660A59 - 20506F73 20252E30 - 660A5A20 506F7320 - 252E3066 0A416E67 - 6C652025 68750A48 - 20537064 20252E32 - 660A5620 53706420 - 252E326600000000 - - - 0629E070 00000010 - 4955C009 60000000 - 60000000 60000000 - 04291750 495688B1 - 04138B50 496C15CD - 077FA000 000001E8 - 9421FFE0 7C0802A6 - 90010024 93E1001C - 4AAB56B5 38E00200 - 38C00320 38A0FFD8 - 3880000A 38610008 - 4AAC824D 814D9EF0 - 3FE08180 3BFFA1EC - 39200000 39000002 - 3CE08180 38E7A164 - 80CA0048 38A10008 - 38800000 7FE3FB78 - 4AACE999 39200001 - 913F01B0 80010024 - 7C0803A6 83E1001C - 38210020 4E800020 - 9421FFE8 7C0802A6 - 9001001C 93A1000C - 93C10010 93E10014 - 7C7F1B78 81230000 - 83A90064 3D208180 - 8129A39C 2F890000 - 409E002C 7FE3FB78 - 7FA903A6 4E800421 - 8001001C 7C0803A6 - 83A1000C 83C10010 - 83E10014 38210018 - 4E800020 3D208040 - 612957B0 83C90000 - 3C608180 3863A1EC - 4AACED21 C0BE00A8 - C09E00B0 A0DE0096 - C07E0018 C05E0014 - C03E0010 3CA08180 - 38A5A164 38800080 - 4CC63242 4AB37811 - 4BFFFF94 9421FFF0 - 7C0802A6 90010014 - 93E1000C 7C7F1B78 - 4AAE9735 38E00081 - 7FE6FB78 38A00000 - 38800000 3C608180 - 3863A1EC 4AACDE05 - 80010014 7C0803A6 - 83E1000C 38210010 - 4E800020 5820506F - 7320252E 30660A59 - 20506F73 20252E30 - 660A5A20 506F7320 - 252E3066 0A416E67 - 6C652025 68750A48 - 20537064 20252E32 - 660A5620 53706420 - 252E3266 20202020 - 20202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202000 00000000 - C229E64C 00000003 - 38600000 3D808180 - 906CA39C 807F0040 - 60000000 00000000 - - - - metadata - SpeedDisplay - Speed display - Geschwindigkeits-Display - Affichage de vitesse - 速度表示 - Noki Doki, sup39(サポミク) - 1.5 - Mar 24, 2022 - drawText - drawText - - Shows Mario's speed at any given time. - - ::: warning - This code is not compatible with the Position/Angle/Speed Display code. - ::: - - - Zeigt Mario's Geschwindigkeit jederzeit auf dem Bildschirm an. - - ::: warning - Dieser Code ist nicht kompatibel mit dem Position/Winkel/Gewschw. Display Code - ::: - - Affiche la vitesse de Mario à tout moment. - 常に「マリオの速度」を表示します。 - - 062A6160 00000010 - 49553F19 60000000 - 60000000 60000000 - 042998B8 49560749 - 04143F14 496B61F9 - 077FA000 00000188 - 9421FFE0 7C0802A6 - 90010024 93E1001C - 4AABD6E5 38E00200 - 38C00320 38A0FFD8 - 3880000A 38610008 - 4AAD01B9 814D9FC8 - 3FE08180 3BFFA214 - 39200000 39000002 - 3CE08180 38E7A154 - 80CA0048 38A10008 - 38800000 7FE3FB78 - 4AAD67F1 39200001 - 913F01B0 80010024 - 7C0803A6 83E1001C - 38210020 4E800020 - 9421FFE8 7C0802A6 - 9001001C 93C10010 - 93E10014 7C7F1B78 - 81230000 83C90064 - 3D208180 8129A3C4 - 2C090000 40820028 - 7FE3FB78 7FC903A6 - 4E800421 8001001C - 7C0803A6 83C10010 - 83E10014 38210018 - 4E800020 93A1000C - 3D208040 6129E0E8 - 83A90000 3C608180 - 3863A214 4AAD6B7D - C05D00A8 C03D00B0 - 3CA08180 38A5A154 - 38800030 4CC63242 - 4AB3F6A5 83A1000C - 4BFFFFA0 9421FFF0 - 7C0802A6 90010014 - 93E1000C 7C7F1B78 - 4AAF159D 38E00081 - 7FE6FB78 38A00000 - 38800000 3C608180 - 3863A214 4AAD5C6D - 80010014 7C0803A6 - 83E1000C 38210010 - 4E800020 48205370 - 6420252E 32660A56 - 20537064 20252E32 - 66202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202000 00000000 - C22A66F4 00000003 - 38600000 3D808180 - 906CA3C4 807F0040 - 60000000 00000000 - - - 04206734 495F38CD - 077FA000 0000007A - 9421FFF0 7C0802A6 - 90010014 93E1000C - 7C7F1B78 4A83B215 - 3D208041 8129A378 - 3D008180 38600010 - 3908A064 C04900A8 - 38E0FFFF C02900B0 - 38C0FFFF 38A00014 - 388000F0 4CC63242 - 4BFF61F1 80010014 - 7FE3FB78 83E1000C - 7C0803A6 38210010 - 4A83B1C8 48205370 - 6420252E 32660A56 - 20537064 20252E32 - 66000000 00000000 - - - 041252A0 496D4D61 - 077FA000 0000007A - 9421FFF0 7C0802A6 - 90010014 93E1000C - 7C7F1B78 4AAD0EB9 - 3D208040 8129EF88 - 3D008180 38600010 - 3908A064 C04900A8 - 38E0FFFF C02900B0 - 38C0FFFF 38A00014 - 388000F0 4CC63242 - 4BFF61F1 80010014 - 7FE3FB78 83E1000C - 7C0803A6 38210010 - 4AAD0E6C 48205370 - 6420252E 32660A56 - 20537064 20252E32 - 66000000 00000000 - - - 0629E070 00000010 - 4955C009 60000000 - 60000000 60000000 - 04291750 495688B1 - 04138B50 496C15BD - 077FA000 00000188 - 9421FFE0 7C0802A6 - 90010024 93E1001C - 4AAB56B5 38E00200 - 38C00320 38A0FFD8 - 3880000A 38610008 - 4AAC824D 814D9EF0 - 3FE08180 3BFFA214 - 39200000 39000002 - 3CE08180 38E7A154 - 80CA0048 38A10008 - 38800000 7FE3FB78 - 4AACE999 39200001 - 913F01B0 80010024 - 7C0803A6 83E1001C - 38210020 4E800020 - 9421FFE8 7C0802A6 - 9001001C 93C10010 - 93E10014 7C7F1B78 - 81230000 83C90064 - 3D208180 8129A3C4 - 2C090000 40820028 - 7FE3FB78 7FC903A6 - 4E800421 8001001C - 7C0803A6 83C10010 - 83E10014 38210018 - 4E800020 93A1000C - 3D208040 612957B0 - 83A90000 3C608180 - 3863A214 4AACED25 - C05D00A8 C03D00B0 - 3CA08180 38A5A154 - 38800030 4CC63242 - 4AB37825 83A1000C - 4BFFFFA0 9421FFF0 - 7C0802A6 90010014 - 93E1000C 7C7F1B78 - 4AAE9745 38E00081 - 7FE6FB78 38A00000 - 38800000 3C608180 - 3863A214 4AACDE15 - 80010014 7C0803A6 - 83E1000C 38210010 - 4E800020 48205370 - 6420252E 32660A56 - 20537064 20252E32 - 66202020 20202020 - 20202020 20202020 - 20202020 20202020 - 20202000 00000000 - C229E64C 00000003 - 38600000 3D808180 - 906CA3C4 807F0040 - 60000000 00000000 - - metadata CustomizedDisplay - Customized display + Customized Display カスタマイズ表示 sup39(サポミク) - 0.3 - Oct 30, 2022 + 0.4 + Jan 31, 2023 drawText Shows metadata at any given time. - ::: warning - This code is not compatible with other Display codes. - ::: - - ::: warning - The preview is based on NTSC-J's font data, and may be inaccurate for NTSC-U and PAL. - In addition, some characters may not shown properly. - ::: - #### Format Use `< ID-of-the-data | format | value-shown-in-preview >` to display a metadata. @@ -3255,12 +2807,23 @@ |`VSpd`|Vertical speed of Mario|float| |`QF`|QF offset|\{0,1,2,3}| |`CAngle`|Camera Angle|uint16| + |`invinc`|Invincibility Timer (frame)|int16| + |`goop`|Pollution Degree (<600 to complete SB6)|int32| + |`spin`|Whether satisfying spin jump condition|Show 🅐 if YES| For float data, you can set the *format* to `.{digit}` to specify how many digits to show. %details[ - %summary[All printable characters (for NTSC-J)] - ![Printable charaters](/img/preview/font-jp.png){style="background:black"} + %summary[All printable characters (NTSC-J)] + ![Printable charaters](/img/preview/font-JP.png){style="background:black;padding:8px"} + ] + %details[ + %summary[All printable characters (NTSC-U)] + ![Printable charaters](/img/preview/font-US.png){style="background:black;padding:8px"} + ] + %details[ + %summary[All printable characters (PAL)] + ![Printable charaters](/img/preview/font-EU.png){style="background:black;padding:8px"} ] #### Preview @@ -3282,101 +2845,120 @@ |`VSpd`|マリオのY速度|float| |`QF`|ずれたQFの数|\{0,1,2,3}| |`CAngle`|カメラの角度|uint16| + |`invinc`|無敵時間(フレーム数)|int16| + |`goop`|汚れの量(600未満でSB6クリア)|int32| + |`spin`|スピン入力の判定|条件を満たせば🅐を表示| float(小数)型に対して、「表示のフォーマット」を`.{桁数}`に設定して何桁まで表示するか指定できます。 また、全てのひらがなとカタカナ及び一部の漢字の表示も可能です。 %details[ - %summary[表示可能な文字一覧:] - ![表示可能な文字一覧](/img/preview/font-jp.png){style="background:black"} + %summary[表示可能な文字一覧(初期版・後期版)] + ![表示可能な文字一覧(初期版・後期版)](/img/preview/font-JP.png){style="background:black;padding:8px"} + ] + %details[ + %summary[表示可能な文字一覧(北米版・韓国版)] + ![表示可能な文字一覧(北米版・韓国版)](/img/preview/font-US.png){style="background:black;padding:8px"} + ] + %details[ + %summary[表示可能な文字一覧(欧州版)] + ![表示可能な文字一覧(欧州版)](/img/preview/font-EU.png){style="background:black;padding:8px"} ] #### プレビュー - C62069D4 817FA000 - 077FA000 00000088 - 38610E90 4A83B225 - 806D98B8 C0230010 - C0430014 C0630018 - A1230096 C08300B0 - C0A300A8 806D97E8 - 81430058 554A07BE - 48000035 5820252E - 30660A59 20252E30 - 660A5A20 252E3066 - 0A412025 68750A48 - 20252E32 660A5620 - 252E3266 0A514620 - 25750000 7D0802A6 - 38600010 388000C0 - 38A00012 38C0FFFF - 7CC73378 4CC63242 - 4BFF61B9 4AA0C954 + C22069D4 00000014 + 9421FFF0 806D98B8 + C0230010 C0430014 + C0630018 A0A30096 + C08300B0 C0A300A8 + 48000015 001000C8 + 00000014 FFFFFFFF + FFFFFFFF 7C6802A6 + 48000049 5820506F + 7320252E 30660A59 + 20506F73 20252E30 + 660A5A20 506F7320 + 252E3066 0A416E67 + 6C652025 68750A48 + 20537064 20252E32 + 660A5620 53706420 + 252E3266 00000000 + 7C8802A6 3D80817F + 618C0238 7D8903A6 + 4E800421 38210010 + 60000000 00000000 - C61252A0 817FA000 - 077FA000 00000084 - 4AAD0ECD 806D9DE8 + C2125540 00000014 + 9421FFF0 806D9DE8 C0230010 C0430014 - C0630018 A1230096 + C0630018 A0A30096 C08300B0 C0A300A8 - 806D9E78 81430058 - 554A07BE 48000035 - 5820252E 30660A59 - 20252E30 660A5A20 - 252E3066 0A412025 - 68750A48 20252E32 - 660A5620 252E3266 - 0A514620 25750000 - 7D0802A6 38600010 - 388000C8 38A00012 - 38C0FFFF 7CC73378 - 4CC63242 4BFF61BD - 4A92B224 00000000 + 48000015 001000C8 + 00000014 FFFFFFFF + FFFFFFFF 7C6802A6 + 48000049 5820506F + 7320252E 30660A59 + 20506F73 20252E30 + 660A5A20 506F7320 + 252E3066 0A416E67 + 6C652025 68750A48 + 20537064 20252E32 + 660A5620 53706420 + 252E3266 00000000 + 7C8802A6 3D80817F + 618C0238 7D8903A6 + 4E800421 38210010 + 60000000 00000000 - C6143F14 817FA000 - 077FA000 00000084 - 4AAF16BD 806D9F28 + C21441B4 00000014 + 9421FFF0 806D9F28 C0230010 C0430014 - C0630018 A1230096 + C0630018 A0A30096 C08300B0 C0A300A8 - 806D9FB8 81430058 - 554A07BE 48000035 - 5820252E 30660A59 - 20252E30 660A5A20 - 252E3066 0A412025 - 68750A48 20252E32 - 660A5620 252E3266 - 0A514620 25750000 - 7D0802A6 38600010 - 388000C8 38A00012 - 38C0FFFF 7CC73378 - 4CC63242 4BFF61BD - 4A949E98 00000000 + 48000015 001000C8 + 00000014 FFFFFFFF + FFFFFFFF 7C6802A6 + 48000049 5820506F + 7320252E 30660A59 + 20506F73 20252E30 + 660A5A20 506F7320 + 252E3066 0A416E67 + 6C652025 68750A48 + 20537064 20252E32 + 660A5620 53706420 + 252E3266 00000000 + 7C8802A6 3D80817F + 618C0238 7D8903A6 + 4E800421 38210010 + 60000000 00000000 - C6138B50 817FA000 - 077FA000 00000084 - 4AAE9865 806D9E50 + C2138DF0 00000014 + 9421FFF0 806D9E50 C0230010 C0430014 - C0630018 A1230096 + C0630018 A0A30096 C08300B0 C0A300A8 - 806D9EE0 81430058 - 554A07BE 48000035 - 5820252E 30660A59 - 20252E30 660A5A20 - 252E3066 0A412025 - 68750A48 20252E32 - 660A5620 252E3266 - 0A514620 25750000 - 7D0802A6 38600010 - 388000C8 38A00012 - 38C0FFFF 7CC73378 - 4CC63242 4BFF61BD - 4A93EAD4 00000000 + 48000015 001000C8 + 00000014 FFFFFFFF + FFFFFFFF 7C6802A6 + 48000049 5820506F + 7320252E 30660A59 + 20506F73 20252E30 + 660A5A20 506F7320 + 252E3066 0A416E67 + 6C652025 68750A48 + 20537064 20252E32 + 660A5620 53706420 + 252E3266 00000000 + 7C8802A6 3D80817F + 618C0238 7D8903A6 + 4E800421 38210010 + 60000000 00000000 @@ -3802,8 +3384,8 @@ Pattern Selector パターン選択 sup39(サポミク) - 0.3 - Oct 30, 2022 + 0.4 + Jan 31, 2023 drawText Ⓑ is the cursor to select the pattern, @@ -3884,122 +3466,196 @@ %object[]{data="/img/PatternSelector/PV1-3.svg"} - 0424F32C 495A9CD5 - 042069DC 495F26B8 - 077F9000 000001AF - 801F0000 3D00817F - 61089167 3D40817F - 614A0024 3D80803D - 618CA9C0 7C006040 - 41820048 3D80803D - 618C87C0 7C006040 - 40820034 819F0004 - 898C0013 508C442E - 39280031 88080007 - 7CEA00AE A0080005 - 7C006040 41820024 - 39080007 7C084840 - 4180FFE4 4AA671C0 - 2C05FFFF 4082FFF8 - 88EA0000 39080031 - 7CE73B79 4182FFE8 - 7C0838AE 280000FF - 4182FFDC 7C030378 - 4E800020 38610E90 - 4A83C191 3C808040 - A4040D82 3C60817F - 84A30024 70000040 - 41A20050 88840019 - 548007FE 7CA02850 - 5480FFFE 7CA50214 - 54A507BE 5480F7BF - 41A20030 28050003 - 41A00008 38A00000 - 5480EFFE 5080077A - 7D8328AE 7D8C0214 - 280C0005 41A00008 - 398CFFFB 7D8329AE - 98A30003 3821FFF0 - 3D00817F 6108919D - 3C002020 60002023 - 54AC183E 5C00603E - 98080008 540CC63E - 9988000B 540C863E - 9988000E 89230000 - 89430001 89630002 - 91610008 38600010 - 38800140 38A00014 - 38C0FFFF 38E0FFFF - 4CC63182 4BFF70DD - 38210010 4AA0D87C - 452020FF 213200FF - 621CFF1D 32005025 - 25252630 01FF4520 - 20213001 FFFF621C - 1D300151 0707FF08 - 3102FF36 01FF0231 - 021E6E20 FF506174 - 7465726E 203E2558 - 3E25583E 25580000 + C224F32C 00000013 + 801F0000 3D80817F + 61880440 618A0024 + 6C0C803D 280CA9C0 + 41820054 6C0C803D + 280C87C0 40820034 + 819F0004 898C0013 + 508C442E 39280031 + 88080007 7CEA00AE + A0080005 7C006040 + 41820034 39080007 + 7C084840 4180FFE4 + 3D808026 618C0224 + 7D8803A6 4E800021 + 4800002C 2C05FFFF + 4082FFE8 88EA0000 + 39080031 7CE73B79 + 4182FFD8 7C0838AE + 280000FF 4182FFCC + 7C030378 00000000 + C22069DC 00000019 + 3C60817F 60630410 + 38830010 3D808020 + 618C1EA8 7D8803A6 + 4E800021 3C808040 + A4040D82 3C60817F + 85630024 70000040 + 41A20050 88840019 + 548007FE 7D605850 + 5480FFFE 7D6B0214 + 556B07BE 5480F7BF + 41A20030 280B0003 + 41A00008 39600000 + 5480EFFE 5080077A + 7D8358AE 7D8C0214 + 280C0005 41A00008 + 398CFFFB 7D8359AE + 99630003 3C002020 + 60002023 556C183E + 5C00603E 5405063E + 5407C63E 5409863E + 88C30000 89030001 + 89430002 3D80817F + 61830424 61840434 + 618C0238 7D8803A6 + 4E800021 00000000 - 04027900 497D1701 - 04125548 496D3B4C - 077F9000 000001AF - 801F0000 3D00817F - 61089167 3D40817F - 614A0024 3D80803A - 618C6D70 7C006040 - 41820048 3D80803A - 618C4B80 7C006040 - 40820034 819F0004 - 898C0013 508C442E - 39280031 88080007 - 7CEA00AE A0080005 - 7C006040 41820024 - 39080007 7C084840 - 4180FFE4 4A83F620 - 2C05FFFF 4082FFF8 - 88EA0000 39080031 - 7CE73B79 4182FFE8 - 7C0838AE 280000FF - 4182FFDC 7C030378 - 4E800020 38610E90 - 4AAD1E35 3C80803F - A404545A 3C60817F - 84A30024 70000040 - 41A20050 88840019 - 548007FE 7CA02850 - 5480FFFE 7CA50214 - 54A507BE 5480F7BF - 41A20030 28050003 - 41A00008 38A00000 - 5480EFFE 5080077A - 7D8328AE 7D8C0214 - 280C0005 41A00008 - 398CFFFB 7D8329AE - 98A30003 3821FFF0 - 3D00817F 6108919D - 3C002020 60002023 - 54AC183E 5C00603E - 98080008 540CC63E - 9988000B 540C863E - 9988000E 89230000 - 89430001 89630002 - 91610008 38600010 - 38800140 38A00014 - 38C0FFFF 38E0FFFF - 4CC63182 4BFF70DD - 38210010 4A92C3E8 - 452020FF 213200FF - 621CFF1D 32005025 - 25252630 01FF4520 - 20213001 FFFF621C - 1D300151 0707FF08 - 3102FF36 01FF0231 - 021E6E20 FF506174 - 7465726E 203E2558 - 3E25583E 25580000 + C2027900 00000013 + 801F0000 3D80817F + 61880440 618A0024 + 6C0C803A 280C6D70 + 41820054 6C0C803A + 280C4B80 40820034 + 819F0004 898C0013 + 508C442E 39280031 + 88080007 7CEA00AE + A0080005 7C006040 + 41820034 39080007 + 7C084840 4180FFE4 + 3D808003 618C8684 + 7D8803A6 4E800021 + 4800002C 2C05FFFF + 4082FFE8 88EA0000 + 39080031 7CE73B79 + 4182FFD8 7C0838AE + 280000FF 4182FFCC + 7C030378 00000000 + C2125548 00000019 + 3C60817F 60630410 + 38830010 3D808012 + 618C1660 7D8803A6 + 4E800021 3C80803F + A404545A 3C60817F + 85630024 70000040 + 41A20050 88840019 + 548007FE 7D605850 + 5480FFFE 7D6B0214 + 556B07BE 5480F7BF + 41A20030 280B0003 + 41A00008 39600000 + 5480EFFE 5080077A + 7D8358AE 7D8C0214 + 280C0005 41A00008 + 398CFFFB 7D8359AE + 99630003 3C002020 + 60002023 556C183E + 5C00603E 5405063E + 5407C63E 5409863E + 88C30000 89030001 + 89430002 3D80817F + 61830424 61840434 + 618C0238 7D8803A6 + 4E800021 00000000 + + + C203B54C 00000013 + 801F0000 3D80817F + 61880440 618A0024 + 6C0C803A 280CDF98 + 41820054 6C0C803A + 280CBDA8 40820034 + 819F0004 898C0013 + 508C442E 39280031 + 88080007 7CEA00AE + A0080005 7C006040 + 41820034 39080007 + 7C084840 4180FFE4 + 3D808004 618CC228 + 7D8803A6 4E800021 + 4800002C 2C05FFFF + 4082FFE8 88EA0000 + 39080031 7CE73B79 + 4182FFD8 7C0838AE + 280000FF 4182FFCC + 7C030378 00000000 + C2138DF8 00000019 + 3C60817F 60630410 + 38830010 3D808013 + 618C4F0C 7D8803A6 + 4E800021 3C808040 + A404BC26 3C60817F + 85630024 70000040 + 41A20050 88840019 + 548007FE 7D605850 + 5480FFFE 7D6B0214 + 556B07BE 5480F7BF + 41A20030 280B0003 + 41A00008 39600000 + 5480EFFE 5080077A + 7D8358AE 7D8C0214 + 280C0005 41A00008 + 398CFFFB 7D8359AE + 99630003 3C002020 + 60002023 556C183E + 5C00603E 5405063E + 5407C63E 5409863E + 88C30000 89030001 + 89430002 3D80817F + 61830424 61840434 + 618C0238 7D8803A6 + 4E800021 00000000 + + + C203B6FC 00000013 + 801F0000 3D80817F + 61880440 618A0024 + 6C0C803B 280C6178 + 41820054 6C0C803B + 280C3F88 40820034 + 819F0004 898C0013 + 508C442E 39280031 + 88080007 7CEA00AE + A0080005 7C006040 + 41820034 39080007 + 7C084840 4180FFE4 + 3D808004 618CD0D4 + 7D8803A6 4E800021 + 4800002C 2C05FFFF + 4082FFE8 88EA0000 + 39080031 7CE73B79 + 4182FFD8 7C0838AE + 280000FF 4182FFCC + 7C030378 00000000 + C21441BC 00000019 + 3C60817F 60630410 + 38830010 3D808014 + 618C0390 7D8803A6 + 4E800021 3C808040 + A4044486 3C60817F + 85630024 70000040 + 41A20050 88840019 + 548007FE 7D605850 + 5480FFFE 7D6B0214 + 556B07BE 5480F7BF + 41A20030 280B0003 + 41A00008 39600000 + 5480EFFE 5080077A + 7D8358AE 7D8C0214 + 280C0005 41A00008 + 398CFFFB 7D8359AE + 99630003 3C002020 + 60002023 556C183E + 5C00603E 5405063E + 5407C63E 5409863E + 88C30000 89030001 + 89430002 3D80817F + 61830424 61840434 + 618C0238 7D8803A6 + 4E800021 00000000 @@ -4029,161 +3685,140 @@ lib drawText sup39(サポミク) - 0.2.0 - Mar 25, 2022 + 0.3 + Jan 02, 2023 - ```c - void drawText(int x, int y, int fontSize, uint32_t colorTop, uint32_t colorBot, const char *fmt, ...); - ``` + ```c + typedef struct { + int16_t x; + int16_t y; + uint32_t fontSize; + uint32_t colorTop; + uint32_t colorBot; + } DrawTextOpt; + void drawText(DrawTextOpt *opt, const char *fmt, ...); + ``` - 077F0238 00000110 - 9421FED8 7C0802A6 - BF810118 7C7F1B78 - 9001012C 7C9E2378 - 90C100B8 7CBD2B78 - 90E100BC 7D1C4378 - 912100C0 914100C4 - 40860024 D82100C8 - D84100D0 D86100D8 - D88100E0 D8A100E8 - D8C100F0 D8E100F8 - D9010100 39200600 - 390100BC B12100A0 - 39210130 912100A4 - 392100A8 912100A8 - 808D97F8 38E100B8 - 7FA6EB78 38A00000 - 38610008 6FDE8000 - 4A826AF5 3D204330 - 91210108 3D40817F - 93C1010C 6FFF8000 - C00A0344 38610070 - C9810108 91210110 - 3D20817F 93E10114 - FC4C0028 C0690340 - C9810110 93A10064 - FC2C0028 93A10060 - 4A8A43E9 38800000 - 38610070 4A8BD419 - 38C100A0 7F85E378 - 388000FF 38610008 - 4A826951 BB810118 - 38210128 80010004 - 7C0803A6 4E800020 - 00000000 59800004 - - - 077F0238 00000110 - 9421FED8 7C0802A6 - BF810118 7C7F1B78 - 9001012C 7C9E2378 - 90C100B8 7CBD2B78 - 90E100BC 7D1C4378 - 912100C0 914100C4 - 40860024 D82100C8 - D84100D0 D86100D8 - D88100E0 D8A100E8 - D8C100F0 D8E100F8 - D9010100 39200600 - 390100BC B12100A0 - 39210130 912100A4 - 392100A8 912100A8 - 808D9E88 38E100B8 - 7FA6EB78 38A00000 - 38610008 6FDE8000 - 4AABD249 3D204330 - 91210108 3D40817F - 93C1010C 6FFF8000 - C00A0344 38610070 - C9810108 91210110 - 3D20817F 93E10114 - FC4C0028 C0690340 - C9810110 93A10064 - FC2C0028 93A10060 - 4AB393C9 38800000 - 38610070 4AB523F9 - 38C100A0 7F85E378 - 388000FF 38610008 - 4AABD0A5 BB810118 - 38210128 80010004 - 7C0803A6 4E800020 - 00000000 59800004 - - - 077F0238 00000110 - 9421FED8 7C0802A6 - BF810118 7C7F1B78 - 9001012C 7C9E2378 - 90C100B8 7CBD2B78 - 90E100BC 7D1C4378 - 912100C0 914100C4 - 40860024 D82100C8 - D84100D0 D86100D8 - D88100E0 D8A100E8 - D8C100F0 D8E100F8 - D9010100 39200600 - 390100BC B12100A0 - 39210130 912100A4 - 392100A8 912100A8 - 808D9FC8 38E100B8 - 7FA6EB78 38A00000 - 38610008 6FDE8000 - 4AADDA39 3D204330 - 91210108 3D40817F - 93C1010C 6FFF8000 - C00A0344 38610070 - C9810108 91210110 - 3D20817F 93E10114 - FC4C0028 C0690340 - C9810110 93A10064 - FC2C0028 93A10060 - 4AB59AC9 38800000 - 38610070 4AB72AF9 - 38C100A0 7F85E378 - 388000FF 38610008 - 4AADD895 BB810118 - 38210128 80010004 - 7C0803A6 4E800020 - 00000000 59800004 - - - 077F0238 00000110 - 9421FED8 7C0802A6 - BF810118 7C7F1B78 - 9001012C 7C9E2378 - 90C100B8 7CBD2B78 - 90E100BC 7D1C4378 - 912100C0 914100C4 - 40860024 D82100C8 - D84100D0 D86100D8 - D88100E0 D8A100E8 - D8C100F0 D8E100F8 - D9010100 39200600 - 390100BC B12100A0 - 39210130 912100A4 - 392100A8 912100A8 - 808D9EF0 38E100B8 - 7FA6EB78 38A00000 - 38610008 6FDE8000 - 4AAD5ACD 3D204330 - 91210108 3D40817F - 93C1010C 6FFF8000 - C00A0344 38610070 - C9810108 91210110 - 3D20817F 93E10114 - FC4C0028 C0690340 - C9810110 93A10064 - FC2C0028 93A10060 - 4AB51D25 38800000 - 38610070 4AB6AD19 - 38C100A0 7F85E378 - 388000FF 38610008 - 4AAD5929 BB810118 - 38210128 80010004 - 7C0803A6 4E800020 - 00000000 59800004 - + 077F0238 000000D4 + 9421FF08 7C0802A6 + BFC100F0 7C7F1B78 + 900100FC 7C9E2378 + 90A10088 90C1008C + 90E10090 91010094 + 91210098 9141009C + D82100A0 D84100A8 + D86100B0 D88100B8 + D8A100C0 D8C100C8 + D8E100D0 D90100D8 + 39200200 80DF0004 + B1210070 39200000 + 39210100 91210074 + 39210080 91210078 + 808D97F8 391F000C + 38FF0008 38A00000 + 38610008 4A826AF9 + 813F0004 38610008 + 91210064 91210060 + A95F0000 388000FF + 91410024 7FC5F378 + E01F5000 38C10070 + F001002C 38000000 + 90010034 4A826985 + BBC100F0 382100F8 + 80010004 7C0803A6 + 4E800020 00000000 + + + 077F0238 000000D4 + 9421FF08 7C0802A6 + BFC100F0 7C7F1B78 + 900100FC 7C9E2378 + 90A10088 90C1008C + 90E10090 91010094 + 91210098 9141009C + D82100A0 D84100A8 + D86100B0 D88100B8 + D8A100C0 D8C100C8 + D8E100D0 D90100D8 + 39200200 80DF0004 + B1210070 39200000 + 39210100 91210074 + 39210080 91210078 + 808D9E88 391F000C + 38FF0008 38A00000 + 38610008 4AABD24D + 813F0004 38610008 + 91210064 91210060 + A95F0000 388000FF + 91410024 7FC5F378 + E01F5000 38C10070 + F001002C 38000000 + 90010034 4AABD0D9 + BBC100F0 382100F8 + 80010004 7C0803A6 + 4E800020 00000000 + + + 077F0238 000000D4 + 9421FF08 7C0802A6 + BFC100F0 7C7F1B78 + 900100FC 7C9E2378 + 90A10088 90C1008C + 90E10090 91010094 + 91210098 9141009C + D82100A0 D84100A8 + D86100B0 D88100B8 + D8A100C0 D8C100C8 + D8E100D0 D90100D8 + 39200200 80DF0004 + B1210070 39200000 + 39210100 91210074 + 39210080 91210078 + 808D9FC8 391F000C + 38FF0008 38A00000 + 38610008 4AADDA3D + 813F0004 38610008 + 91210064 91210060 + A95F0000 388000FF + 91410024 7FC5F378 + E01F5000 38C10070 + F001002C 38000000 + 90010034 4AADD8C9 + BBC100F0 382100F8 + 80010004 7C0803A6 + 4E800020 00000000 + + + 077F0238 000000D4 + 9421FF08 7C0802A6 + BFC100F0 7C7F1B78 + 900100FC 7C9E2378 + 90A10088 90C1008C + 90E10090 91010094 + 91210098 9141009C + D82100A0 D84100A8 + D86100B0 D88100B8 + D8A100C0 D8C100C8 + D8E100D0 D90100D8 + 39200200 80DF0004 + B1210070 39200000 + 39210100 91210074 + 39210080 91210078 + 808D9EF0 391F000C + 38FF0008 38A00000 + 38610008 4AAD5AD1 + 813F0004 38610008 + 91210064 91210060 + A95F0000 388000FF + 91410024 7FC5F378 + E01F5000 38C10070 + F001002C 38000000 + 90010034 4AAD595D + BBC100F0 382100F8 + 80010004 7C0803A6 + 4E800020 00000000 + InstantRestart @@ -4194,62 +3829,75 @@ 0.2.0 Apr 28, 2022 - When you pressed the buttons configured in [#Button Config](#config) simultaneously, - you can restart the current area without selecting "Exit Area" in pause menu. - Note that the restart function behaves differently than pressing Y or Z with "Level Select". - This code only supports restarting 1 area only. - For example, you can restart outside a secret stage or inside a secret stage individually, - but you can NOT restart a combination of outside+inside a secret stage. + When you pressed the buttons configured in [#Button Config](#config) simultaneously, + you can restart the current area without selecting "Exit Area" in pause menu. + Note that the restart function behaves differently than pressing Y or Z with "Level Select". + This code only supports restarting 1 area only. + For example, you can restart outside a secret stage or inside a secret stage individually, + but you can NOT restart a combination of outside+inside a secret stage. - ::: warning - You can NOT restart after destroying the last platform in Bowser fight at the moment. - ::: + ::: warning + You can NOT restart after destroying the last platform in Bowser fight at the moment. + ::: - [#ボタン設定](#config)で設定したボタンを同時に押すと、ポーズメニューから「コースから出る」を選択せずに所在のエリアをやり直すことができます。ただし、Level SelectのYとZのやり直し機能と異なり、エリアごとのやり直ししかできないので注意してください。例えば、ヒミツ外部のみ、ヒミツ内部のみといった一つのエリアのやり直しはできますが、ヒミツ外部+ヒミツ内部といった組み合わせのやり直しはできません。 + [#ボタン設定](#config)で設定したボタンを同時に押すと、ポーズメニューから「コースから出る」を選択せずに所在のエリアをやり直すことができます。ただし、Level SelectのYとZのやり直し機能と異なり、エリアごとのやり直ししかできないので注意してください。例えば、ヒミツ外部のみ、ヒミツ内部のみといった一つのエリアのやり直しはできますが、ヒミツ外部+ヒミツ内部といった組み合わせのやり直しはできません。 - ::: warning - 現時点ではクッパ戦で最後の足場を破壊するとやり直しできません。 - ::: + ::: warning + 現時点ではクッパ戦で最後の足場を破壊するとやり直しできません。 + ::: - C20EAFA0 0000000A - 3C608040 A0A30D50 - 28050808 40A20038 - 3C60817F 38A00001 - 98A300B3 98A30100 - 3C60803E 84A3600E - 90A30004 38A00040 - 90A30000 3C60800E - 6063B3F8 7C6803A6 - 4E800020 2C000002 - 60000000 00000000 - - - C227768C 0000000A - 3C60803F A0A35428 - 28050808 40A20038 - 3C60817F 38A00001 - 98A300B3 98A30100 - 3C60803E 84A3A8EE - 90A30004 38A00040 - 90A30000 3C608027 - 60637AE4 7C6803A6 - 4E800020 2C000002 - 60000000 00000000 + C20EAFA0 0000000A + 3C608040 A0A30D50 + 28050208 40A20038 + 3C60817F 38A00001 + 98A300B3 98A30100 + 3C60803E 84A3600E + 90A30004 38A00040 + 90A30000 3C60800E + 6063B3F8 7C6803A6 + 4E800020 2C000002 + 60000000 00000000 - C22979E4 0000000A - 3C608040 A0A34454 - 28050808 40A20038 - 3C60817F 38A00001 - 98A300B3 98A30100 - 3C60803F 84A3970E - 90A30004 38A00040 - 90A30000 3C608029 - 60637E3C 7C6803A6 - 4E800020 2C000002 - 60000000 00000000 + C22979E4 0000000A + 3C608040 A0A34454 + 28050208 40A20038 + 3C60817F 38A00001 + 98A300B3 98A30100 + 3C60803F 84A3970E + 90A30004 38A00040 + 90A30000 3C608029 + 60637E3C 7C6803A6 + 4E800020 2C000002 + 60000000 00000000 + + + C228F87C 0000000A + 3C608040 A0A3BBF4 + 28050208 40A20038 + 3C60817F 38A00001 + 98A300B3 98A30100 + 3C60803E 84A310CE + 90A30004 38A00040 + 90A30000 3C608028 + 6063FCD4 7C6803A6 + 4E800020 2C000002 + 60000000 00000000 + + + C227768C 0000000A + 3C60803F A0A35428 + 28050208 40A20038 + 3C60817F 38A00001 + 98A300B3 98A30100 + 3C60803E 84A3A8EE + 90A30004 38A00040 + 90A30000 3C608027 + 60637AE4 7C6803A6 + 4E800020 2C000002 + 60000000 00000000 @@ -4332,22 +3980,77 @@ 70000061 4C423102 60000000 00000000 28400D51 00000024 - 040ECF14 b01a004c - 040ec5d0 70000061 + 040ECF14 B01A004C + 040EC5D0 70000061 + E0000000 00000000 + + + 28404454 00000028 + C2299990 0000000A + 899A0064 2C0C0001 + 40A20040 819A0074 + 818C0094 816C02B8 + 2C0B0003 41A1002C + 41A00018 3D80803F + 818C9734 39600000 + 916C0018 48000014 + 3863000F 907A0054 + 3B800000 48000008 + B01A004C 00000000 + C229904C 00000004 + 807F0074 80630094 + 806302B8 2C830000 + 70000061 4C423102 + 60000000 00000000 + 28404455 00000024 + 04299990 B01A004C + 0429904C 70000061 + E0000000 00000000 + + + 283FBBF4 00000028 + C2291828 0000000A + 899A0064 2C0C0001 + 40A20040 819A0074 + 818C0094 816C08DC + 2C0B0003 41A1002C + 41A00018 3D80803E + 818C10F4 39600000 + 916C0018 48000014 + 3863000F 907A0054 + 3B800000 48000008 + B01A004C 00000000 + C2290EE4 00000004 + 807F0074 80630094 + 806308DC 2C830000 + 70000061 4C423102 + 60000000 00000000 + 283FBBF5 00000024 + 04291828 B01A004C + 04290EE4 70000061 E0000000 00000000 283F5428 00000028 - C2279640 00000005 + C2279640 0000000A 899A0064 2C0C0001 - 4182000C B01A004C - 48000010 3863000F - 907A0054 3B800000 + 40A20040 819A0074 + 818C0094 816C02BC + 2C0B0003 41A1002C + 41A00018 3D80803E + 818CA914 39600000 + 916C0018 48000014 + 3863000F 907A0054 + 3B800000 48000008 + B01A004C 00000000 + C2278CFC 00000004 + 807F0074 80630094 + 806302BC 2C830000 + 70000061 4C423102 60000000 00000000 - 04278D00 60000000 283F5429 00000024 04279640 B01A004C - 04278D00 418204EC + 04278CFC 70000061 E0000000 00000000 @@ -4399,6 +4102,75 @@ 4E800021 A01F00FC 60000000 00000000 + + C228102C 0000000A + 807F03F0 3C808040 + A0844454 54800436 + 2C000800 40820034 + 54840EFD 4182002C + 3C006300 5C0027BE + 980300D0 80030008 + 9003000C 807F03F0 + 3D808028 618C11A8 + 7D8803A6 4E800020 + 60000000 00000000 + C21BC5C4 00000009 + 3C808040 A0844454 + 54800436 2C000800 + 4082002C 54840EFD + 41820024 806D9F28 + 806303F0 93E300F0 + 7FE3FB78 81830000 + 818C0104 7D8803A6 + 4E800021 A01F00FC + 60000000 00000000 + + + C2278DB8 0000000A + 807F03F0 3C808040 + A084BBF4 54800436 + 2C000800 40820034 + 54840EFD 4182002C + 3C006300 5C0027BE + 980300D0 80030008 + 9003000C 807F03F0 + 3D808027 618C8F34 + 7D8803A6 4E800020 + 60000000 00000000 + C21B447C 00000009 + 3C808040 A084BBF4 + 54800436 2C000800 + 4082002C 54840EFD + 41820024 806D9E50 + 806303F0 93E300F0 + 7FE3FB78 81830000 + 818C0104 7D8803A6 + 4E800021 A01F00FC + 60000000 00000000 + + + C2260D7C 0000000A + 807F03F0 3C80803F + A0845428 54800436 + 2C000800 40820034 + 54840EFD 4182002C + 3C006300 5C0027BE + 980300D0 80030008 + 9003000C 807F03F0 + 3D808026 618C0EF8 + 7D8803A6 4E800020 + 60000000 00000000 + C219C34C 00000009 + 3C80803F A0845428 + 54800436 2C000800 + 4082002C 54840EFD + 41820024 806D9DE8 + 806303F0 93E300F0 + 7FE3FB78 81830000 + 818C0104 7D8803A6 + 4E800021 A01F00FC + 60000000 00000000 + misc @@ -4413,7 +4185,7 @@ | Combination | Result | |---------------|------| |B + D-Pad Left | Fast forward 4x | - |B + D-Pad Right| Fast forward 8x (may cause lag) | + |B + D-Pad Right| Fast forward 8x (lag may occur) | ::: warning SGT will be inaccurate with this code. @@ -4425,18 +4197,34 @@ | ボタン | 効果 | |--------------|------| |B + 十字キー左|4倍速| - |B + 十字キー右|8倍速(ラグが発生する可能性がある)| + |B + 十字キー右|8倍速(ラグが発生する可能性があります)| ::: warning このコードを使うとシャインゲットタイマーのタイムがずれます。 ::: - 020ecde2 00000258 + 020ECDE2 00000258 28400D50 00000201 - 020ecde2 00000960 + 020ECDE2 00000960 28400D51 00000202 - 020ecde2 000012C0 + 020ECDE2 000012C0 + E0000000 00000000 + + + 0229985E 00000258 + 28404454 00000201 + 0229985E 00000960 + 28404455 00000202 + 0229985E 000012C0 + E0000000 00000000 + + + 022916F6 00000258 + 283FBBF4 00000201 + 022916F6 00000960 + 283FBBF5 00000202 + 022916F6 000012C0 E0000000 00000000 @@ -5575,6 +5363,800 @@ 39E30008 7DE47850 4E800020 4E800020 + + + qfst + misc + Quarterframe Section Timer + QFセクションタイマー + sup39(サポミク) + 0.1 + Jan 31, 2023 + drawText + + Calculate and display section times whenever Quarterframe Timer freezes. + + + QFタイマーが一時停止する度にセクションタイムを計算して表示します。 + + + C20F9DD0 00000003 + 3C60817F 3BA00004 + 93A303CC 3BA00000 + B3A303CA 00000000 + C22069E4 0000001B + 3821FFD0 BF210008 + 3F20817F AB9903B2 + 3BF903D0 A3D903CA + 7F9DE378 835903B4 + 80D900BC 28060000 + 41A2002C 809900B8 + 80B903CC 7C042800 + 40A1001C 7C052050 + 57CC16BA 7C1F612E + 909903CC 3BDE0001 + B3D903CA 3879039C + 389903AC 3D808020 + 398C1EA8 7D8803A6 + 4E800021 57DBE13F + 41820008 3B7EFFF0 + 7C1BF040 4080004C + 576316BA 7C1F182E + 1D6003E9 38000078 + 7D6B0396 380003E8 + 7CAB0396 1C0503E8 + 7CC05850 387903B0 + 389903C0 39990238 + 7D8803A6 4E800021 + 7FBDD214 3B7B0001 + B3B903B2 4BFFFFB4 + B39903B2 BB210008 + 38210030 00000000 + + + C2286228 00000003 + 3C60817F 3BA00004 + 93A303CC 3BA00000 + B3A303CA 00000000 + C2125550 0000001B + 3821FFD0 BF210008 + 3F20817F AB9903B2 + 3BF903D0 A3D903CA + 7F9DE378 835903B4 + 80D900BC 28060000 + 41A2002C 809900B8 + 80B903CC 7C042800 + 40A1001C 7C052050 + 57CC16BA 7C1F612E + 909903CC 3BDE0001 + B3D903CA 3879039C + 389903AC 3D808012 + 398C1660 7D8803A6 + 4E800021 57DBE13F + 41820008 3B7EFFF0 + 7C1BF040 4080004C + 576316BA 7C1F182E + 1D6003E9 38000078 + 7D6B0396 380003E8 + 7CAB0396 1C0503E8 + 7CC05850 387903B0 + 389903C0 39990238 + 7D8803A6 4E800021 + 7FBDD214 3B7B0001 + B3B903B2 4BFFFFB4 + B39903B2 BB210008 + 38210030 00000000 + + + C229E2DC 00000003 + 3C60817F 3BA00004 + 93A303CC 3BA00000 + B3A303CA 00000000 + C2138E00 0000001B + 3821FFD0 BF210008 + 3F20817F AB9903B2 + 3BF903D0 A3D903CA + 7F9DE378 835903B4 + 80D900BC 28060000 + 41A2002C 809900B8 + 80B903CC 7C042800 + 40A1001C 7C052050 + 57CC16BA 7C1F612E + 909903CC 3BDE0001 + B3D903CA 3879039C + 389903AC 3D808013 + 398C4F0C 7D8803A6 + 4E800021 57DBE13F + 41820008 3B7EFFF0 + 7C1BF040 4080004C + 576316BA 7C1F182E + 1D6003E9 38000078 + 7D6B0396 380003E8 + 7CAB0396 1C0503E8 + 7CC05850 387903B0 + 389903C0 39990238 + 7D8803A6 4E800021 + 7FBDD214 3B7B0001 + B3B903B2 4BFFFFB4 + B39903B2 BB210008 + 38210030 00000000 + + + C22A63CC 00000003 + 3C60817F 3BA00004 + 93A303CC 3BA00000 + B3A303CA 00000000 + C21441C4 0000001B + 3821FFD0 BF210008 + 3F20817F AB9903B2 + 3BF903D0 A3D903CA + 7F9DE378 835903B4 + 80D900BC 28060000 + 41A2002C 809900B8 + 80B903CC 7C042800 + 40A1001C 7C052050 + 57CC16BA 7C1F612E + 909903CC 3BDE0001 + B3D903CA 3879039C + 389903AC 3D808014 + 398C0390 7D8803A6 + 4E800021 57DBE13F + 41820008 3B7EFFF0 + 7C1BF040 4080004C + 576316BA 7C1F182E + 1D6003E9 38000078 + 7D6B0396 380003E8 + 7CAB0396 1C0503E8 + 7CC05850 387903B0 + 389903C0 39990238 + 7D8803A6 4E800021 + 7FBDD214 3B7B0001 + B3B903B2 4BFFFFB4 + B39903B2 BB210008 + 38210030 00000000 + + + + AttemptCounter + misc + Attempt Counter + sup39(サポミク) + 0.1 + Feb 05, 2023 + drawText + + Display attempt count and success count of current area. + + This code can be used with 'Area Lock' of 'Instant Level Select'. + + + 現在のエリアの試行回数と成功回数を表示します。 + + このコードは「レベル選択DX」の「エリアロック」と併用できます。 + + + C210C3C8 00000008 + 7C7E1B78 3D80817F + A00C0476 A17E007C + 7C005800 B16C0476 + 896C0479 996C0478 + 39600000 996C04A8 + 39600001 4082000C + 816C04A4 396B0001 + 916C04A4 00000000 + C20EDAE8 00000005 + 7C0802A6 3D80817F + 816C04A4 3D6B0001 + 916C04A4 896C0479 + 996C0478 39600001 + 996C04A8 00000000 + C20EAB7C 00000008 + 3B836000 A19C000E + A17C000A 7C0C5800 + 41820028 3D80817F + 896C04A8 7D6B5B79 + 40820018 816C04A4 + 3D6B0001 916C04A4 + 896C0479 996C0478 + 60000000 00000000 + C22069D8 0000000A + 3D80817F 886C0478 + 3463FFFF 41A00040 + 986C0478 386C0490 + 38830010 3D808020 + 398C1EA8 7D8803A6 + 4E800021 3D80817F + 386C0480 388C047A + A0AC04A4 A0CC04A6 + 398C0238 7D8803A6 + 4E800021 00000000 + + + C2296F20 00000008 + 7C7E1B78 3D80817F + A00C0476 A17E007C + 7C005800 B16C0476 + 896C0479 996C0478 + 39600000 996C04A8 + 39600001 4082000C + 816C04A4 396B0001 + 916C04A4 00000000 + C227A214 00000005 + 7C0802A6 3D80817F + 816C04A4 3D6B0001 + 916C04A4 896C0479 + 996C0478 39600001 + 996C04A8 00000000 + C2277268 00000008 + 3B83A8E0 A19C000E + A17C000A 7C0C5800 + 41820028 3D80817F + 896C04A8 7D6B5B79 + 40820018 816C04A4 + 3D6B0001 916C04A4 + 896C0479 996C0478 + 60000000 00000000 + C2125544 0000000A + 3D80817F 886C0478 + 3463FFFF 41A00040 + 986C0478 386C0490 + 38830010 3D808012 + 398C1660 7D8803A6 + 4E800021 3D80817F + 386C0480 388C047A + A0AC04A4 A0CC04A6 + 398C0238 7D8803A6 + 4E800021 00000000 + + + C22AF6E0 00000008 + 7C7E1B78 3D80817F + A00C0476 A17E007C + 7C005800 B16C0476 + 896C0479 996C0478 + 39600000 996C04A8 + 39600001 4082000C + 816C04A4 396B0001 + 916C04A4 00000000 + C22923FC 00000005 + 7C0802A6 3D80817F + 816C04A4 3D6B0001 + 916C04A4 896C0479 + 996C0478 39600001 + 996C04A8 00000000 + C228F458 00000008 + 3B8310C0 A19C000E + A17C000A 7C0C5800 + 41820028 3D80817F + 896C04A8 7D6B5B79 + 40820018 816C04A4 + 3D6B0001 916C04A4 + 896C0479 996C0478 + 60000000 00000000 + C2138DF4 0000000A + 3D80817F 886C0478 + 3463FFFF 41A00040 + 986C0478 386C0490 + 38830010 3D808013 + 398C4F0C 7D8803A6 + 4E800021 3D80817F + 386C0480 388C047A + A0AC04A4 A0CC04A6 + 398C0238 7D8803A6 + 4E800021 00000000 + + + C22B7710 00000008 + 7C7E1B78 3D80817F + A00C0476 A17E007C + 7C005800 B16C0476 + 896C0479 996C0478 + 39600000 996C04A8 + 39600001 4082000C + 816C04A4 396B0001 + 916C04A4 00000000 + C229A564 00000005 + 7C0802A6 3D80817F + 816C04A4 3D6B0001 + 916C04A4 896C0479 + 996C0478 39600001 + 996C04A8 00000000 + C22975C0 00000008 + 3B839700 A19C000E + A17C000A 7C0C5800 + 41820028 3D80817F + 896C04A8 7D6B5B79 + 40820018 816C04A4 + 3D6B0001 916C04A4 + 896C0479 996C0478 + 60000000 00000000 + C21441B8 0000000A + 3D80817F 886C0478 + 3463FFFF 41A00040 + 986C0478 386C0490 + 38830010 3D808014 + 398C0390 7D8803A6 + 4E800021 3D80817F + 386C0480 388C047A + A0AC04A4 A0CC04A6 + 398C0238 7D8803A6 + 4E800021 00000000 + + + + misc + In-Stage Attempt Counter + ステージ内Attempt Counter + sup39(サポミク) + 1.0 + Feb 13, 2023 + + | Combination | Result | + | ----------- | --------------------------- | + | D-Pad Left | Display the attempt counter | + | D-Pad Right | Increase attempt count by 1 | + + + | ボタン | 機能 | + | ---------- | --------------------- | + | 十字キー左 | Attempt Counterを表示 | + | 十字キー右 | 試行回数を1増やす | + + + C20ECE5C 0000000A + 3D608040 A40B0D82 + 2B800001 419E000C + 28000002 40A20030 + 3D40817F 880A0479 + 980A0478 419E0020 + A00B0004 A18B0008 + 7C006279 41820010 + A18A04A6 398C0001 + B18A04A6 38E00000 + 60000000 00000000 + + + C2279588 0000000A + 3D60803F A40B545A + 2B800001 419E000C + 28000002 40A20030 + 3D40817F 880A0479 + 980A0478 419E0020 + A00B0004 A18B0008 + 7C006279 41820010 + A18A04A6 398C0001 + B18A04A6 38E00000 + 60000000 00000000 + + + C2291770 0000000A + 3D608040 A40BBC26 + 2B800001 419E000C + 28000002 40A20030 + 3D40817F 880A0479 + 980A0478 419E0020 + A00B0004 A18B0008 + 7C006279 41820010 + A18A04A6 398C0001 + B18A04A6 38E00000 + 60000000 00000000 + + + C22998D8 0000000A + 3D608040 A40B4486 + 2B800001 419E000C + 28000002 40A20030 + 3D40817F 880A0479 + 980A0478 419E0020 + A00B0004 A18B0008 + 7C006279 41820010 + A18A04A6 398C0001 + B18A04A6 38E00000 + 60000000 00000000 + + + + misc + Manual Attempt Counter + 手動Attempt Counter + sup39(サポミク) + 1.0 + Feb 13, 2023 + + Allows you to modify the attempt count and success count manually. + + | Combination | Result | + | ------------------- | --------------------------- | + | R + X + D-Pad Left | Decrease attempt count by 1 | + | R + X + D-Pad Right | Increase attempt count by 1 | + | R + X + D-Pad Down | Decrease success count by 1 | + | R + X + D-Pad Up | Increase success count by 1 | + + + Attempt Counterを手動で操作できるようになります。 + + | ボタン | 機能 | + | ------------------ | ----------------- | + | R + X + 十字キー左 | 試行回数を1減らす | + | R + X + 十字キー右 | 試行回数を1増やす | + | R + X + 十字キー下 | 成功回数を1減らす | + | R + X + 十字キー上 | 成功回数を1増やす | + + + C20ECE58 0000000D + 3D208040 A4090D82 + 7000FFF0 28000420 + 40A2004C 89290019 + 5520073F 41820040 + 3D40817F 880A0479 + 980A0478 A18A04A4 + 5520F7FE 7D806050 + 5520EFFE 7D8C0214 + B18A04A4 A18A04A6 + 552007FE 7D806050 + 5520FFFE 7D8C0214 + B18A04A6 38C00000 + 60000000 00000000 + + + C2279584 0000000D + 3D20803F A409545A + 7000FFF0 28000420 + 40A2004C 89290019 + 5520073F 41820040 + 3D40817F 880A0479 + 980A0478 A18A04A4 + 5520F7FE 7D806050 + 5520EFFE 7D8C0214 + B18A04A4 A18A04A6 + 552007FE 7D806050 + 5520FFFE 7D8C0214 + B18A04A6 38C00000 + 60000000 00000000 + + + C229176C 0000000D + 3D208040 A409BC26 + 7000FFF0 28000420 + 40A2004C 89290019 + 5520073F 41820040 + 3D40817F 880A0479 + 980A0478 A18A04A4 + 5520F7FE 7D806050 + 5520EFFE 7D8C0214 + B18A04A4 A18A04A6 + 552007FE 7D806050 + 5520FFFE 7D8C0214 + B18A04A6 38C00000 + 60000000 00000000 + + + C22998D4 0000000D + 3D208040 A4094486 + 7000FFF0 28000420 + 40A2004C 89290019 + 5520073F 41820040 + 3D40817F 880A0479 + 980A0478 A18A04A4 + 5520F7FE 7D806050 + 5520EFFE 7D8C0214 + B18A04A4 A18A04A6 + 552007FE 7D806050 + 5520FFFE 7D8C0214 + B18A04A6 38C00000 + 60000000 00000000 + + + + controller + metadata + Controller Input Display + コントローラ入力表示 + sup39(サポミク) + 0.1 + Feb 05, 2023 + + Display controller input. + + + コントローラ入力を表示します。 + + + C20F9CCC 00000047 + 4E800021 9421FEB0 + BE610008 3C003A04 + 7C17E3A6 3F00817F + 3B1804C3 83AD8DF0 + 7FBDEB79 41820208 + 838D8DF4 480000B0 + 38800000 3D80800B + 398C88A8 7D8903A6 + 4E800420 7F2803A6 + 4E800020 3BE5FFFF + 7F2802A6 7CBE0034 + 3BDEFFEF 4BFFFFD5 + E0577000 E077F002 + 82770004 5FE0F4BA + 7C1C042E 7C3D042E + 10000C20 100010DC + F01B3000 B35B0000 + 927B0000 37FFFFFF + 4080FFDC 3AF70008 + 4BFFFFAC 3BE50000 + 7F2802A6 4BFFFF8D + 57E007BC 1017078C + F01BB000 37FFFFFF + 57E007BC 60000001 + 1017078C F01BB000 + B35B0000 927B0000 + 4181FFD8 3AF70004 + 4BFFFF6C 38610050 + 7EC4B378 3D808003 + 398C6B38 4BFFFF51 + 88180000 98030038 + 80180001 90030084 + 90030098 E0185005 + 102004A0 F0038090 + F02380A0 3D808003 + 398C6CEC 4BFFFF21 + 3860FFFF 38800001 + 3D808024 398C2F80 + 4BFFFF0D 3B400000 + 3F60CC00 637B8000 + 3EA08040 A6950D50 + 3AF80015 386000A0 + 38A00004 8277FFF4 + 4BFFFF45 3AD70030 + 88970003 5E8427FF + 41A20014 386000A0 + 38A00020 4BFFFED9 + 3AF7FFF8 386000B0 + 38A00021 4BFFFEC9 + 7C17B040 4180FFD4 + 3AD70014 3AB5003C + 88970004 5E8427FF + E017A008 C4350004 + 40820010 E017A000 + E057C005 EC0100BA + F017A002 386000A0 + 38A00004 8278000D + 4BFFFED5 3AF70002 + 386000B0 38A00005 + 82780011 4BFFFEC1 + 7C17B040 4180FFB4 + 3AD70020 3AB5006C + E0172008 E4350040 + 10400850 10211460 + E057A003 1001009C + F0172000 386000A0 + 38A00020 4BFFFE39 + 386000B0 38A00009 + 4BFFFE2D 7C17B040 + 4180FFC8 BA610008 + 38210150 00000000 + + + C2286124 00000047 + 4E800021 9421FEB0 + BE610008 3C003A04 + 7C17E3A6 3F00817F + 3B1804C3 83ADA018 + 7FBDEB79 41820208 + 838DA01C 480000B0 + 38800000 3D808034 + 398CD888 7D8903A6 + 4E800420 7F2803A6 + 4E800020 3BE5FFFF + 7F2802A6 7CBE0034 + 3BDEFFEF 4BFFFFD5 + E0577000 E077F002 + 82770004 5FE0F4BA + 7C1C042E 7C3D042E + 10000C20 100010DC + F01B3000 B35B0000 + 927B0000 37FFFFFF + 4080FFDC 3AF70008 + 4BFFFFAC 3BE50000 + 7F2802A6 4BFFFF8D + 57E007BC 1017078C + F01BB000 37FFFFFF + 57E007BC 60000001 + 1017078C F01BB000 + B35B0000 927B0000 + 4181FFD8 3AF70004 + 4BFFFF6C 38610050 + 7EC4B378 3D80802D + 398CC7DC 4BFFFF51 + 88180000 98030038 + 80180001 90030084 + 90030098 E0185005 + 102004A0 F0038090 + F02380A0 3D80802D + 398CC990 4BFFFF21 + 3860FFFF 38800001 + 3D808016 398C3F7C + 4BFFFF0D 3B400000 + 3F60CC00 637B8000 + 3EA0803F A6955428 + 3AF80015 386000A0 + 38A00004 8277FFF4 + 4BFFFF45 3AD70030 + 88970003 5E8427FF + 41A20014 386000A0 + 38A00020 4BFFFED9 + 3AF7FFF8 386000B0 + 38A00021 4BFFFEC9 + 7C17B040 4180FFD4 + 3AD70014 3AB5003C + 88970004 5E8427FF + E017A008 C4350004 + 40820010 E017A000 + E057C005 EC0100BA + F017A002 386000A0 + 38A00004 8278000D + 4BFFFED5 3AF70002 + 386000B0 38A00005 + 82780011 4BFFFEC1 + 7C17B040 4180FFB4 + 3AD70020 3AB5006C + E0172008 E4350040 + 10400850 10211460 + E057A003 1001009C + F0172000 386000A0 + 38A00020 4BFFFE39 + 386000B0 38A00009 + 4BFFFE2D 7C17B040 + 4180FFC8 BA610008 + 38210150 00000000 + + + C229E1D8 00000047 + 4E800021 9421FEB0 + BE610008 3C003A04 + 7C17E3A6 3F00817F + 3B1804C3 83ADA090 + 7FBDEB79 41820208 + 838DA094 480000B0 + 38800000 3D808035 + 398C61A8 7D8903A6 + 4E800420 7F2803A6 + 4E800020 3BE5FFFF + 7F2802A6 7CBE0034 + 3BDEFFEF 4BFFFFD5 + E0577000 E077F002 + 82770004 5FE0F4BA + 7C1C042E 7C3D042E + 10000C20 100010DC + F01B3000 B35B0000 + 927B0000 37FFFFFF + 4080FFDC 3AF70008 + 4BFFFFAC 3BE50000 + 7F2802A6 4BFFFF8D + 57E007BC 1017078C + F01BB000 37FFFFFF + 57E007BC 60000001 + 1017078C F01BB000 + B35B0000 927B0000 + 4181FFD8 3AF70004 + 4BFFFF6C 38610050 + 7EC4B378 3D80802E + 398C5174 4BFFFF51 + 88180000 98030038 + 80180001 90030084 + 90030098 E0185005 + 102004A0 F0038090 + F02380A0 3D80802E + 398C5328 4BFFFF21 + 3860FFFF 38800001 + 3D808018 398C91DC + 4BFFFF0D 3B400000 + 3F60CC00 637B8000 + 3EA08040 A695BBF4 + 3AF80015 386000A0 + 38A00004 8277FFF4 + 4BFFFF45 3AD70030 + 88970003 5E8427FF + 41A20014 386000A0 + 38A00020 4BFFFED9 + 3AF7FFF8 386000B0 + 38A00021 4BFFFEC9 + 7C17B040 4180FFD4 + 3AD70014 3AB5003C + 88970004 5E8427FF + E017A008 C4350004 + 40820010 E017A000 + E057C005 EC0100BA + F017A002 386000A0 + 38A00004 8278000D + 4BFFFED5 3AF70002 + 386000B0 38A00005 + 82780011 4BFFFEC1 + 7C17B040 4180FFB4 + 3AD70020 3AB5006C + E0172008 E4350040 + 10400850 10211460 + E057A003 1001009C + F0172000 386000A0 + 38A00020 4BFFFE39 + 386000B0 38A00009 + 4BFFFE2D 7C17B040 + 4180FFC8 BA610008 + 38210150 00000000 + + + C22A62C8 00000047 + 4E800021 9421FEB0 + BE610008 3C003A04 + 7C17E3A6 3F00817F + 3B1804C3 83ADA158 + 7FBDEB79 41820208 + 838DA15C 480000B0 + 38800000 3D808036 + 398CDF88 7D8903A6 + 4E800420 7F2803A6 + 4E800020 3BE5FFFF + 7F2802A6 7CBE0034 + 3BDEFFEF 4BFFFFD5 + E0577000 E077F002 + 82770004 5FE0F4BA + 7C1C042E 7C3D042E + 10000C20 100010DC + F01B3000 B35B0000 + 927B0000 37FFFFFF + 4080FFDC 3AF70008 + 4BFFFFAC 3BE50000 + 7F2802A6 4BFFFF8D + 57E007BC 1017078C + F01BB000 37FFFFFF + 57E007BC 60000001 + 1017078C F01BB000 + B35B0000 927B0000 + 4181FFD8 3AF70004 + 4BFFFF6C 38610050 + 7EC4B378 3D80802F + 398CCFCC 4BFFFF51 + 88180000 98030038 + 80180001 90030084 + 90030098 E0185005 + 102004A0 F0038090 + F02380A0 3D80802F + 398CD180 4BFFFF21 + 3860FFFF 38800001 + 3D808018 398C2BF8 + 4BFFFF0D 3B400000 + 3F60CC00 637B8000 + 3EA08040 A6954454 + 3AF80015 386000A0 + 38A00004 8277FFF4 + 4BFFFF45 3AD70030 + 88970003 5E8427FF + 41A20014 386000A0 + 38A00020 4BFFFED9 + 3AF7FFF8 386000B0 + 38A00021 4BFFFEC9 + 7C17B040 4180FFD4 + 3AD70014 3AB5003C + 88970004 5E8427FF + E017A008 C4350004 + 40820010 E017A000 + E057C005 EC0100BA + F017A002 386000A0 + 38A00004 8278000D + 4BFFFED5 3AF70002 + 386000B0 38A00005 + 82780011 4BFFFEC1 + 7C17B040 4180FFB4 + 3AD70020 3AB5006C + E0172008 E4350040 + 10400850 10211460 + E057A003 1001009C + F0172000 386000A0 + 38A00020 4BFFFE39 + 386000B0 38A00009 + 4BFFFE2D 7C17B040 + 4180FFC8 BA610008 + 38210150 00000000 + savestate diff --git a/Removed-Codes.xml b/Removed-Codes.xml index a753450..b673557 100644 --- a/Removed-Codes.xml +++ b/Removed-Codes.xml @@ -533,4 +533,424 @@ 60000000 00000000 + + metadata + PASDisplay + Position/angle/speed display + Position/Winkel/Geschw. Display + Affichage de position/angle/vitesse + 位置/角度/速度表示 + Noki Doki, sup39(サポミク) + 1.4 + Mar 24, 2022 + drawText + drawText + + Shows Mario's position, angle and speed at any given time. + + ::: warning + This code is not compatible with the Speed Display code. + ::: + + + Zeigt Mario's Position, Winkel und Geschwindigkeit jederzeit auf dem Bildschirm an. + + ::: warning + Dieser Code ist nicht kompatibel mit dem Geschwindigkeits-Display Code + ::: + + Affiche la position, l'angle et la vitesse de Mario à tout moment. + 常に「マリオの位置」「マリオの角度」「マリオの速度」を表示します。 + + 062A6160 00000010 + 49553F19 60000000 + 60000000 60000000 + 042998B8 49560749 + 04143F14 496B6209 + 077FA000 000001E8 + 9421FFE0 7C0802A6 + 90010024 93E1001C + 4AABD6E5 38E00200 + 38C00320 38A0FFD8 + 3880000A 38610008 + 4AAD01B9 814D9FC8 + 3FE08180 3BFFA1EC + 39200000 39000002 + 3CE08180 38E7A164 + 80CA0048 38A10008 + 38800000 7FE3FB78 + 4AAD67F1 39200001 + 913F01B0 80010024 + 7C0803A6 83E1001C + 38210020 4E800020 + 9421FFE8 7C0802A6 + 9001001C 93A1000C + 93C10010 93E10014 + 7C7F1B78 81230000 + 83A90064 3D208180 + 8129A39C 2F890000 + 409E002C 7FE3FB78 + 7FA903A6 4E800421 + 8001001C 7C0803A6 + 83A1000C 83C10010 + 83E10014 38210018 + 4E800020 3D208040 + 6129E0E8 83C90000 + 3C608180 3863A1EC + 4AAD6B79 C0BE00A8 + C09E00B0 A0DE0096 + C07E0018 C05E0014 + C03E0010 3CA08180 + 38A5A164 38800080 + 4CC63242 4AB3F691 + 4BFFFF94 9421FFF0 + 7C0802A6 90010014 + 93E1000C 7C7F1B78 + 4AAF158D 38E00081 + 7FE6FB78 38A00000 + 38800000 3C608180 + 3863A1EC 4AAD5C5D + 80010014 7C0803A6 + 83E1000C 38210010 + 4E800020 5820506F + 7320252E 30660A59 + 20506F73 20252E30 + 660A5A20 506F7320 + 252E3066 0A416E67 + 6C652025 68750A48 + 20537064 20252E32 + 660A5620 53706420 + 252E3266 20202020 + 20202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202000 00000000 + C22A66F4 00000003 + 38600000 3D808180 + 906CA39C 807F0040 + 60000000 00000000 + + + 04206734 495F38CD + 077FA000 000000B5 + 9421FFF0 7C0802A6 + 90010014 93E1000C + 7C7F1B78 4A83B215 + 3D208041 8149A378 + 3D008180 38600010 + 3908A074 C0AA00A8 + 38E0FFFF C08A00B0 + 38C0FFFF A12A0096 + 38A00014 C06A0018 + 388000C8 C04A0014 + C02A0010 4CC63242 + 4BFF61E1 80010014 + 7FE3FB78 83E1000C + 7C0803A6 38210010 + 4A83B1B8 5820506F + 7320252E 30660A59 + 20506F73 20252E30 + 660A5A20 506F7320 + 252E3066 0A416E67 + 6C652025 68750A48 + 20537064 20252E32 + 660A5620 53706420 + 252E3266 00000000 + + + 041252A0 496D4D61 + 077FA000 000000B5 + 9421FFF0 7C0802A6 + 90010014 93E1000C + 7C7F1B78 4AAD0EB9 + 3D208040 8149EF88 + 3D008180 38600010 + 3908A074 C0AA00A8 + 38E0FFFF C08A00B0 + 38C0FFFF A12A0096 + 38A00014 C06A0018 + 388000C8 C04A0014 + C02A0010 4CC63242 + 4BFF61E1 80010014 + 7FE3FB78 83E1000C + 7C0803A6 38210010 + 4AAD0E5C 5820506F + 7320252E 30660A59 + 20506F73 20252E30 + 660A5A20 506F7320 + 252E3066 0A416E67 + 6C652025 68750A48 + 20537064 20252E32 + 660A5620 53706420 + 252E326600000000 + + + 0629E070 00000010 + 4955C009 60000000 + 60000000 60000000 + 04291750 495688B1 + 04138B50 496C15CD + 077FA000 000001E8 + 9421FFE0 7C0802A6 + 90010024 93E1001C + 4AAB56B5 38E00200 + 38C00320 38A0FFD8 + 3880000A 38610008 + 4AAC824D 814D9EF0 + 3FE08180 3BFFA1EC + 39200000 39000002 + 3CE08180 38E7A164 + 80CA0048 38A10008 + 38800000 7FE3FB78 + 4AACE999 39200001 + 913F01B0 80010024 + 7C0803A6 83E1001C + 38210020 4E800020 + 9421FFE8 7C0802A6 + 9001001C 93A1000C + 93C10010 93E10014 + 7C7F1B78 81230000 + 83A90064 3D208180 + 8129A39C 2F890000 + 409E002C 7FE3FB78 + 7FA903A6 4E800421 + 8001001C 7C0803A6 + 83A1000C 83C10010 + 83E10014 38210018 + 4E800020 3D208040 + 612957B0 83C90000 + 3C608180 3863A1EC + 4AACED21 C0BE00A8 + C09E00B0 A0DE0096 + C07E0018 C05E0014 + C03E0010 3CA08180 + 38A5A164 38800080 + 4CC63242 4AB37811 + 4BFFFF94 9421FFF0 + 7C0802A6 90010014 + 93E1000C 7C7F1B78 + 4AAE9735 38E00081 + 7FE6FB78 38A00000 + 38800000 3C608180 + 3863A1EC 4AACDE05 + 80010014 7C0803A6 + 83E1000C 38210010 + 4E800020 5820506F + 7320252E 30660A59 + 20506F73 20252E30 + 660A5A20 506F7320 + 252E3066 0A416E67 + 6C652025 68750A48 + 20537064 20252E32 + 660A5620 53706420 + 252E3266 20202020 + 20202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202000 00000000 + C229E64C 00000003 + 38600000 3D808180 + 906CA39C 807F0040 + 60000000 00000000 + + + + metadata + SpeedDisplay + Speed display + Geschwindigkeits-Display + Affichage de vitesse + 速度表示 + Noki Doki, sup39(サポミク) + 1.5 + Mar 24, 2022 + drawText + drawText + + Shows Mario's speed at any given time. + + ::: warning + This code is not compatible with the Position/Angle/Speed Display code. + ::: + + + Zeigt Mario's Geschwindigkeit jederzeit auf dem Bildschirm an. + + ::: warning + Dieser Code ist nicht kompatibel mit dem Position/Winkel/Gewschw. Display Code + ::: + + Affiche la vitesse de Mario à tout moment. + 常に「マリオの速度」を表示します。 + + 062A6160 00000010 + 49553F19 60000000 + 60000000 60000000 + 042998B8 49560749 + 04143F14 496B61F9 + 077FA000 00000188 + 9421FFE0 7C0802A6 + 90010024 93E1001C + 4AABD6E5 38E00200 + 38C00320 38A0FFD8 + 3880000A 38610008 + 4AAD01B9 814D9FC8 + 3FE08180 3BFFA214 + 39200000 39000002 + 3CE08180 38E7A154 + 80CA0048 38A10008 + 38800000 7FE3FB78 + 4AAD67F1 39200001 + 913F01B0 80010024 + 7C0803A6 83E1001C + 38210020 4E800020 + 9421FFE8 7C0802A6 + 9001001C 93C10010 + 93E10014 7C7F1B78 + 81230000 83C90064 + 3D208180 8129A3C4 + 2C090000 40820028 + 7FE3FB78 7FC903A6 + 4E800421 8001001C + 7C0803A6 83C10010 + 83E10014 38210018 + 4E800020 93A1000C + 3D208040 6129E0E8 + 83A90000 3C608180 + 3863A214 4AAD6B7D + C05D00A8 C03D00B0 + 3CA08180 38A5A154 + 38800030 4CC63242 + 4AB3F6A5 83A1000C + 4BFFFFA0 9421FFF0 + 7C0802A6 90010014 + 93E1000C 7C7F1B78 + 4AAF159D 38E00081 + 7FE6FB78 38A00000 + 38800000 3C608180 + 3863A214 4AAD5C6D + 80010014 7C0803A6 + 83E1000C 38210010 + 4E800020 48205370 + 6420252E 32660A56 + 20537064 20252E32 + 66202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202000 00000000 + C22A66F4 00000003 + 38600000 3D808180 + 906CA3C4 807F0040 + 60000000 00000000 + + + 04206734 495F38CD + 077FA000 0000007A + 9421FFF0 7C0802A6 + 90010014 93E1000C + 7C7F1B78 4A83B215 + 3D208041 8129A378 + 3D008180 38600010 + 3908A064 C04900A8 + 38E0FFFF C02900B0 + 38C0FFFF 38A00014 + 388000F0 4CC63242 + 4BFF61F1 80010014 + 7FE3FB78 83E1000C + 7C0803A6 38210010 + 4A83B1C8 48205370 + 6420252E 32660A56 + 20537064 20252E32 + 66000000 00000000 + + + 041252A0 496D4D61 + 077FA000 0000007A + 9421FFF0 7C0802A6 + 90010014 93E1000C + 7C7F1B78 4AAD0EB9 + 3D208040 8129EF88 + 3D008180 38600010 + 3908A064 C04900A8 + 38E0FFFF C02900B0 + 38C0FFFF 38A00014 + 388000F0 4CC63242 + 4BFF61F1 80010014 + 7FE3FB78 83E1000C + 7C0803A6 38210010 + 4AAD0E6C 48205370 + 6420252E 32660A56 + 20537064 20252E32 + 66000000 00000000 + + + 0629E070 00000010 + 4955C009 60000000 + 60000000 60000000 + 04291750 495688B1 + 04138B50 496C15BD + 077FA000 00000188 + 9421FFE0 7C0802A6 + 90010024 93E1001C + 4AAB56B5 38E00200 + 38C00320 38A0FFD8 + 3880000A 38610008 + 4AAC824D 814D9EF0 + 3FE08180 3BFFA214 + 39200000 39000002 + 3CE08180 38E7A154 + 80CA0048 38A10008 + 38800000 7FE3FB78 + 4AACE999 39200001 + 913F01B0 80010024 + 7C0803A6 83E1001C + 38210020 4E800020 + 9421FFE8 7C0802A6 + 9001001C 93C10010 + 93E10014 7C7F1B78 + 81230000 83C90064 + 3D208180 8129A3C4 + 2C090000 40820028 + 7FE3FB78 7FC903A6 + 4E800421 8001001C + 7C0803A6 83C10010 + 83E10014 38210018 + 4E800020 93A1000C + 3D208040 612957B0 + 83A90000 3C608180 + 3863A214 4AACED25 + C05D00A8 C03D00B0 + 3CA08180 38A5A154 + 38800030 4CC63242 + 4AB37825 83A1000C + 4BFFFFA0 9421FFF0 + 7C0802A6 90010014 + 93E1000C 7C7F1B78 + 4AAE9745 38E00081 + 7FE6FB78 38A00000 + 38800000 3C608180 + 3863A214 4AACDE15 + 80010014 7C0803A6 + 83E1000C 38210010 + 4E800020 48205370 + 6420252E 32660A56 + 20537064 20252E32 + 66202020 20202020 + 20202020 20202020 + 20202020 20202020 + 20202000 00000000 + C229E64C 00000003 + 38600000 3D808180 + 906CA3C4 807F0040 + 60000000 00000000 + + diff --git a/changelog.md b/changelog.md index c5b502b..6a73414 100644 --- a/changelog.md +++ b/changelog.md @@ -1,10 +1,25 @@ # Changelog +## Jul 15, 2023 +### Fixed the bug that background color cannot be changed in 'Controller Input Display' +### Ported 'FastForward', 'InstantRestart', 'SpawnYoshi', 'StageIntroSkip' to all versions + +## Jul 9, 2023 +### Updated 'Level Select' +The peaceful plaza (after unlocking Ricco and Gelato) is now available as C↘ + Y, later plazas have their shortcuts moved clockwise, and the post-Corona plaza no longer has a dedicated shortcut. To access it, simply load Corona (X with neutral C stick) or Bowser (C↖ + Y + L) then exit to the plaza. + +## May 17, 2023 +- Added font for NTSC-U +- Fixed the encoding of NTSC-U and PAL (should be Windows-1252 instead of latin1) + ## May 16, 2023 ### GCI Loader 0.5 Added error messages ### GCI Loader 0.4 Fixed hook address of GMSE01 code +## Feb 28, 2023 +Fix preview of Controller Input Display + ## Feb 23, 2023 ### Updated 'Force Plaza Events' Set the correct BH/RH/GB unlock flag @@ -21,6 +36,8 @@ Disable Z menu for Instant Level Select to prevent broken texture - Added 'Mario State Savestate' - Added 'No Shine Get Animation' - Added 'Fruit Never Time Out' +- Added 'In-Stage Attempt Counter' +- Added 'Manual Attempt Counter' ## Feb 11, 2023 - Added 'Deathless Blooper Surfing' @@ -36,6 +53,46 @@ Ported GCI Loader to all versions ### Updated 'Instant Level Select' Overwrite button input value to prevent Level Select being activated when AreaLock is enabled +## Feb 07, 2023 +### Updated 'Customized Display' +Support signed int32 and int16 for fields + +## Feb 06, 2023 +### Fixed 'Customized Display' +Fixed the hex value of multi-byte char in format string + +## Feb 05, 2023 +### Created 'Controller Input Display' +Display controller input +### Created 'Attempt Counter' +Display attempt count and success count of current area +### Updated 'Instant Level Select' +- Rewrote with C2 +- Go to level instantly without transition + +## Jan 31, 2023 +### Created 'Quarterframe Section Timer' +Calculate and display section times whenever Quarterframe Timer freezes +### Updated 'Pattern Selector' +- Rewrote with C2 + separated config 06 +- Remove label option +### Updated 'Customized Display' +- Rewrote with C2 +- Implemented a more complex assembler/compiler to support function call +- Add options + - Invincibility Timer + - Pollution Degree + - Spin Jump Condition Check + +## Jan 28, 2023 +### Rewrote 'drawText' +- Reduced parameters to struct pointer + format string + varargs +- Rewrote QFT, Pattern Selector, Customized Display with the new drawText function +### Improved Preview +- Added PAL font (TODO: NTSC-U) +- Merged P/A/S Display and Speed Display to Customized Display +- Provided background options to Pattern Selector and Customized Display + ## Jan 10, 2023 ### Updated 'Quarterframe Timer' Added the following options to freeze QFT: diff --git a/package-lock.json b/package-lock.json index 3fdaae6..893998c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,10 +14,8 @@ "devDependencies": { "@sup39/markdown-it-attr": "1.2.2", "@sup39/markdown-it-inline-tag": "1.0.1", - "@types/encoding-japanese": "^2.0.1", "@vuepress/plugin-back-to-top": "1.9.8", "@vuepress/plugin-medium-zoom": "1.9.8", - "encoding-japanese": "^2.0.0", "jsdom": "21.1.0", "pre-commit": "1.2.2", "prettier": "2.8.3", @@ -1896,12 +1894,6 @@ "@types/node": "*" } }, - "node_modules/@types/encoding-japanese": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/encoding-japanese/-/encoding-japanese-2.0.1.tgz", - "integrity": "sha512-JaCXs2HLniKY8xXeWlg8MAtd4iKhNh8LwutW3yDMWY4usEdTZ2va1x9kd8V3179OAIUTgGQVA63XJrHettpVFQ==", - "dev": true - }, "node_modules/@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", @@ -6604,15 +6596,6 @@ "node": ">= 0.8" } }, - "node_modules/encoding-japanese": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz", - "integrity": "sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==", - "dev": true, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -19065,12 +19048,6 @@ "@types/node": "*" } }, - "@types/encoding-japanese": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/encoding-japanese/-/encoding-japanese-2.0.1.tgz", - "integrity": "sha512-JaCXs2HLniKY8xXeWlg8MAtd4iKhNh8LwutW3yDMWY4usEdTZ2va1x9kd8V3179OAIUTgGQVA63XJrHettpVFQ==", - "dev": true - }, "@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", @@ -22969,12 +22946,6 @@ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true }, - "encoding-japanese": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz", - "integrity": "sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==", - "dev": true - }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", diff --git a/package.json b/package.json index 181d328..21e3777 100644 --- a/package.json +++ b/package.json @@ -22,10 +22,8 @@ "devDependencies": { "@sup39/markdown-it-attr": "1.2.2", "@sup39/markdown-it-inline-tag": "1.0.1", - "@types/encoding-japanese": "^2.0.1", "@vuepress/plugin-back-to-top": "1.9.8", "@vuepress/plugin-medium-zoom": "1.9.8", - "encoding-japanese": "^2.0.0", "jsdom": "21.1.0", "pre-commit": "1.2.2", "prettier": "2.8.3", diff --git a/site/.vuepress/components/CodeInfo.vue b/site/.vuepress/components/CodeInfo.vue index 756d505..12c0c19 100644 --- a/site/.vuepress/components/CodeInfo.vue +++ b/site/.vuepress/components/CodeInfo.vue @@ -19,6 +19,7 @@ diff --git a/site/.vuepress/components/PreviewString.vue b/site/.vuepress/components/PreviewString.vue index e1a7370..a149d67 100644 --- a/site/.vuepress/components/PreviewString.vue +++ b/site/.vuepress/components/PreviewString.vue @@ -1,47 +1,33 @@ diff --git a/site/.vuepress/components/codes/AttemptCounter/codegen.js b/site/.vuepress/components/codes/AttemptCounter/codegen.js new file mode 100644 index 0000000..b141dfd --- /dev/null +++ b/site/.vuepress/components/codes/AttemptCounter/codegen.js @@ -0,0 +1,55 @@ +import { parseJSON } from '../codegen.js'; +import { insts2hex, getDrawTextOpt, getFillRectParams } from '../asm'; +import { measureText } from '../text.js'; +import { int2hex } from '../utils.js'; +export const lskey = 'config/AttemptCounter'; + +export const defaultConfig = { + x: 152, + y: 125, + fontSize: 32, + fgRGB: 0xffff99, + fgA: 0xff, + fgRGB2: null, + fgA2: null, + bgRGB: 0x000000, + bgA: 0x40, + bgLeft: 4, + bgRight: 6, + bgTop: 4, + bgBot: 3, + duration: 60, +}; + +export const getPreviewText = () => '88\n99'; + +/** @returns {typeof defaultConfig} */ +export function getConfig() { + const config = + (typeof localStorage !== 'undefined' && parseJSON(localStorage.getItem(lskey))) || {}; + return { + ...defaultConfig, + ...config, + text: getPreviewText(), + }; +} + +/** + * @param {keyof typeof import('../addrs.js').ctxSpOff} version + * @param {string=} baseCode + */ +export default function codegen(version, baseCode) { + if (!baseCode) return ''; + + const config = getConfig(); + + let code = baseCode; + code += '077F0479 0000002B'; + code += int2hex(config.duration, 1); + code += '25640A256400'; // fmt = "%d\n%d" + code += insts2hex(getDrawTextOpt(config)); + code += insts2hex(getFillRectParams(config, measureText(getPreviewText(), version))); + code += '0000000000'; // padding + + return code.replace(/\s/g, ''); +} diff --git a/site/.vuepress/components/codes/AttemptCounter/config.vue b/site/.vuepress/components/codes/AttemptCounter/config.vue new file mode 100644 index 0000000..da8add2 --- /dev/null +++ b/site/.vuepress/components/codes/AttemptCounter/config.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/site/.vuepress/components/codes/CustomizedDisplay/assembler.js b/site/.vuepress/components/codes/CustomizedDisplay/assembler.js new file mode 100644 index 0000000..37ab83c --- /dev/null +++ b/site/.vuepress/components/codes/CustomizedDisplay/assembler.js @@ -0,0 +1,214 @@ +import { ASM, liDX, makeProgram, insts2hex } from '../asm.js'; +import { splitArray } from '../utils.js'; + +/** + * @typedef {number} Inst + * @typedef {{type: 'call', addr: number, prep?: Inst[]}} CallInst -- function call instruction + * @typedef {{type: 'struct', reg: number, hex: string}} LoadStructInst -- struct pointer load instruction + * @typedef {Inst|CallInst|LoadStructInst} ASMInst + */ + +/** + * @param {ASMInst[]} insts + * @param {number} stackFrameSize + */ +export function assemble(insts, stackFrameSize) { + const rAddr = 12; + const rData = 31; + + /** + * [0]: data + * [.]: body + */ + const p = makeProgram(0); + + /** @type {Map>} */ + const callCounts = new Map(); // [addr][prep] = count + /** @type {Set} */ + const structDB = new Set(); + + // summarize data + let hasRepeatCall = false; + let loadStructCount = 0; + let sizeWithoutBLTrick = 0; // # of instruction + for (const inst of insts) { + if (typeof inst === 'number') continue; + const { type } = inst; + if (type === 'call') { + const { addr, prep = [] } = inst; + const prepKey = insts2hex(prep); + const prepCounts = callCounts.get(addr); + if (prepCounts == null) { + callCounts.set(addr, new Map([[prepKey, 1]])); + } else { + prepCounts.set(prepKey, (prepCounts.get(prepKey) ?? 0) + 1); + hasRepeatCall = true; + } + } else if (type === 'struct') { + const { hex } = inst; + structDB.add(hex); + loadStructCount++; + sizeWithoutBLTrick += ((hex.length + 7) >>> 3) + 2; // bl L; mflr + } + } + + const useSharedCall = hasRepeatCall || callCounts.size > 2; + const sizeWithBLTrick = + ((Array.from(structDB.entries()).reduce((a, [hex]) => a + hex.length, 0) + 7) >>> 3) + + loadStructCount + // addi rReg, rData, off + (stackFrameSize > 0 ? 0 : 2) + + (useSharedCall ? 0 : 1) + + 3; // stw, mflr, lwz + const useBLTrick = sizeWithBLTrick < sizeWithoutBLTrick; + + /** @type {Map}>} */ + const offFuncs = new Map(); + /** @type {number|null} */ + let offCall = null; + /** @type {Map} */ + const offStructs = new Map(); + + if (useSharedCall) { + let off = 0; + /** @type {string[]} */ + const funcHexs = []; + for (const [addr, prepCounts] of callCounts.entries()) { + // put repeated call only + if (Array.from(prepCounts).reduce((a, [k, c]) => a + c, 0) <= 1) continue; + /** @type {Map} */ + const preps = new Map(); + const prepKeys = Array.from(prepCounts.keys()).filter((k) => k !== ''); + let hex = ''; + // TODO optimize only when one prep (excluding '') is used + if (prepKeys.length === 1) { + const [prep] = prepKeys; + preps.set(prep, off); + hex += prep; + } + offFuncs.set(addr, { fallback: off + hex.length / 2, preps }); + // liDX addr + hex += insts2hex(liDX(rAddr, addr)); + // b call + off += 4 + hex.length / 2; + // push + funcHexs.push(hex); + } + const offDst = Math.max(0, off - 4); + offCall = offDst; + + // make data + /** callX: */ + funcHexs.forEach((hex, i, arr) => { + p.pushHex(hex); + // b call # except the last 1 + if (i < arr.length - 1) { + p.b(offDst); + } + }); + /** call: */ + p.push(ASM.mtctr(rAddr), ASM.bctr()); + } + + // add struct data + if (useBLTrick) { + // [4-byte aligned data, chars data] + const [aligned, chars] = splitArray(structDB, (hex) => hex.length % 8 === 0); + for (const data of [aligned, chars]) { + for (const hex of data) { + offStructs.set(hex, p.pc); + p.pushHex(hex); + } + } + // make 4-byte alignment + p.align(); + } + + // make body + const dataSize = p.pc; + /** mflr rData */ + if (useBLTrick) p.push(ASM.mflr(rData)); + /** for each ASM instructions */ + for (const inst of insts) { + if (typeof inst === 'number') { + p.push(inst); + } else if (inst.type === 'call') { + const { prep = [], addr } = inst; + const prepKey = insts2hex(prep); + const off = offFuncs.get(addr); + if (off == null) { + // fallback to prepare and load addr manually + p.push(...prep, ...liDX(rAddr, addr)); + // call + if (offCall == null) { + p.push( + // mtctr rAddr + ASM.mtctr(rAddr), + // bctrl + ASM.bctr(true), + ); + } else { + p.bl(offCall); + } + } else { + // bl to callX directly + const { fallback, preps } = off; + const dst = preps.get(prepKey); + if (dst == null) { + // fallback to prepare manually + p.pushHex(prepKey); + p.bl(fallback); + } else { + // bl to dst directly + p.bl(dst); + } + } + } else if (inst.type === 'struct') { + const { reg, hex } = inst; + const off = offStructs.get(hex); + if (off == null) { + // fallback to use BL trick here + /** bl L */ + const d = ((hex.length + 7) >> 3) << 2; + p.push(ASM.b(4 + d, true)); + /** (data) */ + p.pushHex(hex); + p.align(); + /** L: mflr rReg */ + p.push(ASM.mflr(reg)); + } else { + // use addi directly + p.push(ASM.addi(reg, rData, off)); + } + } + } + + /** @type {Inst[]} */ + const prologue = []; + if (useBLTrick) stackFrameSize += 4; // for r31 + if (stackFrameSize > 0) { + // stack frame size: 16-byte align + stackFrameSize = ((stackFrameSize + 0xf) >> 4) << 4; + // stwu r1 + prologue.push(ASM.stwu(1, 1, -stackFrameSize)); + if (useBLTrick) { + // stw r31 + prologue.push(ASM.stw(31, 1, stackFrameSize - 4)); + } + } + if (useSharedCall || useBLTrick) { + prologue.push(ASM.b(4 + dataSize, true)); + } + + /** @type {Inst[]} */ + const epilogue = []; + if (stackFrameSize > 0) { + if (useBLTrick) { + // lwz r31 + epilogue.push(ASM.lwz(31, 1, stackFrameSize - 4)); + } + // addi r1 + epilogue.push(ASM.addi(1, 1, stackFrameSize)); + } + + return insts2hex(prologue) + p.hex + insts2hex(epilogue); +} diff --git a/site/.vuepress/components/codes/CustomizedDisplay/codegen.js b/site/.vuepress/components/codes/CustomizedDisplay/codegen.js index e34297e..c24a1bb 100644 --- a/site/.vuepress/components/codes/CustomizedDisplay/codegen.js +++ b/site/.vuepress/components/codes/CustomizedDisplay/codegen.js @@ -1,31 +1,25 @@ import { parseJSON } from '../codegen.js'; -import { ASM, makeInst, liDX, str2inst, makeProgram, inst2gecko } from '../asm.js'; +import { ASM, liDX, str2inst, makeProgram, inst2gecko, getFillRectParams } from '../asm.js'; +import { measureText } from '../text.js'; +import { addrs } from '../addrs.js'; +import { parseFormat } from './format.js'; +import { assemble } from './assembler.js'; +import { drawText, fillRect } from './functions.js'; export const lskey = 'config/CustomizedDisplay'; -export const defaultConfig = [ - { - x: 16, - y: 192, - fontSize: 18, - fgRGB: 0xffffff, - fgA: 0xff, - fgRGB2: null, - fgA2: null, - fmt: `X -Y -Z -A -H -V -QF `, - }, -]; +import configDB from './configDB.js'; +export const defaultConfig = [configDB.PAS]; +/** @type {(...args: Parameters) => string} */ +export const format2previewText = (input, version) => parseFormat(input, version).preview; + +/** @typedef {'GMSJ01'|'GMSJ0A'|'GMSE01'|'GMSP01'} GameVersion */ /** @param {GameVersion} version */ export function getConfig(version) { /** @type {typeof defaultConfig} */ const config = typeof localStorage !== 'undefined' && parseJSON(localStorage.getItem(lskey)); return (config instanceof Array ? config : defaultConfig).map(({ fmt, ...o }) => ({ + ...defaultConfig[0], ...o, fmt, text: format2previewText(fmt, version), @@ -33,412 +27,47 @@ export function getConfig(version) { } /** - * @typedef {number[]} Inst - * @typedef {8|16|32|'float'} DataType - * @typedef {(gpr: number)=>Inst} GPRHandler -- (src=gpr, dst=gpr) - * @typedef {{type: 'gpr'|'fpr'|'sp', index: number}} Dst - * @typedef {'GMSJ01'|'GMSJ0A'|'GMSE01'|'GMSP01'} GameVersion - * - * @typedef {{ - * offset: number - * dtype: DataType - * post?: GPRHandler - * }} FieldInfo - * - * @typedef {{ - * id: string - * pre: GPRHandler - * }} Base - * - * @typedef {{ - * pre: GPRHandler - * fields: {info: FieldInfo, dst: Dst}[] - * }} Entry - */ - -/** @typedef {{[ver in GameVersion]: GPRHandler}} VBase */ -const bases = { - gpMarioOriginal: /**@type{VBase}*/ ({ - GMSJ01: (rT) => ASM.lwz(rT, 13, -0x6748), - GMSE01: (rT) => ASM.lwz(rT, 13, -0x60d8), - GMSP01: (rT) => ASM.lwz(rT, 13, -0x61b0), - GMSJ0A: (rT) => ASM.lwz(rT, 13, -0x6218), - }), - gpMarDirector: /**@type{VBase}*/ ({ - GMSJ01: (rT) => ASM.lwz(rT, 13, -0x6818), - GMSE01: (rT) => ASM.lwz(rT, 13, -0x6048), - GMSP01: (rT) => ASM.lwz(rT, 13, -0x6120), - GMSJ0A: (rT) => ASM.lwz(rT, 13, -0x6188), - }), - gpCamera: /**@type{VBase}*/ ({ - GMSJ01: (rT) => ASM.lwz(rT, 13, -0x5750), - GMSE01: (rT) => ASM.lwz(rT, 13, -0x7118), - GMSP01: (rT) => ASM.lwz(rT, 13, -0x7158), - GMSJ0A: (rT) => ASM.lwz(rT, 13, -0x5768), - }), -}; -/** @typedef {keyof typeof bases} BaseId */ - -/** @type {({id: string, base: BaseId, fmt: string, preview: number} & FieldInfo)[]} */ -const fields = [ - { id: 'x', base: 'gpMarioOriginal', dtype: 'float', offset: 0x10, fmt: '%.0f', preview: 426.39 }, - { id: 'y', base: 'gpMarioOriginal', dtype: 'float', offset: 0x14, fmt: '%.0f', preview: -427.39 }, - { id: 'z', base: 'gpMarioOriginal', dtype: 'float', offset: 0x18, fmt: '%.0f', preview: 428.39 }, - { id: 'angle', base: 'gpMarioOriginal', dtype: 16, offset: 0x96, fmt: '%hu', preview: 1207 }, - { - id: 'HSpd', - base: 'gpMarioOriginal', - dtype: 'float', - offset: 0xb0, - fmt: '%.2f', - preview: 15.15, - }, - { - id: 'VSpd', - base: 'gpMarioOriginal', - dtype: 'float', - offset: 0xa8, - fmt: '%.2f', - preview: -31.17, - }, - { - id: 'QF', - base: 'gpMarDirector', - dtype: 32, - offset: 0x58, - fmt: '%u', - preview: 0, - post: (rT) => ASM.rlwinm(rT, rT, 0, 30, 31, false), - }, - { - id: 'CAngle', - base: 'gpCamera', - dtype: 16, - offset: 0xa6, - fmt: '%hu', - preview: 9, - post: (rT) => ASM.addi(rT, rT, -0x8000), // offset by 0x8000 - }, -]; -const fieldDB = Object.fromEntries( - fields.map(({ id, base, fmt, preview, ...info }) => [ - id.toLowerCase(), - { base, info, fmt, preview }, - ]), -); - -const store = { - 8: ASM.stb, - 16: ASM.sth, - 32: ASM.stw, - float: ASM.stfs, - double: ASM.stfd, -}; -const load = { - 8: ASM.lbz, - 16: ASM.lhz, - 32: ASM.lwz, - float: ASM.lfs, -}; - -/** - * @param {number} x - * @param {number} y - * @param {number} fontSize - * @param {number} colorTop - * @param {number} colorBot - */ -export function prepareDrawText(x, y, fontSize, colorTop, colorBot) { - let gpr = 9; - let fpr = 1; - let sp = 8; - let fmt = ''; - let hasFloat = false; - /** @type {{[id: string]: Entry}} */ - const entries = {}; - - /** @returns {Dst} */ - function allocInt() { - if (gpr <= 10) { - return { type: 'gpr', index: gpr++ }; - } else { - /** @type {Dst} */ - const dst = { type: 'sp', index: sp }; - sp += 4; - return dst; - } - } - /** @returns {Dst} */ - function allocFloat() { - hasFloat = true; - if (fpr <= 8) { - return { type: 'fpr', index: fpr++ }; - } else { - sp += sp & 4; // align 8 - /** @type {Dst} */ - const dst = { type: 'sp', index: sp }; - sp += 8; - return dst; - } - } - /** @param {Base} base */ - const getEntry = (base) => - entries[base.id] ?? - (entries[base.id] = { - pre: base.pre, - fields: [], - }); - - return { - /** - * @param {string} format - * @param {Base} base - * @param {FieldInfo} field - */ - pushValue(format, base, field) { - fmt += format; - getEntry(base).fields.push({ - info: field, - dst: (field.dtype === 'float' ? allocFloat : allocInt)(), - }); - }, - /** - * @param {string} text - */ - pushText(text) { - fmt += text.replace(/%/g, '%%'); - }, - makeCode() { - /** @type {Inst[]} */ - const insts = []; - // sp - const spAdd = sp === 8 ? 0 : ((sp >> 4) + (sp & 0xf ? 1 : 0)) << 4; - // params - for (const { pre, fields: params } of Object.values(entries)) { - // load base to gpr - const rBase = 3; - insts.push(pre(rBase)); - // load all params - const rField = 5; - const fField = 9; - for (const { - info: { offset: srcoff, dtype, post }, - dst, - } of params) { - if (dst.type === 'sp') { - const dstoff = dst.index; - if (dtype === 'float') { - insts.push( - // lfs fField, offset(rBase) - load.float(fField, rBase, srcoff), - // post - post?.(fField) ?? [], - // stfd fField, dst.index(r1) - store.double(fField, 1, dstoff), - ); - } else { - insts.push( - // load rField, offset(rBase) - load[dtype](rField, rBase, srcoff), - // post - post?.(rField) ?? [], - // stw rField, dst.index(r1) - store[32](rField, 1, dstoff), - ); - } - } else { - // load to register - const { index: rDst } = dst; - insts.push( - // load rDst - load[dtype](rDst, rBase, srcoff), - // post - post?.(rDst) ?? [], - ); - } - } - } - // r8 = fmt - const fmtbuf = str2inst(fmt); - insts.push( - // bl 4+len4(fmt) - ASM.b(4 + (fmtbuf.length << 2), true), - // .string fmt - fmtbuf, - // mflr r8 - ASM.mflr(8), - ); - /* - * r3 = x - * r4 = y - * r5 = fontSize - * r6 = colorTop - * r7 = colorBot - */ - insts.push( - liDX(3, x), - liDX(4, y), - liDX(5, fontSize), - liDX(6, colorTop), - colorTop === colorBot ? ASM.mr(7, 6) : liDX(7, colorBot), - ); - // cr{set|clr} 6 - insts.push((hasFloat ? ASM.crset : ASM.crclr)(6)); - // DONE - return { code: insts.flatMap((e) => e), spNeed: spAdd }; - }, - }; -} - -const dtype2fmtinfo = { - 8: { prefix: 'hh', mask: 0xff }, - 16: { prefix: 'h', mask: 0xffff }, - 32: { prefix: '', mask: 0xffffffff }, -}; - -/** - * @param {string} input - * @param {GameVersion} version - * @param {ReturnType|null} f - */ -export function format2previewText(input, version, f = null) { - const regex = /<(.*?)>/g; - let preview = ''; - /** @type {RegExpExecArray|null} */ - let m = null; - let i0 = 0; - while ((m = regex.exec(input))) { - const { index: i } = m; - // text - const text = input.slice(i0, i); - f?.pushText(text); - preview += text; - // arg - const [fieldId, fmt0, pvw0] = m[1].split('|'); - const field = fieldDB[fieldId.toLowerCase()]; - if (field) { - const { base: baseId, info, fmt: fmt1, preview: pvw1 } = field; - const { dtype } = info; - const fmt2 = fmt0 || fmt1; - let ipvw = +pvw0; - if (!pvw0 || !isFinite(ipvw)) ipvw = pvw1; - let fmt; - let pvw; - let padfmt = ''; - if (dtype === 'float') { - const m = fmt2.trim().match(/^(?:%?(\d*)\.)?(\d+)([eEf]?)$/); - padfmt = m?.[1] || ''; - const digit = +(m?.[2] || 0); - const suffix = m?.[3] || 'f'; - fmt = `%${padfmt}.${digit}${suffix}`; - pvw = ipvw[suffix === 'f' ? 'toFixed' : 'toExponential'](digit); - if (suffix === 'E') pvw = pvw.toUpperCase(); - } else { - const { prefix, mask } = dtype2fmtinfo[dtype]; - ipvw &= mask; - const m = fmt2.trim().match(/^%?(\d*)h{,2}([dioxXu])$/); - padfmt = m?.[1] || ''; - const t = m?.[2] || 'u'; - fmt = `%${padfmt}${prefix}${t}`; - if ('di'.includes(t)) { - if (ipvw > mask >>> 1) ipvw -= mask; - pvw = ipvw.toString(10); - } else if (t === 'o') { - pvw = (ipvw >>> 0).toString(8); - } else if ('xX'.includes(t)) { - pvw = (ipvw >>> 0).toString(16); - } else { - pvw = (ipvw >>> 0).toString(10); - } - } - pvw = pvw.padStart(+padfmt, padfmt[0] === '0' ? '0' : ' '); - f?.pushValue(fmt, { id: baseId, pre: bases[baseId][version] }, info); - preview += pvw; - } else { - // fail to parse - f?.pushText(m[0]); - preview += m[0]; - } - // next - i0 = i + m[0].length; - } - const text = input.slice(i0); - f?.pushText(text); - preview += text; - // DONE - return preview; -} - -const addrsOrig = { - GMSJ01: 0x80206a00 - 0x2c, - GMSJ0A: 0x8012556c - 0x2c, - GMSE01: 0x801441e0 - 0x2c, - GMSP01: 0x80138e1c - 0x2c, -}; -const addrsSetup2D = { - GMSJ01: 0x80035228, - GMSJ0A: 0x802caecc, - GMSE01: 0x802eb6bc, - GMSP01: 0x802e3864, -}; -const addrDrawText = 0x817f0238; -const addrDst = 0x817fa000; - -/** + * @typedef {Parameters[0][number]} ASMInst * @param {GameVersion} version */ export default function codegen(version) { - const config = getConfig(version); + const configs = getConfig(version); - let spOff = 0; - const fcodes = /** @type {Inst[]} */ ([]); + let stackFrameSize = 0; - for (const { x, y, fontSize, fgRGB, fgA, fgRGB2, fgA2, fmt } of config) { - // color - const colorTop = (fgRGB << 8) | fgA; - const colorBot = fgRGB2 == null || fgA2 == null ? colorTop : (fgRGB2 << 8) | fgA; - // prepare drawText - const f = prepareDrawText(x, y, fontSize, colorTop, colorBot); - format2previewText(fmt, version, f); - // update code and sp - const { code, spNeed } = f.makeCode(); - spOff = Math.max(spOff, spNeed); - fcodes.push(code); + /** @type {ASMInst[]} */ + const asm = []; + + for (const config of configs) { + const { fmt: fmtRaw, bgA } = config; + const { preview, format, fields } = parseFormat(fmtRaw, version); + + // fill_rect + if (bgA) { + asm.push(...fillRect(version, config, measureText(preview, version))); + } + + // drawText + if (format.trim()) { + const { insts, sp } = drawText(version, config, format, fields); + stackFrameSize = Math.max(stackFrameSize, sp); + asm.push(...insts); + } } - const addrOrig = addrsOrig[version]; - const addrSetup2D = addrsSetup2D[version]; + let body = assemble(asm, stackFrameSize); + // align code + if (body.length % 16 === 0) body += '60000000'; + body += '00000000'; - // program - const program = makeProgram(addrDst); - // addi r3, r1, 0xE90 - program.push(ASM.addi(3, 1, 0xe90)); - // addi r1, r1, -spOff - if (spOff) program.push(ASM.addi(1, 1, -spOff)); - // bl setup - program.bl(addrSetup2D); - // (drawText) - for (const code of fcodes) { - program.push(code); - program.bl(addrDrawText); - } - // addi r1, r1, spOff - if (spOff) program.push(ASM.addi(1, 1, spOff)); - // b orig+4 - program.b(addrOrig + 4); - - // dump code - const pcode = program.dump(); - const psize = pcode.length; - return [ - makeInst((0xc6 << 24) | (addrOrig & 0x1ffffff)), - makeInst(addrDst), - makeInst((0x06 << 24) | (addrDst & 0x1fffffff)), - makeInst(psize << 2), - pcode, - psize & 1 ? [0] : [], - ] - .flatMap((e) => e) - .map(inst2gecko) - .join(''); + const addrDst = addrs.drawWater[version] - 0x2c; // [-0x30, -0x18] + return ( + [ + 0xc2000000 | (addrDst & 0x1fffffff), + body.length >>> 4, // 16 hex-digits per line + ] + .flatMap((e) => e) + .map(inst2gecko) + .join('') + body + ); } diff --git a/site/.vuepress/components/codes/CustomizedDisplay/config.vue b/site/.vuepress/components/codes/CustomizedDisplay/config.vue index 19a095b..c07a125 100644 --- a/site/.vuepress/components/codes/CustomizedDisplay/config.vue +++ b/site/.vuepress/components/codes/CustomizedDisplay/config.vue @@ -1,20 +1,27 @@ diff --git a/site/.vuepress/components/codes/TextConfig.vue b/site/.vuepress/components/codes/TextConfig.vue index c420645..e54d120 100644 --- a/site/.vuepress/components/codes/TextConfig.vue +++ b/site/.vuepress/components/codes/TextConfig.vue @@ -15,6 +15,23 @@ {{l.fgColor2}} {{l.alpha}}/255={{(fgA2/2.55).toFixed(1)}}% +
+
+ {{ l.bgColor }} + {{ l.alpha }}/255={{ (bgA / 2.55).toFixed(1) }}% +
+
+ {{ l.bgOffset }} + {{ l.left }} + {{ l.right }} + {{ l.top }} + {{ l.bottom }} +
+
@@ -41,6 +58,7 @@ export default { }, ...Object.fromEntries([ 'x', 'y', 'fontSize', 'fgRGB', 'fgA', 'fgRGB2', 'fgA2', + 'bgRGB', 'bgA', 'bgLeft', 'bgRight', 'bgTop', 'bgBot', ].map(k => [k, makeField(k)])), }, methods: { @@ -72,7 +90,7 @@ input[type=number], td.right { text-align: right; } input[type="number"] { - width: 3em; + width: 2em; margin: 0 2px; } .appearance > div { diff --git a/site/.vuepress/components/codes/addrs.js b/site/.vuepress/components/codes/addrs.js new file mode 100644 index 0000000..04636a8 --- /dev/null +++ b/site/.vuepress/components/codes/addrs.js @@ -0,0 +1,68 @@ +export const addrs = { + drawText: 0x817f0238, + drawWater: { + GMSJ01: 0x80206a00, + GMSJ0A: 0x8012556c, + GMSE01: 0x801441e0, + GMSP01: 0x80138e1c, + }, + fillRect: { + GMSJ01: 0x80201ea8, + GMSJ0A: 0x80121660, + GMSE01: 0x80140390, + GMSP01: 0x80134f0c, + }, + setup2D: { + GMSJ01: 0x80035228, + GMSJ0A: 0x802caecc, + GMSE01: 0x802eb6bc, + GMSP01: 0x802e3864, + }, + getPollutionDegree: { + GMSJ01: 0x801ef6b8, + GMSE01: 0x8019db20, + GMSP01: 0x801963a8, + GMSJ0A: 0x8017e26c, + }, + checkStickRotate: { + GMSJ01: 0x80130758, + GMSE01: 0x80251304, + GMSP01: 0x80249090, + GMSJ0A: 0x80231054, + }, +}; + +export const r13offs = { + gpMarioOriginal: { + GMSJ01: -0x6748, + GMSE01: -0x60d8, + GMSP01: -0x61b0, + GMSJ0A: -0x6218, + }, + gpMarDirector: { + GMSJ01: -0x6818, + GMSE01: -0x6048, + GMSP01: -0x6120, + GMSJ0A: -0x6188, + }, + gpCamera: { + GMSJ01: -0x5750, + GMSE01: -0x7118, + GMSP01: -0x7158, + GMSJ0A: -0x5768, + }, + gpPollution: { + GMSJ01: -0x6518, + GMSE01: -0x62f0, + GMSP01: -0x63c8, + GMSJ0A: -0x6430, + }, +}; + +// r1 offset of J2DGrafContext in TGCConsole2::perform() +export const ctxSpOff = { + GMSJ01: 0xe90, + GMSJ0A: 0xbec, + GMSE01: 0xbd0, + GMSP01: 0xbe4, +}; diff --git a/site/.vuepress/components/codes/asm.js b/site/.vuepress/components/codes/asm.js index 6117066..daf4665 100644 --- a/site/.vuepress/components/codes/asm.js +++ b/site/.vuepress/components/codes/asm.js @@ -1,7 +1,9 @@ -import * as Encoding from 'encoding-japanese'; +import charInfoJP from '../../data/charInfo-JP.json'; +import charInfoEU from '../../data/charInfo-EU.json'; +import charInfoUS from '../../data/charInfo-US.json'; /** - * @typedef {number[]} Inst + * @typedef {number} Inst * * @typedef {( * rT: number, @@ -27,7 +29,7 @@ import * as Encoding from 'encoding-japanese'; * rT: number, * rA: number, * rB: number, - * Rc: number|boolean, + * Rc?: number|boolean, * ) => Inst} InstX * @typedef {( * rS: number, @@ -43,13 +45,6 @@ import * as Encoding from 'encoding-japanese'; * ) => Inst} InstI */ -/** @param {number} inst */ -export const makeInst = (inst) => { - // const buf = Inst.alloc(4); - // buf.writeUint32BE(inst >>> 0); - // return buf; - return [inst]; -}; /** * @param {number} op * @param {number} rT @@ -57,7 +52,7 @@ export const makeInst = (inst) => { * @param {number} D */ const InstD = (op, rT, rA, D) => - makeInst(((op & 0x3f) << 26) | ((rT & 0x1f) << 21) | ((rA & 0x1f) << 16) | (D & 0xffff)); + ((op & 0x3f) << 26) | ((rT & 0x1f) << 21) | ((rA & 0x1f) << 16) | (D & 0xffff); /** * @param {number} op * @param {number} rT @@ -67,14 +62,12 @@ const InstD = (op, rT, rA, D) => * @param {number} Rc */ const InstX = (op, rT, rA, rB, op2, Rc) => - makeInst( - ((op & 0x3f) << 26) | - ((rT & 0x1f) << 21) | - ((rA & 0x1f) << 16) | - ((rB & 0x1f) << 11) | - ((op2 & 0x3ff) << 1) | - Rc, - ); + ((op & 0x3f) << 26) | + ((rT & 0x1f) << 21) | + ((rA & 0x1f) << 16) | + ((rB & 0x1f) << 11) | + ((op2 & 0x3ff) << 1) | + Rc; /** * @param {number} op * @param {number} RS @@ -85,15 +78,13 @@ const InstX = (op, rT, rA, rB, op2, Rc) => * @param {number} Rc */ const InstM = (op, RA, RS, SH, MB, ME, Rc) => - makeInst( - ((op & 0x3f) << 26) | - ((RS & 0x1f) << 21) | - ((RA & 0x1f) << 16) | - ((SH & 0x1f) << 11) | - ((MB & 0x1f) << 6) | - ((ME & 0x1f) << 1) | - Rc, - ); + ((op & 0x3f) << 26) | + ((RS & 0x1f) << 21) | + ((RA & 0x1f) << 16) | + ((SH & 0x1f) << 11) | + ((MB & 0x1f) << 6) | + ((ME & 0x1f) << 1) | + Rc; /** * @param {number} op * @param {number} LL @@ -101,14 +92,17 @@ const InstM = (op, RA, RS, SH, MB, ME, Rc) => * @param {number} LK */ const InstI = (op, LL, AA, LK) => - makeInst(((op & 0x3f) << 26) | ((LL & 0xffffff) << 2) | ((AA & 1) << 1) | (LK & 1)); + ((op & 0x3f) << 26) | ((LL & 0xffffff) << 2) | ((AA & 1) << 1) | (LK & 1); /** @type {(op: number) => InstD} */ const makeInstD = (op) => (rT, rA, D) => InstD(op, rT, rA, D); /** @type {(op: number) => InstDS} */ const makeInstDS = (op) => (rA, rS, D) => InstD(op, rA, rS, D); /** @type {(op: number, op2: number) => InstX} */ -const makeInstX = (op, op2) => (rT, rA, rB, Rc) => InstX(op, rT, rA, rB, op2, +Rc); +const makeInstX = + (op, op2) => + (rT, rA, rB, Rc = 0) => + InstX(op, rT, rA, rB, op2, +Rc); /** @type {(op: number, op2: number) => InstXS} */ const makeInstXS = (op, op2) => (rA, rS, rB, Rc) => InstX(op, rA, rS, rB, op2, +Rc); /** @type {(op: number) => InstM} */ @@ -130,8 +124,12 @@ export const ASM = { // load rS, rA, D lbz: makeInstD(34), lhz: makeInstD(40), + lha: makeInstD(42), lwz: makeInstD(32), lfs: makeInstD(48), + lfd: makeInstD(50), + // add + add: makeInstX(31, 266), // li rT, D addi: makeInstD(14), li: (/**@type{number}*/ rT, /**@type{number}*/ D) => InstD(14, rT, 0, D), @@ -144,8 +142,10 @@ export const ASM = { mr: (/**@type{number}*/ rT, /**@type{number}*/ rA, flag = 0) => InstX(31, rA, rT, rA, 444, flag), // mask rlwinm: makeInstM(21), + rlwimi: makeInstM(20), // b b: makeInstI(18), + bctr: (/**@type{number|boolean}*/ LK = 0) => InstX(19, 0b10100, 0, 0, 528, LK ? 1 : 0), // mflr mflr: (/**@type{number}*/ rT) => InstX(31, rT, 8, 0, 339, 0), mfctr: (/**@type{number}*/ rT) => InstX(31, rT, 9, 0, 339, 0), @@ -155,6 +155,26 @@ export const ASM = { // cr crset: (/**@type{number}*/ B) => InstX(19, B, B, B, 289, 0), crclr: (/**@type{number}*/ B) => InstX(19, B, B, B, 193, 0), + // float + fmr: (/**@type{number}*/ fT, /**@type{number}*/ fB, Rc = 0) => InstX(63, fT, 0, fB, 72, Rc), +}; + +export const $load = { + 8: ASM.lbz, + 16: ASM.lhz, + 32: ASM.lwz, + [-16]: ASM.lha, + [-32]: ASM.lwz, + float: ASM.lfs, +}; +export const $store = { + 8: ASM.stb, + 16: ASM.sth, + 32: ASM.stw, + [-16]: ASM.sth, + [-32]: ASM.stw, + float: ASM.stfs, + double: ASM.stfd, }; /** @@ -163,26 +183,50 @@ export const ASM = { */ export function liDX(rT, D) { if (-0x8000 <= D && D < 0x8000) { - return ASM.li(rT, D); + return [ASM.li(rT, D)]; } else if ((D & 0xffff) === 0) { - return ASM.lis(rT, D >>> 16); + return [ASM.lis(rT, D >>> 16)]; } else { const h = D >>> 16; const l = D & 0xffff; - return [...ASM.lis(rT, h), ...ASM.ori(rT, rT, l)]; + return [ASM.lis(rT, h), ASM.ori(rT, rT, l)]; } } -/** @param {string} s */ -export function strlen(s) { - const fmtbuf = Encoding.convert(Encoding.stringToCode(s), 'SJIS'); - return fmtbuf.length; // not NUL terminated +/** + * @param {string} s + * @param {string} version + */ +export function str2bytes(s, version) { + /** @type {Record} */ + const charInfo = version.startsWith('GMSJ') + ? charInfoJP + : version === 'GMSE01' + ? charInfoUS + : charInfoEU; + const fmtbuf = Array.from(s).flatMap((c) => { + const code = charInfo[c]?.code ?? c.charCodeAt(0); // TODO multi-byte invalid char + return code >= 0x100 ? [code >> 8, code & 0xff] : [code]; + }); + fmtbuf.push(0); // NUL terminated + return fmtbuf; } -/** @param {string} s */ -export function str2inst(s) { - const fmtbuf = Encoding.convert(Encoding.stringToCode(s), 'SJIS'); - fmtbuf.push(0); // NUL terminated +/** + * @param {string} s + * @param {string} version + */ +export const str2hex = (s, version) => + str2bytes(s, version) + .map((x) => x.toString(16).toUpperCase().padStart(2, '0')) + .join(''); + +/** + * @param {string} s + * @param {string} version + */ +export function str2inst(s, version) { + const fmtbuf = str2bytes(s, version); const fmtlen = fmtbuf.length; const fmtlen3 = fmtlen & 3; const pad = fmtlen3 ? 4 - fmtlen3 : 0; @@ -194,32 +238,90 @@ export function str2inst(s) { return insts; } -/** @param {number} pc */ -export function makeProgram(pc) { - /** @type {Inst[]} */ - const bufs = []; - return { - pc, - /** - * @param {number} dst - * @param {boolean} LL - */ - b(dst, LL = false) { - // TODO check overflow - this.push(ASM.b(dst - this.pc, LL)); - }, - /** @param {number} dst */ - bl(dst) { - this.b(dst, true); - }, - /** @param {Inst[]} codes */ - push(...codes) { - bufs.push(...codes); - this.pc += codes.reduce((a, e) => a + e.length, 0) << 2; - }, - dump: () => bufs.flatMap((e) => e), - }; -} +/** + * @param {number} pc + * @param {string} [hex] + */ +export const makeProgram = (pc, hex = '') => ({ + pc, + hex, + /** + * @param {number} dst + * @param {boolean} LL + */ + b(dst, LL = false) { + // TODO check overflow + this.push(ASM.b(dst - this.pc, LL)); + }, + /** @param {number} dst */ + bl(dst) { + this.b(dst, true); + }, + /** @param {Inst[]} codes */ + push(...codes) { + this.hex += codes.map(inst2gecko).join(''); + this.pc += codes.length << 2; + }, + /** @param {string} data */ + pushHex(data) { + this.hex += data; + this.pc += data.length >> 1; + }, + align() { + const l4 = this.pc % 4; + if (l4) { + const diff = 4 - l4; + this.hex += ''.padEnd(diff << 1, '0'); + this.pc += diff; + } + }, +}); /** @param {number} x */ export const inst2gecko = (x) => (x >>> 0).toString(16).toUpperCase().padStart(8, '0'); +/** @param {Inst[]} insts */ +export const insts2hex = (insts) => insts.map(inst2gecko).join(''); + +/** + * @param {{ + * x: number, + * y: number, + * fontSize: number, + * bgRGB: number, + * bgA: number, + * bgLeft: number, + * bgRight: number, + * bgTop: number, + * bgBot: number + * }} opt + * @param {{width: number, height: number}} size + **/ +export const getFillRectParams = ( + { x, y, fontSize, bgRGB, bgA, bgLeft, bgRight, bgTop, bgBot }, + { width, height }, +) => [ + // rect + x - bgLeft, // x0 + y - fontSize - bgTop, // y0 + x + Math.ceil((width * fontSize) / 20) + bgRight, // x1 + y - fontSize + Math.ceil((height * fontSize) / 20) + bgBot, // y1 + // color + (bgRGB << 8) | bgA, +]; + +/** + * @param {{ + * x: number, + * y: number, + * fontSize: number, + * fgRGB: number + * fgA: number + * fgRGB2: number | null + * fgA2: number | null + * }} config + */ +export function getDrawTextOpt({ x, y, fontSize, fgRGB, fgA, fgRGB2, fgA2 }) { + const colorTop = (fgRGB << 8) | fgA; + const colorBot = fgRGB2 == null || fgA2 == null ? colorTop : (fgRGB2 << 8) | fgA; + return [((x & 0xffff) << 16) | (y & 0xffff), fontSize, colorTop, colorBot]; +} diff --git a/site/.vuepress/components/codes/codegen.js b/site/.vuepress/components/codes/codegen.js index f98a2e0..4ee4139 100644 --- a/site/.vuepress/components/codes/codegen.js +++ b/site/.vuepress/components/codes/codegen.js @@ -1,13 +1,19 @@ import InstantRestart from './InstantRestart/codegen.js'; import qft from './qft/codegen.js'; +import qfst from './qfst/codegen.js'; import CustomizedDisplay from './CustomizedDisplay/codegen.js'; import PatternSelector from './PatternSelector/codegen.js'; +import AttemptCounter from './AttemptCounter/codegen.js'; +import controller from './controller/codegen.js'; export default { InstantRestart, qft, + qfst, CustomizedDisplay, PatternSelector, + AttemptCounter, + controller, }; /** diff --git a/site/.vuepress/components/codes/controller/codegen.js b/site/.vuepress/components/codes/controller/codegen.js new file mode 100644 index 0000000..068e7ce --- /dev/null +++ b/site/.vuepress/components/codes/controller/codegen.js @@ -0,0 +1,106 @@ +import { parseJSON } from '../codegen.js'; +import { float2hex, int2hex } from '../utils.js'; +import hiddenConfig from './hidden.js'; +import { SHIFTS, makeRect, makeNgon, makeTriggerInfo } from './utils.js'; +export const lskey = 'config/controller'; + +export const defaultConfig = { + x: 16, + y: 314, + lw: 20, + height: 120, + bgRGB: 0, + bgA: 0x7f, +}; + +/** @returns {typeof defaultConfig & typeof hiddenConfig} */ +export function getConfig() { + const config = + (typeof localStorage !== 'undefined' && parseJSON(localStorage.getItem(lskey))) || {}; + return { + ...defaultConfig, + ...config, + ...hiddenConfig, + }; +} + +/** + * @param {keyof typeof import('../addrs.js').ctxSpOff} version + * @param {string=} baseCode + */ +export default function codegen(version, baseCode) { + if (!baseCode) return ''; + + const { + x, + y, + lw, + height, + bgRGB, + bgA, + bgLeft, + bgRight, + bgTop, + bgBot, + buttons, + cTF, + cTS, + triggers, + sticks, + } = getConfig(); + const logQ = 6; + + let code = baseCode; + code += '077F04C3 0000007D'; + + // basic config + code += [ + // lw + int2hex(lw, 1), + // mtx.scale + float2hex((2 ** -logQ * height) / 120), + // mtx.x + int2hex(x, 2), + // mtx.y + int2hex(y - 16, 2), + // .conf.bg.color + int2hex((bgRGB << 8) | bgA, 4), + // .conf.trigger.fill + int2hex(cTF, 4), + // .conf.trigger.stroke + int2hex(cTS, 4), + ].join(''); + + // background + code += makeRect(bgLeft, bgTop, bgRight, bgBot); + + // buttons + code += buttons.map((c) => makeNgon(c.x, c.y, c.r, SHIFTS[c.id], c.c)).join(''); + + // triggers + code += triggers + .flatMap((c) => [ + // fill + makeRect(c.x, c.y0, c.x + c.w, c.y1), + // info + makeTriggerInfo(SHIFTS[c.id], c.wa), + // stroke + makeRect(c.x, c.y0, c.x + c.w, c.y1), + ]) + .join(''); + + // sticks + code += sticks + .flatMap((c) => [ + // fill + makeNgon(-1, -1, c.rF, c.rMove, c.cF), + // stroke + makeNgon(c.x, c.y, c.rS, -1, c.cS), + ]) + .join(''); + + // padding + code += '000000'; + + return code.replace(/\s/g, ''); +} diff --git a/site/.vuepress/components/codes/controller/config.vue b/site/.vuepress/components/codes/controller/config.vue new file mode 100644 index 0000000..80e1679 --- /dev/null +++ b/site/.vuepress/components/codes/controller/config.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/site/.vuepress/components/codes/controller/hidden.js b/site/.vuepress/components/codes/controller/hidden.js new file mode 100644 index 0000000..812ad2f --- /dev/null +++ b/site/.vuepress/components/codes/controller/hidden.js @@ -0,0 +1,66 @@ +export const buttons = [ + { x: 138, y: 66, r: 18, id: 'A', c: 0x2ee5b8bf }, + { x: 113, y: 89, r: 9, id: 'B', c: 0xff1a1abf }, + { x: 164, y: 50, r: 8, id: 'X', c: 0xeeeeeebf }, + { x: 119, y: 41, r: 8, id: 'Y', c: 0xeeeeeebf }, + { x: 144, y: 34, r: 6, id: 'Z', c: 0x9494ffbf }, + { x: 91, y: 64, r: 5, id: 'S', c: 0xeeeeeebf }, +]; + +export const sticks = [ + { + id: 'M', + x: 32, + y: 52, + rMove: 14, + rS: 19, + cS: 0xeeeeeeef, + rF: 12, + cF: 0xeeeeeeef, + }, + { + id: 'C', + x: 64, + y: 92, + rMove: 14, + rS: 19, + cS: 0xffd300ef, + rF: 12, + cF: 0xffd300ef, + }, +]; + +export const triggers = [ + { + id: 'L', + x: 12, + y0: 10, + y1: 18, + w: 64, + wa: 56, + }, + { + id: 'R', + x: 170, + y0: 10, + y1: 18, + w: -64, + wa: -56, + }, +]; + +export default { + // background + bgLeft: 0, + bgRight: 182, + bgTop: 0, + bgBot: 120, + // trigger fill + cTF: 0xdfdfdfbf, + // trigger stroke + cTS: 0xeeeeeebf, + // input + buttons, + triggers, + sticks, +}; diff --git a/site/.vuepress/components/codes/controller/preview.vue b/site/.vuepress/components/codes/controller/preview.vue new file mode 100644 index 0000000..1c7cbdd --- /dev/null +++ b/site/.vuepress/components/codes/controller/preview.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/site/.vuepress/components/codes/controller/utils.js b/site/.vuepress/components/codes/controller/utils.js new file mode 100644 index 0000000..1fb4c99 --- /dev/null +++ b/site/.vuepress/components/codes/controller/utils.js @@ -0,0 +1,37 @@ +import { int2hex } from '../utils.js'; + +/** @type {Record} */ +export const SHIFTS = { + Z: 32 - 4, + R: 32 - 5, + L: 32 - 6, + A: 32 - 8, + B: 32 - 9, + X: 32 - 10, + Y: 32 - 11, + S: 32 - 12, +}; + +/** + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + */ +export const makeRect = (x0, y0, x1, y1) => [x0, y0, x1, y1].map((x) => int2hex(x, 1)).join(''); + +/** + * @param {number} x + * @param {number} y + * @param {number} r + * @param {number} s + * @param {number} color + */ +export const makeNgon = (x, y, r, s, color) => + [x, y, r, s].map((x) => int2hex(x, 1)).join('') + int2hex(color, 4); + +/** + * @param {number} shift + * @param {number} WA + */ +export const makeTriggerInfo = (shift, WA) => [shift, WA].map((x) => int2hex(x, 1)).join(''); diff --git a/site/.vuepress/components/codes/labels.json b/site/.vuepress/components/codes/labels.json index 7ea4e0b..80dc8ed 100644 --- a/site/.vuepress/components/codes/labels.json +++ b/site/.vuepress/components/codes/labels.json @@ -1,20 +1,60 @@ { "ja-JP": { + "h3": { + "appearance": "見た目" + }, "location": "位置:", "fontSize": "文字サイズ:", "fgColor": "文字色:", "fgColorGrad": "グラデーション", "fgColor1": "文字色(上):", "fgColor2": "文字色(下):", - "alpha": "不透明度=" + "alpha": "不透明度=", + "bgColor": "背景色:", + "bgOffset": "背景位置:", + "size": "サイズ:", + "left": "左", + "right": "右", + "top": "上", + "bottom": "下", + "display": { + "duration": "表示時間:", + "frame": "(フレーム)", + "sec": "(秒)" + } }, "en-US": { + "h3": { + "appearance": "Appearance" + }, "location": "Location: ", "fontSize": "Font size: ", "fgColor": "Font color: ", "fgColorGrad": "Gradient", "fgColor1": "Font color(Top): ", "fgColor2": "Font color(Bottom): ", - "alpha": "Alpha=" + "alpha": "Alpha=", + "bgColor": "Background color: ", + "bgOffset": "Background offset: ", + "size": "Size: ", + "left": "Left", + "right": "Right", + "top": "Top", + "bottom": "Bottom", + "display": { + "duration": "Display duration: ", + "frame": "(frame)", + "sec": "(sec)" + } + }, + "fr-FR": { + "location": "Position : ", + "fontSize": "Taille de police : ", + "fgColor": "Couleur du texte : ", + "fgColorGrad": "Dégradé", + "fgColor1": "Couleur du texte (haut) : ", + "fgColor2": "Couleur du texte (bas) : ", + "bgColor": "Couleur de fond : ", + "alpha": "Alpha = " } } diff --git a/site/.vuepress/components/codes/preview.js b/site/.vuepress/components/codes/preview.js new file mode 100644 index 0000000..5ffa598 --- /dev/null +++ b/site/.vuepress/components/codes/preview.js @@ -0,0 +1,31 @@ +import * as qft from './qft/codegen.js'; +import * as qfst from './qfst/codegen.js'; +import * as CustomizedDisplay from './CustomizedDisplay/codegen.js'; +import * as PatternSelector from './PatternSelector/codegen.js'; +import * as AttemptCounter from './AttemptCounter/codegen.js'; +import * as controller from './controller/codegen.js'; + +export const previewIds = [ + 'CustomizedDisplay', + 'AttemptCounter', + 'PatternSelector', + 'qft', + 'qfst', + 'controller', +]; + +/** + * Get code configs for preview + * @param {keyof typeof import('./addrs.js').ctxSpOff} version + */ +export const getConfigs = (version) => + Object.fromEntries( + Object.entries({ + qft, + qfst, + CustomizedDisplay, + PatternSelector, + AttemptCounter, + controller, + }).map(([k, v]) => [k, v.getConfig(version)]), + ); diff --git a/site/.vuepress/components/codes/qfst/codegen.js b/site/.vuepress/components/codes/qfst/codegen.js new file mode 100644 index 0000000..4526a83 --- /dev/null +++ b/site/.vuepress/components/codes/qfst/codegen.js @@ -0,0 +1,66 @@ +import { parseJSON } from '../codegen.js'; +import { insts2hex, getDrawTextOpt, getFillRectParams } from '../asm'; +import { measureText } from '../text.js'; +export const lskey = 'config/qfst'; + +export const defaultConfig = { + x: 533, + y: 150, + fontSize: 13, + fgRGB: 0xffffff, + fgA: 0xff, + fgRGB2: null, + fgA2: null, + bgRGB: 0x000000, + bgA: 0x40, + bgLeft: 4, + bgRight: 3, + bgTop: 4, + bgBot: 2, +}; + +export const getPreviewText = () => ` 0.426 + 0.427 + 0.428 + 1.515 + 3.117 +39.000 + 9.999 +11.111 +22.222 +33.333 +44.444 +55.555 +66.666 +77.777 +88.888 +99.999`; + +/** @returns {typeof defaultConfig} */ +export function getConfig() { + const config = + (typeof localStorage !== 'undefined' && parseJSON(localStorage.getItem(lskey))) || {}; + return { + ...defaultConfig, + ...config, + text: getPreviewText(), + }; +} + +/** + * @param {keyof typeof import('../addrs.js').ctxSpOff} version + * @param {string=} baseCode + */ +export default function codegen(version, baseCode) { + if (!baseCode) return ''; + + const config = getConfig(); + + let code = baseCode; + code += '077F039C 0000002C'; + code += insts2hex(getFillRectParams(config, measureText(getPreviewText(), version))); + code += insts2hex(getDrawTextOpt(config)); + code += '2532642E 25303364 00000000'; // fmt = "%2d.%03d" + + return code.replace(/\s/g, ''); +} diff --git a/site/.vuepress/components/codes/qfst/config.vue b/site/.vuepress/components/codes/qfst/config.vue new file mode 100644 index 0000000..56d3d65 --- /dev/null +++ b/site/.vuepress/components/codes/qfst/config.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/site/.vuepress/components/codes/qft/codegen.js b/site/.vuepress/components/codes/qft/codegen.js index 88a286f..ad66eba 100644 --- a/site/.vuepress/components/codes/qft/codegen.js +++ b/site/.vuepress/components/codes/qft/codegen.js @@ -1,10 +1,13 @@ import { parseJSON } from '../codegen.js'; +import { getFillRectParams } from '../asm'; +import { int2hex } from '../utils'; export const lskey = 'config/qft'; +export const getPreviewText = () => '0:00.000'; + export const defaultConfig = { x: 16, y: 456, - width: 112, fontSize: 20, fgRGB: 0xffffff, fgA: 0xff, @@ -12,6 +15,10 @@ export const defaultConfig = { fgA2: null, bgRGB: 0x000000, bgA: 0x80, + bgLeft: 0, + bgRight: 2, + bgTop: 2, + bgBot: 0, freezeDuration: 30, freeze: { yellowCoin: false, @@ -35,6 +42,7 @@ export const defaultConfig = { }, }; +/** @returns {typeof defaultConfig} */ export function getConfig() { const config = (typeof localStorage !== 'undefined' && parseJSON(localStorage.getItem(lskey))) || {}; @@ -45,6 +53,7 @@ export function getConfig() { ...defaultConfig.freeze, ...config.freeze, }, + text: getPreviewText(), }; } @@ -57,8 +66,10 @@ import * as GMSP01 from './code/GMSP01.js'; import * as GMSJ0A from './code/GMSJ0A.js'; export const codes = { GMSJ01, GMSE01, GMSP01, GMSJ0A }; -import statusDB from './code/status.js'; -export const statusKeys = Object.keys(statusDB); +import { measureText } from '../text.js'; +import statusDB0 from './code/status.js'; +const statusDB = /**@type{Record}*/ (statusDB0); +export const statusKeys = Object.keys(statusDB0); /**** ## save freeze frame, load and save QF @@ -100,7 +111,7 @@ export default function codegen(version, baseCode) { const hook = freezeCodeHooks[key]; if (hook) { if (key === 'blueCoin') { - const addr = hook; + const addr = /**@type{number}*/ (hook); // special: needs to adjust QF -> use separate C2 instead code += [ 0xc2000000 + (addr & 0x1ffffff), @@ -234,25 +245,24 @@ export default function codegen(version, baseCode) { // ui /* bounds */ - const { x, y, fontSize, width } = config; + const { x, y, fontSize, bgLeft, bgRight, bgTop, bgBot } = config; + const rect = getFillRectParams(config, measureText(getPreviewText(), version)); + const [bgColor] = rect.splice(-1); const scale = fontSize / 20; code += '077F0094 0000001D'; - code += [ - x, // x1 - y - fontSize - 2, // y1 - x + width * scale, // x2 - y, // y2 - ] - .map(int2gecko) - .join(''); + code += rect.map(int2gecko).join(''); code += '25753a253032752e2530337500000000'; // fmt - /* fontSize, fgColor, bgColor */ - code += '077F0110 00000010'; - const bgColor = (config.bgRGB & 0xffffff) * 256 + (config.bgA & 0xff); + /** + * 817F0110 drawTextOpt: {x, y, fontSize, colorTop, colorBot} + * 817F0120 bgColor + */ + code += '077F0110 00000014'; const fgColor = (config.fgRGB & 0xffffff) * 256 + (config.fgA & 0xff); const fgColor2 = ((config.fgRGB2 ?? config.fgRGB) & 0xffffff) * 256 + ((config.fgA2 ?? config.fgA) & 0xff); + code += [x, y].map((x) => int2hex(x, 2)).join(''); code += [fontSize, fgColor, fgColor2, bgColor].map(int2gecko).join(''); + code += '00000000'; return code.replace(/\s/g, ''); } diff --git a/site/.vuepress/components/codes/qft/config.vue b/site/.vuepress/components/codes/qft/config.vue index cc0437c..1c224bf 100644 --- a/site/.vuepress/components/codes/qft/config.vue +++ b/site/.vuepress/components/codes/qft/config.vue @@ -2,17 +2,7 @@

{{ l.h3 }}

-
- -
-
- {{ l.bgColor }} - {{ l.alpha }}/255={{ (bgA / 2.55).toFixed(1) }}% -
+

{{ l.freeze.h3 }}

@@ -35,31 +25,12 @@