diff --git a/Codes.xml b/Codes.xml index 63ca78d..3c7aa6d 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 @@ -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,19 @@ |`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 (in NTSC-J)] + ![Printable charaters](/img/preview/font-JP.png){style="background:black"} + ] + %details[ + %summary[All printable characters (in PAL)] + ![Printable charaters](/img/preview/font-EU.png){style="background:black"} ] #### Preview @@ -3282,101 +2841,116 @@ |`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-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 @@ -3801,8 +3375,8 @@ Pattern Selector パターン選択 sup39(サポミク) - 0.3 - Oct 30, 2022 + 0.4 + Jan 31, 2023 drawText Ⓑ is the cursor to select the pattern, @@ -3883,122 +3457,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 @@ -4028,161 +3676,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 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 7c64a1d..368f738 100644 --- a/changelog.md +++ b/changelog.md @@ -29,6 +29,27 @@ Disable Z menu for Instant Level Select to prevent broken texture ### Updated 'Instant Level Select' Overwrite button input value to prevent Level Select being activated when AreaLock is enabled +## Jan 31, 2023 +### 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/Generator.vue b/site/.vuepress/components/Generator.vue index 8de2526..29d5553 100644 --- a/site/.vuepress/components/Generator.vue +++ b/site/.vuepress/components/Generator.vue @@ -132,15 +132,6 @@ export default { codeConfigs: {}, }; }, - created() { - this.codeConfigs = { - qft: getConfigQFT(), - PatternSelector: getConfigPS(), - SpeedDisplay: {}, - PASDisplay: {}, - CustomizedDisplay: getConfigCD(this.version), - }; - }, methods: { getLabel(key) { return translate(key, this.$lang); @@ -168,6 +159,13 @@ export default { JSON.stringify({ version: e }), ]); } catch {} + + // update config for preview + this.codeConfigs = { + qft: getConfigQFT(), + PatternSelector: getConfigPS(), + CustomizedDisplay: getConfigCD(e), + }; }, onFormatChanged(e) { this.selectedFormat = e; @@ -222,7 +220,10 @@ export default { .filter(code => !(code.category === category && exclusive)) .map(code => code.id)); ids.add(id); - return Object.fromEntries(Object.entries(this.codeConfigs).filter(([id]) => ids.has(id))); + return { + ...Object.fromEntries(Object.entries(this.codeConfigs).filter(([id]) => ids.has(id))), + _version: this.selectedVersion, + }; }, }, }; diff --git a/site/.vuepress/components/Preview.vue b/site/.vuepress/components/Preview.vue index 8a52383..282f5e5 100644 --- a/site/.vuepress/components/Preview.vue +++ b/site/.vuepress/components/Preview.vue @@ -1,82 +1,30 @@ diff --git a/site/.vuepress/components/PreviewString.vue b/site/.vuepress/components/PreviewString.vue index e1a7370..ef11ea4 100644 --- a/site/.vuepress/components/PreviewString.vue +++ b/site/.vuepress/components/PreviewString.vue @@ -1,47 +1,34 @@ 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..016262a 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, bgA } = config; + const { preview, format, fields } = parseFormat(fmt, version); + + // fill_rect + if (bgA) { + asm.push(...fillRect(version, config, measureText(preview, version))); + } + + // drawText + if (fmt.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..99becb1 100644 --- a/site/.vuepress/components/codes/CustomizedDisplay/config.vue +++ b/site/.vuepress/components/codes/CustomizedDisplay/config.vue @@ -2,19 +2,26 @@
- +
-
- +
+ + + +
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..c404c92 100644 --- a/site/.vuepress/components/codes/asm.js +++ b/site/.vuepress/components/codes/asm.js @@ -1,7 +1,8 @@ -import * as Encoding from 'encoding-japanese'; +import charInfoJP from '../../data/charInfo-JP.json'; +import charInfoEU from '../../data/charInfo-EU.json'; /** - * @typedef {number[]} Inst + * @typedef {number} Inst * * @typedef {( * rT: number, @@ -27,7 +28,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 +44,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 +51,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 +61,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 +77,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 +91,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} */ @@ -132,6 +125,9 @@ export const ASM = { lhz: makeInstD(40), 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 +140,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 +153,22 @@ 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, + float: ASM.lfs, +}; +export const $store = { + 8: ASM.stb, + 16: ASM.sth, + 32: ASM.stw, + float: ASM.stfs, + double: ASM.stfd, }; /** @@ -163,26 +177,46 @@ 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 : charInfoEU; // TODO US + const fmtbuf = Array.from(s).flatMap((c) => { + const code = charInfo[c]?.code ?? c.charCodeAt(0); + return code >= 0x100 ? [code >> 16, 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 +228,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/labels.json b/site/.vuepress/components/codes/labels.json index 7ea4e0b..458b625 100644 --- a/site/.vuepress/components/codes/labels.json +++ b/site/.vuepress/components/codes/labels.json @@ -6,7 +6,13 @@ "fgColorGrad": "グラデーション", "fgColor1": "文字色(上):", "fgColor2": "文字色(下):", - "alpha": "不透明度=" + "alpha": "不透明度=", + "bgColor": "背景色:", + "bgOffset": "背景位置:", + "left": "左", + "right": "右", + "top": "上", + "bottom": "下" }, "en-US": { "location": "Location: ", @@ -15,6 +21,22 @@ "fgColorGrad": "Gradient", "fgColor1": "Font color(Top): ", "fgColor2": "Font color(Bottom): ", - "alpha": "Alpha=" + "alpha": "Alpha=", + "bgColor": "Background color: ", + "bgOffset": "Background offset: ", + "left": "Left", + "right": "Right", + "top": "Top", + "bottom": "Bottom" + }, + "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/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..b1017c0 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 @@