Last active
December 31, 2023 20:41
-
-
Save CataLatas/76700c2781bcfade26953ef4cc827862 to your computer and use it in GitHub Desktop.
Earthbound movement script expansion patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asm65816 | |
/* | |
* Relocates the movement script pointer table, allowing | |
* for custom scripts to be inserted into the game | |
* | |
* By Catador | |
* Additional ideas by JTolmar and cooprocks123e | |
* And maybe others (sorry!) | |
*/ | |
//***************************************************************************** | |
// Here, inside this block, you define the pointers your own movement scripts by using `adr24` | |
// Custom script IDs start at 895 | |
command DEFINE_CUSTOM_POINTERS { | |
adr24(movscr_examples.M_DvdLogo) // 895 | |
adr24(movscr_examples.M_TouchSound) // 896 | |
adr24(movscr_examples.M_UnitTests) // 897 | |
} | |
// This part intentionally has lots of newlines to separate the | |
// "user" section from the "black magic" section | |
//***************************************************************************** | |
// EVERYTHING BELOW OPERATES COMPLETELY ON BLACK MAGIC. | |
// UNLESS YOU REALLY, ABSOLUTELY, SURELY, UNDERSTAND WHAT YOU'RE DOING, | |
// DO. NOT. TOUCH. | |
_MOVSCR_PTR: | |
short 0xC2FFB7 | |
_MOVSCR_PTR_PLUS2: | |
byte[2] 0xC2FFB7 | |
DEFINE_VANILLA_POINTERS | |
DEFINE_CUSTOM_POINTERS | |
ROM[0xC093D5] = LDA_xl(_MOVSCR_PTR_PLUS2) | |
ROM[0xC093DA] = LDA_xl(_MOVSCR_PTR) | |
ROM[0xC46194] = ASMLoadAddress06(_MOVSCR_PTR) | |
ROM[0xC461E4] = ASMLoadAddress06(_MOVSCR_PTR) | |
ROM[0xC4D87E] = ASMLoadAddress06(_MOVSCR_PTR) | |
command DEFINE_VANILLA_POINTERS { | |
adr24(0xC3A043) // 001 | |
adr24(0xC3A05E) // 002 | |
adr24(0xC3A080) // 003 | |
adr24(0xC3A273) // 004 | |
adr24(0xC3A481) // 005 | |
adr24(0xC3A2E4) // 006 | |
adr24(0xC3A287) // 007 | |
adr24(0xC3A2AA) // 008 | |
adr24(0xC3A299) // 009 | |
adr24(0xC3A2D3) // 010 | |
adr24(0xC3A2D3) // 011 | |
adr24(0xC3A2E4) // 012 | |
adr24(0xC3A33B) // 013 | |
adr24(0xC3A349) // 014 | |
adr24(0xC3A357) // 015 | |
adr24(0xC3A365) // 016 | |
adr24(0xC3A373) // 017 | |
adr24(0xC3A381) // 018 | |
adr24(0xC3A48A) // 019 | |
adr24(0xC3A4C9) // 020 | |
adr24(0xC3A549) // 021 | |
adr24(0xC3A5C9) // 022 | |
adr24(0xC3A643) // 023 | |
adr24(0xC3A6C4) // 024 | |
adr24(0xC3A714) // 025 | |
adr24(0xC3A780) // 026 | |
adr24(0xC3A7F8) // 027 | |
adr24(0xC3A874) // 028 | |
adr24(0xC3A8D2) // 029 | |
adr24(0xC3A953) // 030 | |
adr24(0xC3A9DA) // 031 | |
adr24(0xC3DE01) // 032 | |
adr24(0xC3DF72) // 033 | |
adr24(0xC3DF1E) // 034 | |
adr24(0xC3A204) // 035 | |
adr24(0xC3ACAD) // 036 | |
adr24(0xC3AD7A) // 037 | |
adr24(0xC3AE1E) // 038 | |
adr24(0xC3AE78) // 039 | |
adr24(0xC3AEA0) // 040 | |
adr24(0xC3AEAC) // 041 | |
adr24(0xC3AE02) // 042 | |
adr24(0xC3ADE1) // 043 | |
adr24(0xC3AE0F) // 044 | |
adr24(0xC3AF0F) // 045 | |
adr24(0xC3AF4E) // 046 | |
adr24(0xC3AFD8) // 047 | |
adr24(0xC3AFFA) // 048 | |
adr24(0xC3B021) // 049 | |
adr24(0xC3B0EC) // 050 | |
adr24(0xC3B06D) // 051 | |
adr24(0xC3B1A6) // 052 | |
adr24(0xC3B04D) // 053 | |
adr24(0xC3B13E) // 054 | |
adr24(0xC3AFAC) // 055 | |
adr24(0xC3B1E9) // 056 | |
adr24(0xC3B208) // 057 | |
adr24(0xC3B25D) // 058 | |
adr24(0xC3B2B2) // 059 | |
adr24(0xC3B2FA) // 060 | |
adr24(0xC3B35D) // 061 | |
adr24(0xC3B3A2) // 062 | |
adr24(0xC3B3C8) // 063 | |
adr24(0xC3B445) // 064 | |
adr24(0xC3B46F) // 065 | |
adr24(0xC3B4A5) // 066 | |
adr24(0xC3B4FB) // 067 | |
adr24(0xC3B5D6) // 068 | |
adr24(0xC3B538) // 069 | |
adr24(0xC3B633) // 070 | |
adr24(0xC3B69C) // 071 | |
adr24(0xC3B6D4) // 072 | |
adr24(0xC3B757) // 073 | |
adr24(0xC3B784) // 074 | |
adr24(0xC3B7BC) // 075 | |
adr24(0xC3B7EF) // 076 | |
adr24(0xC3B810) // 077 | |
adr24(0xC3B86C) // 078 | |
adr24(0xC3B8A5) // 079 | |
adr24(0xC3B8E8) // 080 | |
adr24(0xC3B902) // 081 | |
adr24(0xC3B926) // 082 | |
adr24(0xC3B95D) // 083 | |
adr24(0xC3B9B6) // 084 | |
adr24(0xC3B9D4) // 085 | |
adr24(0xC3B9F2) // 086 | |
adr24(0xC3BA1C) // 087 | |
adr24(0xC3BA07) // 088 | |
adr24(0xC3BA31) // 089 | |
adr24(0xC3BA4F) // 090 | |
adr24(0xC3BAEA) // 091 | |
adr24(0xC3BB17) // 092 | |
adr24(0xC3BB94) // 093 | |
adr24(0xC3BA64) // 094 | |
adr24(0xC3BA67) // 095 | |
adr24(0xC3BA6A) // 096 | |
adr24(0xC3BA6D) // 097 | |
adr24(0xC3BA70) // 098 | |
adr24(0xC3BB33) // 099 | |
adr24(0xC3BB4C) // 100 | |
adr24(0xC3BD2E) // 101 | |
adr24(0xC3BD0E) // 102 | |
adr24(0xC3BBB7) // 103 | |
adr24(0xC3BC0A) // 104 | |
adr24(0xC3BC5D) // 105 | |
adr24(0xC3BCB0) // 106 | |
adr24(0xC3BD56) // 107 | |
adr24(0xC3BD80) // 108 | |
adr24(0xC3BDA0) // 109 | |
adr24(0xC3BDC3) // 110 | |
adr24(0xC3BE01) // 111 | |
adr24(0xC3BE2C) // 112 | |
adr24(0xC3BE57) // 113 | |
adr24(0xC3BE80) // 114 | |
adr24(0xC3BEEE) // 115 | |
adr24(0xC3BF4E) // 116 | |
adr24(0xC3BFB2) // 117 | |
adr24(0xC3C016) // 118 | |
adr24(0xC3C07C) // 119 | |
adr24(0xC3C236) // 120 | |
adr24(0xC3C258) // 121 | |
adr24(0xC3C2B8) // 122 | |
adr24(0xC3C2C8) // 123 | |
adr24(0xC3C2D1) // 124 | |
adr24(0xC3C2DA) // 125 | |
adr24(0xC3C2E3) // 126 | |
adr24(0xC3C326) // 127 | |
adr24(0xC3C336) // 128 | |
adr24(0xC3C33F) // 129 | |
adr24(0xC3C348) // 130 | |
adr24(0xC3C351) // 131 | |
adr24(0xC3C282) // 132 | |
adr24(0xC3C394) // 133 | |
adr24(0xC3C3ED) // 134 | |
adr24(0xC3C427) // 135 | |
adr24(0xC3C46E) // 136 | |
adr24(0xC3C4CF) // 137 | |
adr24(0xC3C540) // 138 | |
adr24(0xC3C59A) // 139 | |
adr24(0xC3C5C6) // 140 | |
adr24(0xC3C5F0) // 141 | |
adr24(0xC3C60D) // 142 | |
adr24(0xC3C634) // 143 | |
adr24(0xC3C687) // 144 | |
adr24(0xC3C6B5) // 145 | |
adr24(0xC3C6DD) // 146 | |
adr24(0xC3C8A3) // 147 | |
adr24(0xC3C8B2) // 148 | |
adr24(0xC3C8C1) // 149 | |
adr24(0xC3C8D0) // 150 | |
adr24(0xC3C8DF) // 151 | |
adr24(0xC3C8EE) // 152 | |
adr24(0xC3C990) // 153 | |
adr24(0xC3CA3E) // 154 | |
adr24(0xC3C9E0) // 155 | |
adr24(0xC3CA8E) // 156 | |
adr24(0xC3CAEA) // 157 | |
adr24(0xC3CB87) // 158 | |
adr24(0xC3CB38) // 159 | |
adr24(0xC3CBD5) // 160 | |
adr24(0xC3CCB5) // 161 | |
adr24(0xC3C747) // 162 | |
adr24(0xC3CEC7) // 163 | |
adr24(0xC3CDF0) // 164 | |
adr24(0xC3C7AE) // 165 | |
adr24(0xC3CEF5) // 166 | |
adr24(0xC3CF1B) // 167 | |
adr24(0xC3CF3C) // 168 | |
adr24(0xC3CF4B) // 169 | |
adr24(0xC3CF76) // 170 | |
adr24(0xC3D04D) // 171 | |
adr24(0xC3D0C5) // 172 | |
adr24(0xC3D0EE) // 173 | |
adr24(0xC3D10E) // 174 | |
adr24(0xC3D12E) // 175 | |
adr24(0xC3D159) // 176 | |
adr24(0xC3D172) // 177 | |
adr24(0xC3C57A) // 178 | |
adr24(0xC3D196) // 179 | |
adr24(0xC3D1C9) // 180 | |
adr24(0xC3D1F8) // 181 | |
adr24(0xC3D229) // 182 | |
adr24(0xC3D251) // 183 | |
adr24(0xC3D26E) // 184 | |
adr24(0xC3D2F7) // 185 | |
adr24(0xC3D31D) // 186 | |
adr24(0xC3D395) // 187 | |
adr24(0xC3D3C8) // 188 | |
adr24(0xC3D3FD) // 189 | |
adr24(0xC3D423) // 190 | |
adr24(0xC3D454) // 191 | |
adr24(0xC3D464) // 192 | |
adr24(0xC3D486) // 193 | |
adr24(0xC3D4C9) // 194 | |
adr24(0xC3D4EF) // 195 | |
adr24(0xC3D515) // 196 | |
adr24(0xC3D53B) // 197 | |
adr24(0xC3D566) // 198 | |
adr24(0xC3D58C) // 199 | |
adr24(0xC3D5B2) // 200 | |
adr24(0xC3D5D8) // 201 | |
adr24(0xC3D673) // 202 | |
adr24(0xC3D6D6) // 203 | |
adr24(0xC3D732) // 204 | |
adr24(0xC3D758) // 205 | |
adr24(0xC3D7E2) // 206 | |
adr24(0xC3D83C) // 207 | |
adr24(0xC3D898) // 208 | |
adr24(0xC3D8BE) // 209 | |
adr24(0xC3D8E4) // 210 | |
adr24(0xC3D91C) // 211 | |
adr24(0xC3D98C) // 212 | |
adr24(0xC3D9B2) // 213 | |
adr24(0xC3D9D8) // 214 | |
adr24(0xC3D9FE) // 215 | |
adr24(0xC3DA49) // 216 | |
adr24(0xC3DA97) // 217 | |
adr24(0xC3DAF8) // 218 | |
adr24(0xC3DB19) // 219 | |
adr24(0xC3D966) // 220 | |
adr24(0xC30195) // 221 | |
adr24(0xC30235) // 222 | |
adr24(0xC3024A) // 223 | |
adr24(0xC30260) // 224 | |
adr24(0xC302AC) // 225 | |
adr24(0xC302AC) // 226 | |
adr24(0xC302AC) // 227 | |
adr24(0xC302D7) // 228 | |
adr24(0xC302EF) // 229 | |
adr24(0xC30303) // 230 | |
adr24(0xC30317) // 231 | |
adr24(0xC3032B) // 232 | |
adr24(0xC3036F) // 233 | |
adr24(0xC3036F) // 234 | |
adr24(0xC3036F) // 235 | |
adr24(0xC3036F) // 236 | |
adr24(0xC3036F) // 237 | |
adr24(0xC30394) // 238 | |
adr24(0xC303C0) // 239 | |
adr24(0xC303E5) // 240 | |
adr24(0xC30478) // 241 | |
adr24(0xC304FA) // 242 | |
adr24(0xC304FA) // 243 | |
adr24(0xC30520) // 244 | |
adr24(0xC3053A) // 245 | |
adr24(0xC30550) // 246 | |
adr24(0xC3056E) // 247 | |
adr24(0xC3056E) // 248 | |
adr24(0xC30590) // 249 | |
adr24(0xC305EF) // 250 | |
adr24(0xC30671) // 251 | |
adr24(0xC3069F) // 252 | |
adr24(0xC306BA) // 253 | |
adr24(0xC306DA) // 254 | |
adr24(0xC30704) // 255 | |
adr24(0xC30716) // 256 | |
adr24(0xC30776) // 257 | |
adr24(0xC30796) // 258 | |
adr24(0xC307AB) // 259 | |
adr24(0xC30832) // 260 | |
adr24(0xC30869) // 261 | |
adr24(0xC308BB) // 262 | |
adr24(0xC308E5) // 263 | |
adr24(0xC30962) // 264 | |
adr24(0xC30979) // 265 | |
adr24(0xC30993) // 266 | |
adr24(0xC309B0) // 267 | |
adr24(0xC30A32) // 268 | |
adr24(0xC30A76) // 269 | |
adr24(0xC30A91) // 270 | |
adr24(0xC30ACB) // 271 | |
adr24(0xC30AF8) // 272 | |
adr24(0xC30B4E) // 273 | |
adr24(0xC30BEA) // 274 | |
adr24(0xC30BEA) // 275 | |
adr24(0xC30BEA) // 276 | |
adr24(0xC30C09) // 277 | |
adr24(0xC30C20) // 278 | |
adr24(0xC30C37) // 279 | |
adr24(0xC30C3D) // 280 | |
adr24(0xC30C43) // 281 | |
adr24(0xC30C49) // 282 | |
adr24(0xC30C4F) // 283 | |
adr24(0xC30CE2) // 284 | |
adr24(0xC30D1E) // 285 | |
adr24(0xC30DB6) // 286 | |
adr24(0xC30DCD) // 287 | |
adr24(0xC30E21) // 288 | |
adr24(0xC30E52) // 289 | |
adr24(0xC30E7F) // 290 | |
adr24(0xC30E99) // 291 | |
adr24(0xC30EB9) // 292 | |
adr24(0xC30F20) // 293 | |
adr24(0xC30F9C) // 294 | |
adr24(0xC31068) // 295 | |
adr24(0xC310B1) // 296 | |
adr24(0xC31115) // 297 | |
adr24(0xC31140) // 298 | |
adr24(0xC31182) // 299 | |
adr24(0xC311B4) // 300 | |
adr24(0xC311DF) // 301 | |
adr24(0xC31221) // 302 | |
adr24(0xC3126E) // 303 | |
adr24(0xC312AD) // 304 | |
adr24(0xC312C2) // 305 | |
adr24(0xC312E7) // 306 | |
adr24(0xC3131B) // 307 | |
adr24(0xC3133A) // 308 | |
adr24(0xC31359) // 309 | |
adr24(0xC3137E) // 310 | |
adr24(0xC31389) // 311 | |
adr24(0xC313A9) // 312 | |
adr24(0xC313F7) // 313 | |
adr24(0xC313D5) // 314 | |
adr24(0xC3141E) // 315 | |
adr24(0xC31427) // 316 | |
adr24(0xC31452) // 317 | |
adr24(0xC31485) // 318 | |
adr24(0xC31529) // 319 | |
adr24(0xC31556) // 320 | |
adr24(0xC3155C) // 321 | |
adr24(0xC315CC) // 322 | |
adr24(0xC315F8) // 323 | |
adr24(0xC31626) // 324 | |
adr24(0xC31651) // 325 | |
adr24(0xC31689) // 326 | |
adr24(0xC316BC) // 327 | |
adr24(0xC316E4) // 328 | |
adr24(0xC31717) // 329 | |
adr24(0xC31743) // 330 | |
adr24(0xC3176F) // 331 | |
adr24(0xC3179B) // 332 | |
adr24(0xC317C7) // 333 | |
adr24(0xC317FC) // 334 | |
adr24(0xC31831) // 335 | |
adr24(0xC31869) // 336 | |
adr24(0xC3189A) // 337 | |
adr24(0xC318A5) // 338 | |
adr24(0xC318D0) // 339 | |
adr24(0xC318FD) // 340 | |
adr24(0xC31A42) // 341 | |
adr24(0xC31A83) // 342 | |
adr24(0xC31AB1) // 343 | |
adr24(0xC31ABD) // 344 | |
adr24(0xC31B14) // 345 | |
adr24(0xC31B4B) // 346 | |
adr24(0xC31BED) // 347 | |
adr24(0xC31BFD) // 348 | |
adr24(0xC31BFD) // 349 | |
adr24(0xC31C23) // 350 | |
adr24(0xC31C49) // 351 | |
adr24(0xC31CA4) // 352 | |
adr24(0xC31CFB) // 353 | |
adr24(0xC31D15) // 354 | |
adr24(0xC31D61) // 355 | |
adr24(0xC31D6A) // 356 | |
adr24(0xC31D89) // 357 | |
adr24(0xC31E92) // 358 | |
adr24(0xC31EA6) // 359 | |
adr24(0xC31E66) // 360 | |
adr24(0xC31E79) // 361 | |
adr24(0xC31E89) // 362 | |
adr24(0xC31EAF) // 363 | |
adr24(0xC31EB8) // 364 | |
adr24(0xC32149) // 365 | |
adr24(0xC32342) // 366 | |
adr24(0xC322B3) // 367 | |
adr24(0xC31FE8) // 368 | |
adr24(0xC31DB5) // 369 | |
adr24(0xC323D1) // 370 | |
adr24(0xC3240A) // 371 | |
adr24(0xC32454) // 372 | |
adr24(0xC324A8) // 373 | |
adr24(0xC324B1) // 374 | |
adr24(0xC324BA) // 375 | |
adr24(0xC324CE) // 376 | |
adr24(0xC324D7) // 377 | |
adr24(0xC324E0) // 378 | |
adr24(0xC324E9) // 379 | |
adr24(0xC324F2) // 380 | |
adr24(0xC324F9) // 381 | |
adr24(0xC32507) // 382 | |
adr24(0xC32520) // 383 | |
adr24(0xC328A8) // 384 | |
adr24(0xC32534) // 385 | |
adr24(0xC328B1) // 386 | |
adr24(0xC32818) // 387 | |
adr24(0xC32C46) // 388 | |
adr24(0xC32860) // 389 | |
adr24(0xC32C8A) // 390 | |
adr24(0xC32878) // 391 | |
adr24(0xC32CA2) // 392 | |
adr24(0xC32860) // 393 | |
adr24(0xC32C8A) // 394 | |
adr24(0xC32890) // 395 | |
adr24(0xC32CBA) // 396 | |
adr24(0xC327AA) // 397 | |
adr24(0xC32B9B) // 398 | |
adr24(0xC32CF0) // 399 | |
adr24(0xC32486) // 400 | |
adr24(0xC32DFE) // 401 | |
adr24(0xC32E56) // 402 | |
adr24(0xC32E5F) // 403 | |
adr24(0xC324BA) // 404 | |
adr24(0xC324CE) // 405 | |
adr24(0xC324D7) // 406 | |
adr24(0xC324E0) // 407 | |
adr24(0xC324E9) // 408 | |
adr24(0xC32E68) // 409 | |
adr24(0xC33063) // 410 | |
adr24(0xC32E75) // 411 | |
adr24(0xC331ED) // 412 | |
adr24(0xC33205) // 413 | |
adr24(0xC3320E) // 414 | |
adr24(0xC33217) // 415 | |
adr24(0xC33220) // 416 | |
adr24(0xC33229) // 417 | |
adr24(0xC33232) // 418 | |
adr24(0xC3324E) // 419 | |
adr24(0xC3326A) // 420 | |
adr24(0xC332FA) // 421 | |
adr24(0xC33283) // 422 | |
adr24(0xC33310) // 423 | |
adr24(0xC33299) // 424 | |
adr24(0xC3332C) // 425 | |
adr24(0xC332C1) // 426 | |
adr24(0xC33342) // 427 | |
adr24(0xC332D7) // 428 | |
adr24(0xC3335E) // 429 | |
adr24(0xC3337D) // 430 | |
adr24(0xC3338F) // 431 | |
adr24(0xC3338F) // 432 | |
adr24(0xC3338F) // 433 | |
adr24(0xC3338F) // 434 | |
adr24(0xC33424) // 435 | |
adr24(0xC334CF) // 436 | |
adr24(0xC32E34) // 437 | |
adr24(0xC334FF) // 438 | |
adr24(0xC33535) // 439 | |
adr24(0xC33572) // 440 | |
adr24(0xC33595) // 441 | |
adr24(0xC335B5) // 442 | |
adr24(0xC33980) // 443 | |
adr24(0xC339D2) // 444 | |
adr24(0xC33AB5) // 445 | |
adr24(0xC33A88) // 446 | |
adr24(0xC33AED) // 447 | |
adr24(0xC33B0F) // 448 | |
adr24(0xC33B8B) // 449 | |
adr24(0xC33B9E) // 450 | |
adr24(0xC33BB2) // 451 | |
adr24(0xC33BB7) // 452 | |
adr24(0xC3DBA0) // 453 | |
adr24(0xC3DBCC) // 454 | |
adr24(0xC3DBF2) // 455 | |
adr24(0xC3DC57) // 456 | |
adr24(0xC3DC74) // 457 | |
adr24(0xC3DC91) // 458 | |
adr24(0xC3DCAE) // 459 | |
adr24(0xC3DCCB) // 460 | |
adr24(0xC3DD15) // 461 | |
adr24(0xC3DD32) // 462 | |
adr24(0xC3DD4F) // 463 | |
adr24(0xC3DD6C) // 464 | |
adr24(0xC33C6C) // 465 | |
adr24(0xC33CDA) // 466 | |
adr24(0xC33C30) // 467 | |
adr24(0xC3C0F3) // 468 | |
adr24(0xC3C101) // 469 | |
adr24(0xC3C110) // 470 | |
adr24(0xC3C11F) // 471 | |
adr24(0xC3C12E) // 472 | |
adr24(0xC3C167) // 473 | |
adr24(0xC3C17A) // 474 | |
adr24(0xC3C1A8) // 475 | |
adr24(0xC3ABED) // 476 | |
adr24(0xC3AC27) // 477 | |
adr24(0xC3AC61) // 478 | |
adr24(0xC33DD4) // 479 | |
adr24(0xC33F0C) // 480 | |
adr24(0xC33E42) // 481 | |
adr24(0xC33EC4) // 482 | |
adr24(0xC34029) // 483 | |
adr24(0xC34097) // 484 | |
adr24(0xC340CE) // 485 | |
adr24(0xC3410B) // 486 | |
adr24(0xC34114) // 487 | |
adr24(0xC3411D) // 488 | |
adr24(0xC34126) // 489 | |
adr24(0xC3412F) // 490 | |
adr24(0xC34138) // 491 | |
adr24(0xC3415D) // 492 | |
adr24(0xC34182) // 493 | |
adr24(0xC341A7) // 494 | |
adr24(0xC341CC) // 495 | |
adr24(0xC34249) // 496 | |
adr24(0xC3426E) // 497 | |
adr24(0xC342B1) // 498 | |
adr24(0xC3441A) // 499 | |
adr24(0xC34402) // 500 | |
adr24(0xC342F4) // 501 | |
adr24(0xC40F68) // 502 | |
adr24(0xC40F6E) // 503 | |
adr24(0xC40F74) // 504 | |
adr24(0xC40F7A) // 505 | |
adr24(0xC40F80) // 506 | |
adr24(0xC40F86) // 507 | |
adr24(0xC40F8C) // 508 | |
adr24(0xC40F92) // 509 | |
adr24(0xC40F98) // 510 | |
adr24(0xC40F9E) // 511 | |
adr24(0xC40FA4) // 512 | |
adr24(0xC40FAA) // 513 | |
adr24(0xC40FB0) // 514 | |
adr24(0xC40FB6) // 515 | |
adr24(0xC40FBC) // 516 | |
adr24(0xC40FC2) // 517 | |
adr24(0xC40FC8) // 518 | |
adr24(0xC40FCE) // 519 | |
adr24(0xC40FD4) // 520 | |
adr24(0xC40FDA) // 521 | |
adr24(0xC40FE0) // 522 | |
adr24(0xC40FE6) // 523 | |
adr24(0xC40FEC) // 524 | |
adr24(0xC40FF4) // 525 | |
adr24(0xC40FFD) // 526 | |
adr24(0xC41003) // 527 | |
adr24(0xC4100C) // 528 | |
adr24(0xC41012) // 529 | |
adr24(0xC41018) // 530 | |
adr24(0xC34301) // 531 | |
adr24(0xC34378) // 532 | |
adr24(0xC34385) // 533 | |
adr24(0xC41020) // 534 | |
adr24(0xC34E85) // 535 | |
adr24(0xC34EC8) // 536 | |
adr24(0xC34F31) // 537 | |
adr24(0xC34F9B) // 538 | |
adr24(0xC34FC7) // 539 | |
adr24(0xC34FF8) // 540 | |
adr24(0xC3500E) // 541 | |
adr24(0xC35056) // 542 | |
adr24(0xC350B0) // 543 | |
adr24(0xC350F4) // 544 | |
adr24(0xC35154) // 545 | |
adr24(0xC35198) // 546 | |
adr24(0xC34508) // 547 | |
adr24(0xC34572) // 548 | |
adr24(0xC3459E) // 549 | |
adr24(0xC3456F) // 550 | |
adr24(0xC345CA) // 551 | |
adr24(0xC34635) // 552 | |
adr24(0xC34693) // 553 | |
adr24(0xC346F1) // 554 | |
adr24(0xC3474E) // 555 | |
adr24(0xC3486A) // 556 | |
adr24(0xC34810) // 557 | |
adr24(0xC347C1) // 558 | |
adr24(0xC34767) // 559 | |
adr24(0xC34AF6) // 560 | |
adr24(0xC34A6C) // 561 | |
adr24(0xC34975) // 562 | |
adr24(0xC348FC) // 563 | |
adr24(0xC34BAB) // 564 | |
adr24(0xC34BCD) // 565 | |
adr24(0xC34BF7) // 566 | |
adr24(0xC34C3A) // 567 | |
adr24(0xC34C86) // 568 | |
adr24(0xC34CE0) // 569 | |
adr24(0xC34D5C) // 570 | |
adr24(0xC34D65) // 571 | |
adr24(0xC34D6E) // 572 | |
adr24(0xC34D77) // 573 | |
adr24(0xC34D92) // 574 | |
adr24(0xC34D9B) // 575 | |
adr24(0xC34DA4) // 576 | |
adr24(0xC34DA7) // 577 | |
adr24(0xC34DB0) // 578 | |
adr24(0xC34DB9) // 579 | |
adr24(0xC34DC2) // 580 | |
adr24(0xC34DCB) // 581 | |
adr24(0xC34DE0) // 582 | |
adr24(0xC34DEA) // 583 | |
adr24(0xC36A53) // 584 | |
adr24(0xC36A98) // 585 | |
adr24(0xC36ABF) // 586 | |
adr24(0xC36AE6) // 587 | |
adr24(0xC36AFF) // 588 | |
adr24(0xC36B18) // 589 | |
adr24(0xC36B4B) // 590 | |
adr24(0xC36BC6) // 591 | |
adr24(0xC36BEB) // 592 | |
adr24(0xC36C00) // 593 | |
adr24(0xC36C4A) // 594 | |
adr24(0xC36C94) // 595 | |
adr24(0xC36CDB) // 596 | |
adr24(0xC36D29) // 597 | |
adr24(0xC36D40) // 598 | |
adr24(0xC36D53) // 599 | |
adr24(0xC36D5C) // 600 | |
adr24(0xC36D7B) // 601 | |
adr24(0xC36D9F) // 602 | |
adr24(0xC36DBE) // 603 | |
adr24(0xC36DD9) // 604 | |
adr24(0xC36E19) // 605 | |
adr24(0xC36E2D) // 606 | |
adr24(0xC36E52) // 607 | |
adr24(0xC36E5E) // 608 | |
adr24(0xC36E6A) // 609 | |
adr24(0xC36E76) // 610 | |
adr24(0xC36E82) // 611 | |
adr24(0xC36EB7) // 612 | |
adr24(0xC36ED4) // 613 | |
adr24(0xC36F08) // 614 | |
adr24(0xC36F33) // 615 | |
adr24(0xC36F68) // 616 | |
adr24(0xC36F85) // 617 | |
adr24(0xC36FB9) // 618 | |
adr24(0xC36FE4) // 619 | |
adr24(0xC37010) // 620 | |
adr24(0xC37098) // 621 | |
adr24(0xC370FD) // 622 | |
adr24(0xC3715D) // 623 | |
adr24(0xC371F4) // 624 | |
adr24(0xC371FA) // 625 | |
adr24(0xC37245) // 626 | |
adr24(0xC37276) // 627 | |
adr24(0xC37287) // 628 | |
adr24(0xC372B0) // 629 | |
adr24(0xC373C2) // 630 | |
adr24(0xC37409) // 631 | |
adr24(0xC3740F) // 632 | |
adr24(0xC37456) // 633 | |
adr24(0xC37479) // 634 | |
adr24(0xC3749C) // 635 | |
adr24(0xC374B0) // 636 | |
adr24(0xC374E4) // 637 | |
adr24(0xC3756D) // 638 | |
adr24(0xC37596) // 639 | |
adr24(0xC375C5) // 640 | |
adr24(0xC375EE) // 641 | |
adr24(0xC3763B) // 642 | |
adr24(0xC3765F) // 643 | |
adr24(0xC37698) // 644 | |
adr24(0xC376D8) // 645 | |
adr24(0xC37711) // 646 | |
adr24(0xC37751) // 647 | |
adr24(0xC37778) // 648 | |
adr24(0xC377D2) // 649 | |
adr24(0xC377F4) // 650 | |
adr24(0xC37814) // 651 | |
adr24(0xC3786F) // 652 | |
adr24(0xC378B6) // 653 | |
adr24(0xC378FD) // 654 | |
adr24(0xC37891) // 655 | |
adr24(0xC378D8) // 656 | |
adr24(0xC3791D) // 657 | |
adr24(0xC3793F) // 658 | |
adr24(0xC379C0) // 659 | |
adr24(0xC37987) // 660 | |
adr24(0xC37A0B) // 661 | |
adr24(0xC37A55) // 662 | |
adr24(0xC37A5D) // 663 | |
adr24(0xC37A66) // 664 | |
adr24(0xC37A8A) // 665 | |
adr24(0xC37AB5) // 666 | |
adr24(0xC37B0B) // 667 | |
adr24(0xC37B5A) // 668 | |
adr24(0xC37B7E) // 669 | |
adr24(0xC37BFE) // 670 | |
adr24(0xC37CFD) // 671 | |
adr24(0xC37D33) // 672 | |
adr24(0xC37D92) // 673 | |
adr24(0xC37DF1) // 674 | |
adr24(0xC37EC1) // 675 | |
adr24(0xC37F65) // 676 | |
adr24(0xC37F71) // 677 | |
adr24(0xC37F7D) // 678 | |
adr24(0xC37FCD) // 679 | |
adr24(0xC3801C) // 680 | |
adr24(0xC3804C) // 681 | |
adr24(0xC3809C) // 682 | |
adr24(0xC380C0) // 683 | |
adr24(0xC38146) // 684 | |
adr24(0xC381B8) // 685 | |
adr24(0xC381E0) // 686 | |
adr24(0xC38208) // 687 | |
adr24(0xC38230) // 688 | |
adr24(0xC38264) // 689 | |
adr24(0xC38298) // 690 | |
adr24(0xC382CC) // 691 | |
adr24(0xC38309) // 692 | |
adr24(0xC383D2) // 693 | |
adr24(0xC3840A) // 694 | |
adr24(0xC38442) // 695 | |
adr24(0xC384D8) // 696 | |
adr24(0xC384E3) // 697 | |
adr24(0xC384EE) // 698 | |
adr24(0xC38515) // 699 | |
adr24(0xC38544) // 700 | |
adr24(0xC385E2) // 701 | |
adr24(0xC38678) // 702 | |
adr24(0xC3868F) // 703 | |
adr24(0xC386A9) // 704 | |
adr24(0xC386B2) // 705 | |
adr24(0xC386FA) // 706 | |
adr24(0xC38771) // 707 | |
adr24(0xC3877A) // 708 | |
adr24(0xC38783) // 709 | |
adr24(0xC3878C) // 710 | |
adr24(0xC3886C) // 711 | |
adr24(0xC387B6) // 712 | |
adr24(0xC388C3) // 713 | |
adr24(0xC38939) // 714 | |
adr24(0xC389BD) // 715 | |
adr24(0xC389DD) // 716 | |
adr24(0xC389FB) // 717 | |
adr24(0xC38AB1) // 718 | |
adr24(0xC38ADC) // 719 | |
adr24(0xC38B3A) // 720 | |
adr24(0xC38B5D) // 721 | |
adr24(0xC38B7F) // 722 | |
adr24(0xC38BC5) // 723 | |
adr24(0xC38BFC) // 724 | |
adr24(0xC38C7C) // 725 | |
adr24(0xC38CB0) // 726 | |
adr24(0xC38CE4) // 727 | |
adr24(0xC38D18) // 728 | |
adr24(0xC38D50) // 729 | |
adr24(0xC38DB3) // 730 | |
adr24(0xC38DD8) // 731 | |
adr24(0xC38DFC) // 732 | |
adr24(0xC38E32) // 733 | |
adr24(0xC38E61) // 734 | |
adr24(0xC38E89) // 735 | |
adr24(0xC38EB9) // 736 | |
adr24(0xC38EEA) // 737 | |
adr24(0xC38EF1) // 738 | |
adr24(0xC38EF8) // 739 | |
adr24(0xC38EFF) // 740 | |
adr24(0xC38F1B) // 741 | |
adr24(0xC38F39) // 742 | |
adr24(0xC38F91) // 743 | |
adr24(0xC38FDF) // 744 | |
adr24(0xC39022) // 745 | |
adr24(0xC39025) // 746 | |
adr24(0xC39030) // 747 | |
adr24(0xC390B3) // 748 | |
adr24(0xC39053) // 749 | |
adr24(0xC390E6) // 750 | |
adr24(0xC39155) // 751 | |
adr24(0xC3918A) // 752 | |
adr24(0xC391AE) // 753 | |
adr24(0xC391E3) // 754 | |
adr24(0xC39072) // 755 | |
adr24(0xC39080) // 756 | |
adr24(0xC39213) // 757 | |
adr24(0xC3924D) // 758 | |
adr24(0xC3928F) // 759 | |
adr24(0xC392AB) // 760 | |
adr24(0xC393C7) // 761 | |
adr24(0xC393DD) // 762 | |
adr24(0xC393FC) // 763 | |
adr24(0xC39440) // 764 | |
adr24(0xC39AD9) // 765 | |
adr24(0xC39AFA) // 766 | |
adr24(0xC39B25) // 767 | |
adr24(0xC39B86) // 768 | |
adr24(0xC39CD7) // 769 | |
adr24(0xC39D3D) // 770 | |
adr24(0xC39D85) // 771 | |
adr24(0xC39DCF) // 772 | |
adr24(0xC39E13) // 773 | |
adr24(0xC39E22) // 774 | |
adr24(0xC39E50) // 775 | |
adr24(0xC39E8B) // 776 | |
adr24(0xC39E7B) // 777 | |
adr24(0xC39E83) // 778 | |
adr24(0xC39EB6) // 779 | |
adr24(0xC39ECA) // 780 | |
adr24(0xC39EDE) // 781 | |
adr24(0xC39EF2) // 782 | |
adr24(0xC39FA0) // 783 | |
adr24(0xC39FBA) // 784 | |
adr24(0xC40E24) // 785 | |
adr24(0xC0AD8A) // 786 | |
adr24(0xC42172) // 787 | |
adr24(0xC42290) // 788 | |
adr24(0xC4222A) // 789 | |
adr24(0xC422E9) // 790 | |
adr24(0xC42304) // 791 | |
adr24(0xC4231F) // 792 | |
adr24(0xC4233A) // 793 | |
adr24(0xC42355) // 794 | |
adr24(0xC42370) // 795 | |
adr24(0xC4238B) // 796 | |
adr24(0xC423A6) // 797 | |
adr24(0xC423C1) // 798 | |
adr24(0xC351FD) // 799 | |
adr24(0xC35214) // 800 | |
adr24(0xC3523F) // 801 | |
adr24(0xC35FE2) // 802 | |
adr24(0xC35FF1) // 803 | |
adr24(0xC36356) // 804 | |
adr24(0xC3639E) // 805 | |
adr24(0xC363C6) // 806 | |
adr24(0xC36447) // 807 | |
adr24(0xC36405) // 808 | |
adr24(0xC36000) // 809 | |
adr24(0xC36073) // 810 | |
adr24(0xC36093) // 811 | |
adr24(0xC360B3) // 812 | |
adr24(0xC360EC) // 813 | |
adr24(0xC3610A) // 814 | |
adr24(0xC36144) // 815 | |
adr24(0xC36169) // 816 | |
adr24(0xC361AA) // 817 | |
adr24(0xC361BB) // 818 | |
adr24(0xC361CC) // 819 | |
adr24(0xC361DB) // 820 | |
adr24(0xC361FB) // 821 | |
adr24(0xC36219) // 822 | |
adr24(0xC36239) // 823 | |
adr24(0xC3626E) // 824 | |
adr24(0xC3629F) // 825 | |
adr24(0xC362E1) // 826 | |
adr24(0xC36311) // 827 | |
adr24(0xC36320) // 828 | |
adr24(0xC36338) // 829 | |
adr24(0xC366BF) // 830 | |
adr24(0xC3661C) // 831 | |
adr24(0xC36647) // 832 | |
adr24(0xC36692) // 833 | |
adr24(0xC366DC) // 834 | |
adr24(0xC36726) // 835 | |
adr24(0xC36474) // 836 | |
adr24(0xC364B1) // 837 | |
adr24(0xC3652A) // 838 | |
adr24(0xC365A3) // 839 | |
adr24(0xC3675D) // 840 | |
adr24(0xC3678E) // 841 | |
adr24(0xC367A4) // 842 | |
adr24(0xC367E6) // 843 | |
adr24(0xC36814) // 844 | |
adr24(0xC3683F) // 845 | |
adr24(0xC36852) // 846 | |
adr24(0xC36867) // 847 | |
adr24(0xC3687C) // 848 | |
adr24(0xC36891) // 849 | |
adr24(0xC368A6) // 850 | |
adr24(0xC368CF) // 851 | |
adr24(0xC368F8) // 852 | |
adr24(0xC3699B) // 853 | |
adr24(0xC369BA) // 854 | |
adr24(0xC369C9) // 855 | |
adr24(0xC369E2) // 856 | |
adr24(0xC369FB) // 857 | |
adr24(0xC36A2A) // 858 | |
adr24(0xC4279F) // 859 | |
adr24(0xC4217B) // 860 | |
adr24(0xC3A2C6) // 861 | |
adr24(0xC3949B) // 862 | |
adr24(0xC394CC) // 863 | |
adr24(0xC394FD) // 864 | |
adr24(0xC3952E) // 865 | |
adr24(0xC3955F) // 866 | |
adr24(0xC39590) // 867 | |
adr24(0xC395C1) // 868 | |
adr24(0xC395F2) // 869 | |
adr24(0xC39623) // 870 | |
adr24(0xC39654) // 871 | |
adr24(0xC39685) // 872 | |
adr24(0xC396B6) // 873 | |
adr24(0xC396E7) // 874 | |
adr24(0xC39718) // 875 | |
adr24(0xC39749) // 876 | |
adr24(0xC3977A) // 877 | |
adr24(0xC397AB) // 878 | |
adr24(0xC397DC) // 879 | |
adr24(0xC3980D) // 880 | |
adr24(0xC3983E) // 881 | |
adr24(0xC3986F) // 882 | |
adr24(0xC398A0) // 883 | |
adr24(0xC398D1) // 884 | |
adr24(0xC39902) // 885 | |
adr24(0xC39933) // 886 | |
adr24(0xC39964) // 887 | |
adr24(0xC39995) // 888 | |
adr24(0xC399C6) // 889 | |
adr24(0xC399F7) // 890 | |
adr24(0xC39A28) // 891 | |
adr24(0xC39A59) // 892 | |
adr24(0xC39A8A) // 893 | |
adr24(0xC3A099) // 894 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asm65816 | |
// Use a space that is completely unused in RAM | |
// cooprocks123e's "Battle OverWorld Sprites" patch already uses 0x31C2 through 0x31C9 | |
define OBJ_destructor_lo = 0x31CA // 60 bytes (30*2) | |
define OBJ_destructor_hi = 0x3206 // 60 bytes (30*2) | |
// Next free addresses are 0x3242 through 0x3329 | |
/* | |
* TABLE OF CONTENTS (CTRL+F to search) | |
* 1. INSTRUCTIONS | |
* 1.1. SCRIPT CONTROL INSTRUCTIONS | |
* 1.2. DATA MOVEMENT INSTRUCTIONS | |
* 1.3. ARITHMETIC AND LOGICAL INSTRUCTIONS | |
* 1.4. CONTROL FLOW INSTRUCTIONS | |
* 1.5. LOOP INSTRUCTIONS | |
* 1.6. TASK INSTRUCTIONS | |
* 1.7. CALLBACK INSTRUCTIONS | |
* 1.8. ENTITY INSTRUCTIONS | |
* 1.9. OTHER INSTRUCTIONS | |
* 2. CONVENIENCE MACROS | |
* 3. CALLBACKS | |
* 3.1. TICK CALLBACK | |
* 3.2. ONDRAW CALLBACK | |
* 3.3. ONPOSITION CALLBACK | |
* 3.4. ONMOVE CALLBACK | |
* 3.5. ONDESTROY CALLBACK | |
* 4. TASKS | |
* 5. VARIABLES | |
* 6. THE RESULT REGISTER | |
* | |
* | |
* 1. INSTRUCTIONS | |
* 1.1. SCRIPT CONTROL INSTRUCTIONS | |
* m_halt | |
* Halts script execution (infinite loop) | |
* m_pause(delay) | |
* Pauses the script execution for `delay` frames. `delay` must be in range 0..255 | |
* m_pause_result | |
* Pauses the script execution for [RESULT] frames | |
* m_pause_var0 | |
* Pauses the script execution for [VAR0] frames | |
* m_pause_var1 through m_pause_var7 | |
* Same as `m_pause_var0`, but for the other variables | |
* | |
* 1.2. DATA MOVEMENT INSTRUCTIONS | |
* m_set_var0(value) | |
* VAR0 = value | |
* m_set_var1(value) through m_set_var7(value) | |
* Same as `m_set_var0`, but for the other variables | |
* m_set_result(value) | |
* RESULT = value | |
* m_rtovar0 | |
* VAR0 = RESULT | |
* m_rtovar1 through m_rtovar7 | |
* Same as `m_rtovar0`, but for the other variables | |
* m_get_var0 | |
* RESULT = VAR0 | |
* m_get_var1 through m_get_var7 | |
* Same as `m_get_var0`, but for the other variables | |
* m_get_mem16(address) | |
* RESULT = memory[address] | |
* The address must be in bank 7E | |
* The value at the address is interpreted as 16-bit | |
* m_set_mem8(address, value) | |
* memory[address] = value | |
* The address must be in bank 7E | |
* The value at the address is interpreted as 8-bit | |
* m_set_mem16(address, value) | |
* Same as `m_set_mem8`, but the value at the address is interpreted as 16-bit | |
* | |
* 1.3. ARITHMETIC AND LOGICAL INSTRUCTIONS | |
* In the following instructions, `op` can be any of | |
* add - addition (supports negative) | |
* and - bitwise AND | |
* or - bitwise OR | |
* xor - bitwise XOR | |
* | |
* m_op_result(value) | |
* RESULT = RESULT op value | |
* m_op_var0(value) | |
* VAR0 = VAR0 op value | |
* m_op_var1(value) through m_op_var7(value) | |
* Same as `m_op_var0`, but for the other variables | |
* m_op_mem8(address, value) | |
* memory[address] = memory[address] op value | |
* The address must be in bank 7E | |
* The value at `address` is interpreted as 8-bit | |
* m_op_mem16(address, value) | |
* Same as `m_op_mem8`, but the value at `address` is interpreted as 16-bit | |
* | |
* 1.4. CONTROL FLOW INSTRUCTIONS | |
* m_jmp(address) | |
* Jump to `address`. Works exactly like assembly JMP | |
* m_jml(address) | |
* Long jump to `address`. Works exactly like assembly JML | |
* m_multijmp(amount) | |
* Table jump based on the RESULT register. `amount` tells the amount of addresses in the jump table | |
* Works exactly like CCScript control code "[09 XX (YYYYYY)*XX]" | |
* Example usage: | |
* ``` | |
* m_multijmp(3) | |
* short Label1 // Jump to `Label1` if RESULT register is 0 | |
* short Label2 // Jump to `Label2` if RESULT register is 1 | |
* Short label3 // Jump to `Label3` if RESULT register is 2 | |
* // Execution will resume here if RESULT is not any of the above values | |
* ``` | |
* m_jeq(address) | |
* Absolute jump to `address` if RESULT register is zero. Works exactly like `BEQ_a(address)` | |
* m_jne(address) | |
* Absolute jump to `address` if RESULT register is not zero. Works exactly like `BNE_a(address)` | |
* m_jsr(address) | |
* Jump to subroutine. Works exactly like assembly JSR | |
* m_jsl(address) | |
* Long jump to subroutine. Works exactly like assembly JSL | |
* m_multijsr(amount) | |
* Table subroutine jump based on the RESULT register. `amount` tells the amount of addresses in the jump table | |
* Works exactly like CCScript control code "[1F C0 XX (YYYYYY)*XX]" | |
* m_rts | |
* Returns from subroutine. Works exactly like assembly RTS | |
* m_rtl | |
* Returns from subroutine. Works exactly like assembly RTL | |
* | |
* 1.5. LOOP INSTRUCTIONS | |
* m_loop(count) | |
* Starts a loop with `count` iterations | |
* m_loop_result | |
* Starts a loop with [RESULT] iterations | |
* m_endloop | |
* Ends a loop iteration | |
* m_breakeq(address) | |
* Break out of a loop and jump to `address` if RESULT register is zero | |
* m_breakne(address) | |
* Break out of a loop and jump to `address` if RESULT register is not zero | |
* | |
* 1.6. TASK INSTRUCTIONS | |
* m_task(address) | |
* Register and begin task at `address`. The address must be at the same bank as the current bank | |
* m_task_long(address) | |
* Register and begin task at `address`. The address can be at any bank | |
* NOTE: This is not a vanilla instruction! | |
* m_endtask | |
* Ends a task. Unknown (not undefined!) behavior if the script isn't a task | |
* m_endlasttask | |
* Ends the last registered task. Unknown (not undefined!) behavior if the script has no registered tasks | |
* | |
* 1.7. CALLBACK INSTRUCTIONS | |
* m_ontick(address) | |
* Sets the entity's ONTICK callback. The address can be at any bank | |
* m_ontick_nop | |
* Sets the entity's ONTICK callback to NOP (no-operation, do nothing) | |
* m_ondraw(address) | |
* Sets the entity's ONDRAW callback. The address must be in bank C0 | |
* m_onposition(address) | |
* Sets the entity's ONPOSITION callback. The address must be in bank C0 | |
* m_onmove(address) | |
* Sets the entity's ONMOVE callback. The address must be in bank C0 | |
* m_ondestroy(address) | |
* Sets the entity's ONDESTROY callback. The address can be at any bank | |
* NOTE: This is not a vanilla instruction! | |
* | |
* 1.8. ENTITY INSTRUCTIONS | |
* m_set_spritemap(address) | |
* Sets the entity's spritemap. The address can be at any bank | |
* This is mostly undocumented, and not really useful unless you're uploading graphics to VRAM on your own | |
* m_set_anim(value) | |
* Sets the entity's animation frame to `value` | |
* If `value` is -1, the entity is made invisible | |
* m_set_anim_var0 | |
* Sets the entity's animation frame to [VAR0] | |
* If VAR0 is a negative number, the entity is made invisible | |
* m_set_anim_var1 through m_set_anim_var7 | |
* Same as `m_set_anim_var0`, but for the other variables | |
* m_add_anim(value) | |
* Adds `value` to the entity's animation frame (supports negative) | |
* If the resulting frame is negative, the entity is made invisible | |
* m_inc_anim | |
* Same as `m_add_anim(1)` | |
* m_dec_anim | |
* Same as `m_add_anim(-1)` | |
* m_priority(value) | |
* Sets the entity's drawing priority to `value` | |
* The value must be in range 0..3. Undefined behavior if the value is outside this range | |
* m_set_xpos(value) | |
* Sets the entity's X position to `value` | |
* m_set_ypos(value) | |
* Sets the entity's Y position to `value` | |
* m_set_zpos(value) | |
* Sets the entity's Z position to `value` | |
* m_add_xpos(value) | |
* Adds `value` to the entity's X position (supports negative) | |
* m_add_ypos(value) | |
* Adds `value` to the entity's Y position (supports negative) | |
* m_add_zpos(value) | |
* Adds `value` to the entity's Z position (supports negative) | |
* m_set_xvel(value) | |
* Sets the entity's X velocity to `value` | |
* To get the value in pixels per frame, divide `value` by 256 | |
* m_set_yvel(value) | |
* Same as `m_set_xvel`, but for the Y velocity | |
* m_set_zvel(value) | |
* Same as `m_set_xvel`, but for the Z velocity | |
* m_add_xpos(value) | |
* Adds `value` to the entity's X velocity (supports negative) | |
* To get the value in pixels per frame, divide `value` by 256 | |
* m_add_yvel(value) | |
* Same as `m_add_xvel`, but for the Y velocity | |
* m_add_zvel(value) | |
* Same as `m_add_xvel`, but for the Z velocity | |
* m_zerovel | |
* Sets the entity's X/Y/Z velocities to zero | |
* | |
* 1.9. OTHER INSTRUCTIONS | |
* m_end | |
* Ends the script. Shouldn't be called before the entity is deleted via `asmcall(0xC020F1)` | |
* You don't really have to worry about calling this, as it's already done via the convenience macro `m_destroy_self` | |
* m_asmcall(address) | |
* Call ASM routine at `address` | |
* The RESULT register is passed as a parameter to the ASM routine in the accumulator | |
* The RESULT register will also be set to whatever the ASM routine returns in the accumulator | |
* m_store_result | |
* Write RESULT register to storage | |
* Works similar to CCScript control code `store_registers` | |
* m_load_result | |
* Load RESULT register from storage | |
* Works similar to CCScript control code `load_registers` | |
* | |
* | |
* 2. CONVENIENCE MACROS | |
* NOTE: Most of these will clobber the value in the RESULT register. Please keep this in mind | |
* | |
* m_destroy_self | |
* Deletes the entity and ends the script | |
* m_choose_random_2(n1, n2) | |
* Select a random number and store it in the RESULT register | |
* m_choose_random_3(n1, n2, n3) through m_choose_random_8(n1, n2, n3, n4, n5, n6, n7, n8) | |
* Same as `m_choose_random_2`, but select a random number from a greater sample | |
* m_result_greater(value) | |
* Returns 1 if (RESULT > value), otherwise returns 0 | |
* m_x_less_than(value) | |
* Returns 1 if (entity_x < value), otherwise returns 0 | |
* m_y_less_than(value) | |
* Returns 1 if (entity_y < value), otherwise returns 0 | |
* m_rand | |
* Returns a random number in range 0..255 | |
* m_rand_mod4 | |
* Returns a random number in range 0..3 | |
* m_rand_mod8 | |
* Returns a random number in range 0..7 | |
* m_get_random_angle | |
* Returns `rand() << 8`, useful for getting a random angle value | |
* m_get_distance_from_player | |
* Sets the RESULT register to the distance between the entity and the party leader | |
* m_wait_until_touch | |
* Halts script execution until the player touches the entity | |
* m_wait_until_near_self(rx, ry) | |
* Halts script execution until the player is near the entity in radius (rx, ry) | |
* m_wait_until_near_pos(px, py, rx, ry) | |
* Halts script execution until the player is near position (px, py) in radius (rx, ry) | |
* m_unlock_text | |
* Unlocks the text (CCScript) script after a "[1F 61]" control code | |
* m_make_invisible | |
* Makes the entity invisible. Equivalent to `m_set_anim(-1)` | |
* m_disable_collision | |
* Disables collisions with the entity | |
* m_invisible_no_collision | |
* Makes the entity invisible and disables collision | |
* m_enable_collision | |
* Enables collisions with the entity | |
* m_call_npc_text | |
* Calls the NPC's primary text script | |
* Undefined behavior if the entity is not an NPC | |
* m_textcall(address) | |
* Calls the text script at `address` | |
* Respects door transitions and such | |
* m_textcall2(address) | |
* Calls the text script at `address` | |
* Immediately call, don't respect door transitions | |
* m_fadein(delta, delay) | |
* Perform a screen fade-in | |
* `delta` is how much the brightness will change every `delay` frames | |
* NOTE: The game will keep running normally while the fade is in progress | |
* m_fadeout(delta, delay) | |
* Same as `m_fadein`, but performs a screen fade-out | |
* m_wait_fade | |
* Waits until a screen fade (`m_fadein` or `m_fadeout`) is done | |
* m_mosaic_in(delta, delay, bgs) | |
* Perform a screen fade-in with mosaic | |
* `delta` is how much the brightness will change every `delay` frames | |
* `bgs` tell which BG layers are affected by the mosaic (bitwise: 0x01, 0x02, 0x04, 0x08) | |
* NOTE: The game is paused until the screen fade is done | |
* m_mosaic_out(delta, delay, bgs) | |
* Same as `m_mosaic_in`, but performs a screen fade-out | |
* m_create_entity(spr, scr) | |
* Creates a new entity with spritegroup `spr` and script `scr` | |
* m_set_surface_flags(flags) | |
* Sets the entity's surface flags | |
* m_set_speed(value) | |
* Sets the entity's movement speed | |
* To get the value in pixels per frame, divide `value` by 256 | |
* m_set_speed_to_result | |
* Sets the entity's movement speed to the RESULT register | |
* m_get_speed | |
* Stores the entity's movement speed into the RESULT register | |
* To get the value in pixels per frame, divide `value` by 256 | |
* m_set_facing_anim(dir, anim) | |
* Sets the entity's facing direction to `dir` and animation frame to `anim` | |
* If VAR0 is not zero, then something slightly different happens | |
* m_set_facing(dir) | |
* Sets the entity's facing direction to `dir` | |
* m_set_facing_to_result | |
* Sets the entity's facing direction to the RESULT register | |
* m_reverse_facing | |
* Reverses the entity's facing direction | |
* m_get_facing | |
* Stores the entity's facing direction into the RESULT register | |
* m_start_walk(dir) | |
* Makes the entity start walking towards a certain direction | |
* m_walk_pixels(pixels) | |
* Makes the entity walk a certain number of pixels with its current facing direction | |
* m_set_flag(flagid) | |
* Sets the event flag `flagid` | |
* m_unset_flag(flagid) | |
* Unsets the event flag `flagid` | |
* m_get_flag(flagid) | |
* Stores the state of event flag `flagid` into the RESULT register | |
* m_sound(snd) | |
* Plays a sound effect | |
* m_warp_to_pc(pc) | |
* Instantly teleports the entity to the location of the party character `pc` | |
* m_warp_to_leader | |
* Instantly teleports the entity to the location of the party leader | |
* m_warp_to_sprite(spr) | |
* Instantly teleports the entity to the location of another entity with spritegroup `spr` | |
* m_warp_to_dest | |
* Instantly teleports the entity to its destination | |
* m_set_new_entity_spawn_pos(x, y, dir) | |
* Sets the "anchor point" for new entities/npcs created with CCScript control codes "[1F 15]" and "[1F 17]" | |
* m_set_new_entity_spawn_pos_from_leader | |
* Same as `m_set_new_sprite_spawn_pos`, but the coordinates are taken from the party leader | |
* m_set_new_entity_spawn_pos_from_self | |
* Same as `m_set_new_sprite_spawn_pos`, but the coordinates are taken from the current entity | |
* m_set_new_entity_spawn_pos_from_warp(warpid) | |
* Same as `m_set_new_sprite_spawn_pos`, but the coordinates are taken from a warp (as used with CCScript control code `warp`) | |
* m_face_dest | |
* Makes the entity face its destination | |
* m_refresh_graphics | |
* Forces a refresh on the entity's graphics, using the current animation frame | |
* m_refresh_graphics_frame0 | |
* Forces a refresh on the entity's graphics, using animation frame 0 | |
* NOTE: This doesn't actually set the entity's animation frame, it just displays frame 0 | |
* m_refresh_graphics_frame1 | |
* Forces a refresh on the entity's graphics, using animation frame 1 | |
* NOTE: This doesn't actually set the entity's animation frame, it just displays frame 1 | |
* m_copy_xy_to_var01 | |
* Copies the entity's (X, Y) position to (VAR0, VAR1) | |
* m_move_until_at(px, py) | |
* Makes the entity move towards (px, py), halting script execution until reaching the destination | |
* m_move_until_at_radius(px, py, radius) | |
* Same as `m_move_until_at`, but with a configurable detection radius | |
* m_set_dest_pos(px, py) | |
* Sets the entity's destination to (px, py) | |
* m_set_dest_npc(npc) | |
* Sets the entity's destination to NPC `npc` | |
* m_set_dest_sprite(spr) | |
* Sets the entity's destination to sprite with spritegroup `spr` | |
* m_set_dest_pc(pc) | |
* Sets the entity's destination to party character `pc` | |
* Undefined behavior if `pc` is not in the party | |
* m_set_dest_leader | |
* Sets the entity's destination to the party leader | |
* m_set_dest_party_tail | |
* Sets the entity's destination to the party "tail" | |
* m_default_dest_radius | |
* Sets the destination radius check to the lowest possible value, taking into account the entity's movement speed | |
* m_set_dest_radius(radius) | |
* Sets the destination radius check to `radius` | |
* m_walk_to_dest | |
* Makes the entity move towards its current destination, halting script execution until reaching the destination | |
* m_walk_to_leader | |
* Makes the entity walk next to the party leader, halting script execution until reaching the destination | |
* m_init_basic_moving(speed) | |
* Initializes a basic moving entity with movement speed `speed` | |
* To get the speed in pixels per frame, divide `speed` by 256 | |
* The entity will animate with 16-frame delay and respect collision with map tiles | |
* The entity will also be destroyed automatically if it goes off-screen far enough | |
* | |
* | |
* 3. CALLBACKS | |
* 3.1. TICK CALLBACK | |
* An optional function that is executed every frame | |
* DP local variables $00 through $7F can be freely used by the function | |
* 3.2. ONDRAW CALLBACK | |
* A function that is executed every frame, responsible for pushing values into OAM | |
* DP local variables $00 through $7F can be freely used by the function | |
* 3.3. ONPOSITION CALLBACK | |
* A function that is executed every frame, responsible for setting the entity's on-screen position | |
* DP local variables $00 through $7F can be freely used by the function | |
* 3.4. ONMOVE CALLBACK | |
* A function that is executed every frame, responsible for moving the entity based on its velocity values | |
* DP local variables $00 through $7F can be freely used by the function | |
* 3.5. ONDESTROY CALLBACK | |
* An optional function that is executed whenever the entity is destroyed | |
* DP local variables $00 through $1F can be freely used by the function | |
* NOTE: This is not a vanilla callback! | |
* | |
* | |
* 4. TASKS: | |
* "Tasks" are auxiliary scripts that run alongside a main script. | |
* The tasks will always run after the main script | |
* | |
* | |
* 5. VARIABLES | |
* "Variables" are a special form of general-purpose storage that are bound to the ENTITY. | |
* They differ from the RESULT register, which is, in turn, bound to the SCRIPT. | |
* This means that variables can be used to communicate between the main script and its tasks, since they share the same ENTITY. | |
* Common examples of this include the "MovTask_Anim" tasks, which generally use VAR4 as a toggle. | |
* Each entity has eight 16-bit variables, named VAR0 through VAR7. | |
* Most of the times, the pair (VAR6, VAR7) is the entity's current (X, Y) destination point | |
* | |
* | |
* 6. THE RESULT REGISTER | |
* The RESULT register is a 16-bit number, and a special form of storage that is bound to the SCRIPT | |
* This means that the main script and its tasks all have their own distinct RESULT register. | |
* When an ASMCALL instruction is executed, this register is passed as a parameter to the called ASM routine in the accumulator. | |
* The RESULT register will also get its value from the return value of the ASM routine | |
*/ | |
// DO NOT TOUCH ANYTHING BELOW HERE!! | |
//***************************************************************************** | |
// MOVEMENT SCRIPT INSTRUCTION DEFINES | |
//***************************************************************************** | |
// Unused instructions that can still be replaced: 34, 35, 36, 37, 38, 3A | |
// SCRIPT CONTROL INSTRUCTIONS | |
command m_pause(frames) "[06 {byte frames}]" | |
command m_halt "[09]" | |
command m_pause_var0 "[21 00]" | |
command m_pause_var1 "[21 01]" | |
command m_pause_var2 "[21 02]" | |
command m_pause_var3 "[21 03]" | |
command m_pause_var4 "[21 04]" | |
command m_pause_var5 "[21 05]" | |
command m_pause_var6 "[21 06]" | |
command m_pause_var7 "[21 07]" | |
command m_pause_result "[44]" | |
// DATA MOVEMENT INSTRUCTIONS | |
command m_set_var0(val) "[0E 00 {short val}]" | |
command m_set_var1(val) "[0E 01 {short val}]" | |
command m_set_var2(val) "[0E 02 {short val}]" | |
command m_set_var3(val) "[0E 03 {short val}]" | |
command m_set_var4(val) "[0E 04 {short val}]" | |
command m_set_var5(val) "[0E 05 {short val}]" | |
command m_set_var6(val) "[0E 06 {short val}]" | |
command m_set_var7(val) "[0E 07 {short val}]" | |
command m_set_mem8(addr, val) "[12 {short addr} {byte val}]" | |
command m_set_mem16(addr, val) "[15 {short addr} {short val}]" | |
command m_set_result(val) "[1D {short val}]" | |
command m_get_mem16(addr) "[1E {short addr}]" | |
command m_rtovar0 "[1F 00]" | |
command m_rtovar1 "[1F 01]" | |
command m_rtovar2 "[1F 02]" | |
command m_rtovar3 "[1F 03]" | |
command m_rtovar4 "[1F 04]" | |
command m_rtovar5 "[1F 05]" | |
command m_rtovar6 "[1F 06]" | |
command m_rtovar7 "[1F 07]" | |
command m_get_var0 "[20 00]" | |
command m_get_var1 "[20 01]" | |
command m_get_var2 "[20 02]" | |
command m_get_var3 "[20 03]" | |
command m_get_var4 "[20 04]" | |
command m_get_var5 "[20 05]" | |
command m_get_var6 "[20 06]" | |
command m_get_var7 "[20 07]" | |
// ARITHMETIC AND LOGICAL INSTRUCTIONS | |
command m_and_mem16(addr, val) "[0D {short addr} 00 {short val}]" | |
command m_or_mem16(addr, val) "[0D {short addr} 01 {short val}]" | |
command m_add_mem16(addr, val) "[0D {short addr} 02 {short val}]" | |
command m_xor_mem16(addr, val) "[0D {short addr} 03 {short val}]" | |
command m_and_var0(val) "[14 00 00 {short val}]" | |
command m_and_var1(val) "[14 01 00 {short val}]" | |
command m_and_var2(val) "[14 02 00 {short val}]" | |
command m_and_var3(val) "[14 03 00 {short val}]" | |
command m_and_var4(val) "[14 04 00 {short val}]" | |
command m_and_var5(val) "[14 05 00 {short val}]" | |
command m_and_var6(val) "[14 06 00 {short val}]" | |
command m_and_var7(val) "[14 07 00 {short val}]" | |
command m_or_var0(val) "[14 00 01 {short val}]" | |
command m_or_var1(val) "[14 01 01 {short val}]" | |
command m_or_var2(val) "[14 02 01 {short val}]" | |
command m_or_var3(val) "[14 03 01 {short val}]" | |
command m_or_var4(val) "[14 04 01 {short val}]" | |
command m_or_var5(val) "[14 05 01 {short val}]" | |
command m_or_var6(val) "[14 06 01 {short val}]" | |
command m_or_var7(val) "[14 07 01 {short val}]" | |
command m_add_var0(val) "[14 00 02 {short val}]" | |
command m_add_var1(val) "[14 01 02 {short val}]" | |
command m_add_var2(val) "[14 02 02 {short val}]" | |
command m_add_var3(val) "[14 03 02 {short val}]" | |
command m_add_var4(val) "[14 04 02 {short val}]" | |
command m_add_var5(val) "[14 05 02 {short val}]" | |
command m_add_var6(val) "[14 06 02 {short val}]" | |
command m_add_var7(val) "[14 07 02 {short val}]" | |
command m_xor_var0(val) "[14 00 03 {short val}]" | |
command m_xor_var1(val) "[14 01 03 {short val}]" | |
command m_xor_var2(val) "[14 02 03 {short val}]" | |
command m_xor_var3(val) "[14 03 03 {short val}]" | |
command m_xor_var4(val) "[14 04 03 {short val}]" | |
command m_xor_var5(val) "[14 05 03 {short val}]" | |
command m_xor_var6(val) "[14 06 03 {short val}]" | |
command m_xor_var7(val) "[14 07 03 {short val}]" | |
command m_and_mem8(addr, val) "[18 {short addr} 00 {byte val}]" | |
command m_or_mem8(addr, val) "[18 {short addr} 01 {byte val}]" | |
command m_add_mem8(addr, val) "[18 {short addr} 02 {byte val}]" | |
command m_xor_mem8(addr, val) "[18 {short addr} 03 {byte val}]" | |
command m_and_result(val) "[27 00 {short val}]" | |
command m_or_result(val) "[27 01 {short val}]" | |
command m_add_result(val) "[27 02 {short val}]" | |
command m_xor_result(val) "[27 03 {short val}]" | |
// CONTROL FLOW INSTRUCTIONS | |
command m_jml(addr) "[03 {adr24(addr)}]" | |
command m_jsl(addr) "[04 {adr24(addr)}]" | |
command m_rtl "[05]" | |
command m_jeq(addr) "[0A {short addr}]" | |
command m_jne(addr) "[0B {short addr}]" | |
command m_multijmp(amount) "[10 {byte amount}]" | |
command m_multijsr(amount) "[11 {byte amount}]" | |
command m_jmp(addr) "[19 {short addr}]" | |
command m_jsr(addr) "[1A {short addr}]" | |
command m_rts "[1B]" | |
// LOOP INSTRUCTIONS | |
command m_loop(c) "[01 {byte c}]" | |
command m_loop_result "[24]" | |
command m_endloop "[02]" | |
command m_breakeq(addr) "[16 {short addr}]" | |
command m_breakne(addr) "[17 {short addr}]" | |
// TASK INSTRUCTIONS | |
command m_task(addr) "[07 {short addr}]" | |
command m_endtask "[0C]" | |
command m_endlasttask "[13]" | |
command m_task_long(addr) "[31 {adr24(addr)}]" // NON-VANILLA! | |
// CALLBACK INSTRUCTIONS | |
command m_ontick(addr) "[08 {adr24(addr)}]" | |
command m_ontick_nop "[0F]" | |
command m_ondraw(addr) "[22 {short addr}]" | |
command m_onposition(addr) "[23 {short addr}]" | |
command m_onmove(addr) "[25 {short addr}]" | |
command m_ondestroy(addr) "[34 {adr24(addr)}]" // NON-VANILLA! | |
// ENTITY INSTRUCTIONS | |
command m_set_spritemap(addr) "[1C {adr24(addr)}]" | |
command m_set_anim_var0 "[26 00]" | |
command m_set_anim_var1 "[26 01]" | |
command m_set_anim_var2 "[26 02]" | |
command m_set_anim_var3 "[26 03]" | |
command m_set_anim_var4 "[26 04]" | |
command m_set_anim_var5 "[26 05]" | |
command m_set_anim_var6 "[26 06]" | |
command m_set_anim_var7 "[26 07]" | |
command m_set_xpos(val) "[28 {short val}]" | |
command m_set_ypos(val) "[29 {short val}]" | |
command m_set_zpos(val) "[2A {short val}]" | |
command m_add_xpos(val) "[2B {short val}]" | |
command m_add_ypos(val) "[2C {short val}]" | |
command m_add_zpos(val) "[2D {short val}]" | |
command m_add_xvel(val) "[2E {short val}]" | |
command m_add_yvel(val) "[2F {short val}]" | |
command m_add_zvel(val) "[30 {short val}]" | |
command m_zerovel "[39]" | |
command m_set_anim(val) "[3B {byte val}]" | |
command m_inc_anim "[3C]" | |
command m_dec_anim "[3D]" | |
command m_add_anim(val) "[3E {byte val}]" | |
command m_set_xvel(val) "[3F {short val}]" | |
command m_set_yvel(val) "[40 {short val}]" | |
command m_set_zvel(val) "[41 {short val}]" | |
command m_priority(val) "[43 {byte val}]" | |
// OTHER INSTRUCTIONS | |
command m_end "[00]" | |
command m_store_result "[32]" // NON-VANILLA! | |
command m_load_result "[33]" // NON-VANILLA! | |
command m_asmcall(addr) "[42 {adr24(addr)}]" | |
//***************************************************************************** | |
// VANILLA TASK DEFINES | |
//***************************************************************************** | |
define MovTask_Anim8 = 0xC3A09F // Animate with 8 frame delay | |
define MovTask_Anim24 = 0xC3A0B2 // Animate with 24 frame delay | |
define MovTask_Anim12 = 0xC3A0C5 // Animate with 12 frame delay | |
define MovTask_Anim_Var4 = 0xC3A12E // Animate with [VAR4] frame delay | |
define MovTask_Anim8_Toggle_DestroyIfFar = 0xC3A15E // Animate with 8 frame delay (togglable via VAR4) and destroy if far | |
define MovTask_Anim12_24_DestroyIfFar = 0xC3A17B // Animate with 12 then 24 frame delay and destroy if far | |
define MovTask_Anim24_DestroyIfFar = 0xC3A18F // Animate with 24 frame delay and destroy if far | |
define MovTask_Anim9_DestroyIfFar = 0xC3A1B7 // Animate with 9 frame delay and destroy if far | |
define MovTask_Anim6_DestroyIfFar = 0xC3A1CB // Animate with 6 frame delay and destroy if far | |
define MovTask_Anim16_DestroyIfFar = 0xC3A1F3 // Animate with 16 frame delay and destroy if far | |
define MovTask_HandleCollision = 0xC3A262 // Handle collisions. Doesn't need to be used by stationary entities | |
define MovTask_DestroyIfFar = 0xC3A2B8 // Destroy if far | |
define MovTask_EnemyTouch1 = 0xC3A434 // Start battle with enemy on touch | |
define MovTask_EnemyTouch2 = 0xC3A448 // Very similar to above, I don't actually know what's different | |
define MovTask_PartyLook = 0xC3AFA3 // Party members look at ENTITY | |
define MovTask_DestroyIfFar_UnsetFlag_10 = 0xC3B431 // Destroy if far and unset event flag 10 | |
define MovTask_ButterflyTouch = 0xC3DEED // Butterfly effect on touch | |
define MovTask_CallNpcScriptOnTouch = 0xC36D18 // Call NPC primary text script on touch | |
//***************************************************************************** | |
// CONVENIENCE MACROS DEFINITION | |
//***************************************************************************** | |
// Select a random number and store it in the RESULT register | |
command m_choose_random_2(a, b) { | |
m_asmcall (0xC09F82) | |
"[02 {short a} {short b}]" | |
} | |
command m_choose_random_3(a, b, c) { | |
m_asmcall (0xC09F82) | |
"[03 {short a} {short b} {short c}]" | |
} | |
command m_choose_random_4(a, b, c, d) { | |
m_asmcall (0xC09F82) | |
"[04 {short a} {short b} {short c} {short d}]" | |
} | |
command m_choose_random_5(a, b, c, d, e) { | |
m_asmcall (0xC09F82) | |
"[05 {short a} {short b} {short c} {short d} {short e}]" | |
} | |
command m_choose_random_6(a, b, c, d, e, f) { | |
m_asmcall (0xC09F82) | |
"[06 {short a} {short b} {short c} {short d} {short e} {short f}]" | |
} | |
command m_choose_random_7(a, b, c, d, e, f, g) { | |
m_asmcall (0xC09F82) | |
"[07 {short a} {short b} {short c} {short d} {short e} {short f} {short g}]" | |
} | |
command m_choose_random_8(a, b, c, d, e, f, g, h) { | |
m_asmcall (0xC09F82) | |
"[08 {short a} {short b} {short c} {short d} {short e} {short f} {short g} {short h}]" | |
} | |
// RESULT = 1 if (RESULT > value) else 0 | |
command m_result_greater(val) { | |
m_asmcall (_ASM_resultgreater) | |
short val | |
} | |
// RESULT = 1 if (ENTITY_x < value) else 0 | |
command m_x_less_than(val) { | |
m_set_result (val) | |
m_asmcall (0xC468B5) | |
} | |
// RESULT = 1 if (entity_y < value) else 0 | |
command m_y_less_than(val) { | |
m_set_result (val) | |
m_asmcall (0xC468DC) | |
} | |
// Halts script execution until the player is near the entity in radius (rx, ry) | |
command m_wait_until_near_self(rx, ry) { | |
m_set_var2 (rx) | |
m_set_var3 (ry) | |
m_jsl (_SCR_waituntilnearself) | |
} | |
// Halts script execution until the player is near position (px, py) in radius (rx, ry) | |
command m_wait_until_near_pos(px, py, rx, ry) { | |
m_set_var0 (px) | |
m_set_var1 (py) | |
m_set_var2 (rx) | |
m_set_var3 (ry) | |
m_jsl (_SCR_waituntilnear) | |
} | |
// Makes the entity invisible and disables collision | |
command m_invisible_no_collision { | |
m_make_invisible | |
m_disable_collision | |
} | |
// Calls a text script (respects door transitions and such) | |
command m_textcall(textptr) { | |
m_asmcall (0xC0A88D) | |
short[1] textptr | |
short[0] textptr | |
} | |
// Calls a text script (Immediately, don't respect door transitions) | |
command m_textcall2(textptr) { | |
m_asmcall (0xC0A8A0) | |
short[1] textptr | |
short[0] textptr | |
} | |
// Deletes the entity and ends the script | |
command m_destroy_self { | |
m_asmcall (0xC020F1) | |
m_end | |
} | |
// Perform a screen fade-in | |
command m_fadein(amount, speed) { | |
m_asmcall (0xC09FAE) | |
byte amount | |
byte speed | |
} | |
// Perform a screen fade-out | |
command m_fadeout(amount, speed) { | |
m_asmcall (0xC09FBB) | |
byte amount | |
byte speed | |
} | |
// Perform a screen fade-in with mosaic | |
command m_mosaic_in(amount, speed, bgs) { | |
m_asmcall (_ASM_mosaicin) | |
short amount | |
short speed | |
short bgs | |
} | |
// Perform a screen fade-out with mosaic | |
command m_mosaic_out(amount, speed, bgs) { | |
m_asmcall (0xC0AA07) | |
short amount | |
short speed | |
short bgs | |
} | |
// Creates a new entity with spritegroup `spr` and script `scr` | |
command m_create_entity(spr, scr) { | |
m_asmcall (0xC0A98B) | |
short spr | |
short scr | |
} | |
// Sets the entity's surface flags | |
command m_set_surface_flags(flags) { | |
m_asmcall (0xC0A679) | |
byte flags | |
} | |
// Sets the entity's movement speed | |
command m_set_speed(speed) { | |
m_asmcall (0xC0A685) | |
short speed | |
} | |
// Sets the entity's facing direction to `dir` and animation frame to `anim` | |
command m_set_facing_anim(facing, anim) { | |
m_asmcall (0xC0AA6E) | |
byte facing | |
byte anim | |
} | |
// Sets the entity's facing direction to `dir` | |
command m_set_facing(dir) { | |
m_set_result (dir) | |
m_set_facing_to_result | |
} | |
// Reverses the entity's facing direction | |
command m_reverse_facing { | |
m_get_facing | |
m_asmcall (0xC46B37) | |
m_set_facing_to_result | |
} | |
// Makes the entity start walking towards a certain direction | |
command m_start_walk(dir) { | |
m_set_result (dir) | |
m_asmcall (0xC0C83B) | |
} | |
// Makes the entity walk a certain number of pixels with its current facing direction | |
command m_walk_pixels(pixels) { | |
m_asmcall (0xC0A6A2) | |
short pixels | |
} | |
// Sets the event flag `flagid` | |
command m_set_flag(flagid) { | |
m_set_result (1) | |
m_asmcall (0xC0A857) | |
short flagid | |
} | |
// Unsets the event flag `flagid` | |
command m_unset_flag(flagid) { | |
m_set_result (0) | |
m_asmcall (0xC0A857) | |
short flagid | |
} | |
// Stores the state of event flag `flagid` into the RESULT REGISTER | |
command m_get_flag(flagid) { | |
m_asmcall (0xC0A84C) | |
short flagid | |
} | |
// Plays a sound effect | |
command m_sound(snd) { | |
m_asmcall (0xC0A841) | |
short snd | |
} | |
// Instantly teleports the entity to the location of the party character `pc` | |
command m_warp_to_pc(pc) { | |
m_asmcall (0xC0A864) | |
byte pc | |
} | |
// Instantly teleports the entity to the location of the party character `pc` | |
command m_warp_to_leader { | |
m_warp_to_pc (-1) | |
} | |
// Instantly teleports the entity to the location of another entity with spritegroup `spr` | |
command m_warp_to_sprite(spr) { | |
m_asmcall (0xC0A86F) | |
short spr | |
} | |
// Sets the "anchor point" for new entities/npcs created with CCScript control codes "[1F 15]" and "[1F 17]" | |
command m_set_new_entity_spawn_pos(x, y, dir) { | |
m_asmcall (0xC0A912) | |
short x | |
short y | |
byte dir | |
} | |
// Same as `m_set_new_sprite_spawn_pos`, but the coordinates are taken from the party leader | |
command m_set_new_entity_spawn_pos_from_leader { | |
m_set_result (1) | |
m_asmcall (0xC46DAD) | |
} | |
// Same as `m_set_new_sprite_spawn_pos`, but the coordinates are taken from the current entity | |
command m_set_new_entity_spawn_pos_from_self { | |
m_set_result (0) | |
m_asmcall (0xC46DAD) | |
} | |
// Same as `m_set_new_sprite_spawn_pos`, but the coordinates are taken from a "preset warp" (as used with CCScript control code `warp`) | |
command m_set_new_entity_spawn_pos_from_warp(warpid) { | |
m_set_result (warpid) | |
m_asmcall (0xC46DE5) | |
} | |
// Makes the entity face its destination | |
command m_face_dest { | |
m_asmcall (0xC46ADB) // Get angle towards destination | |
m_asmcall (0xC46B0A) // Set movement direction based on angle. Returns the direction | |
m_asmcall (0xC0A65F) // Set facing direction | |
} | |
// Makes the entity move towards (px, py), halting script execution until reaching the destination | |
command m_move_until_at(px, py) { | |
m_default_dest_radius | |
m_set_dest_pos (px, py) | |
m_walk_to_dest | |
} | |
// Same as `m_move_until_at`, but with a configurable detection radius | |
command m_move_until_at_radius(px, py, radius) { | |
m_set_dest_radius (radius) | |
m_set_dest_pos (px, py) | |
m_walk_to_dest | |
} | |
// Sets the entity's destination to (px, py) | |
command m_set_dest_pos(px, py) { | |
m_set_var6 (px) | |
m_set_var7 (py) | |
} | |
// Sets the entity's destination to NPC `npc` | |
command m_set_dest_npc(npc) { | |
m_asmcall (0xC0A92D) | |
short npc | |
} | |
// Sets the entity's destination to sprite with spritegroup `spr` | |
command m_set_dest_sprite(spr) { | |
m_asmcall (0xC0A938) | |
short spr | |
} | |
// Sets the entity's destination to party character `pc` | |
command m_set_dest_pc(pc) { | |
m_asmcall (0xC0A943) | |
byte pc | |
} | |
// Sets the entity's destination to the party leader | |
command m_set_dest_leader { | |
m_asmcall (0xC46B65) | |
} | |
// Sets the entity's destination to the party "tail" | |
command m_set_dest_party_tail { | |
m_set_dest_pc (-2) | |
} | |
// Sets the destination radius check to the lowest possible value, taking into account the entity's movement speed | |
command m_default_dest_radius { | |
m_asmcall (_ASM_ceilspeed) | |
m_rtovar5 | |
} | |
// Sets the destination radius check to `radius` | |
command m_set_dest_radius(radius) { | |
m_asmcall (_ASM_ceilspeed) | |
m_asmcall (_ASM_mathmax) | |
short radius | |
m_rtovar5 | |
} | |
// Makes the entity move towards its current destination, halting script execution until reaching the destination | |
command m_walk_to_dest { | |
m_jsl (_SCR_moveuntilatdest) | |
} | |
// Makes the entity walk next to the party leader, halting script execution until reaching the destination | |
command m_walk_to_leader { | |
m_set_dest_radius (17) | |
m_set_dest_leader | |
m_walk_to_dest | |
} | |
// Initializes a basic moving entity with movement speed `speed` | |
command m_init_basic_moving(speed) { | |
m_set_result (speed) | |
m_jsl (_SCR_initbasicmoving) | |
} | |
// Waits until a screen fade is done | |
command m_wait_fade m_jsl (_SCR_waitfade) | |
// Halts script execution until the player touches the entity | |
command m_wait_until_touch m_jsl (_SCR_waituntiltouch) | |
// Makes the entity invisible | |
command m_make_invisible m_set_anim (-1) | |
// Unlocks the text (CCScript) script after a "[1F 61]" control code | |
command m_unlock_text m_set_mem16 (0x9641, 1) | |
// Copies the entity's (X, Y) position to (VAR0, VAR1) | |
command m_copy_xy_to_var01 m_asmcall (0xC46C45) | |
// Instantly teleports the entity to its destination | |
command m_warp_to_dest m_asmcall (0xC46C87) | |
// Sets the entity's movement speed to the RESULT register | |
command m_set_speed_to_result m_asmcall (0xC0A68B) | |
// Stores the entity's facing direction into the RESULT register | |
command m_get_facing m_asmcall (0xC0A673) | |
// Sets the entity's facing direction from the RESULT register | |
command m_set_facing_to_result m_asmcall (0xC0A66D) | |
// Returns a random number in range 0..255 | |
command m_rand m_asmcall (0xC08E9A) | |
// Returns a random number in range 0..3 | |
command m_rand_mod4 m_asmcall (0xC0A633) | |
// Returns a random number in range 0..7 | |
command m_rand_mod8 m_asmcall (0xC0A63B) | |
// Returns `rand() << 8`, useful for getting a random angle value | |
command m_get_random_angle m_asmcall (0xC09FA8) | |
// Sets the RESULT register to the distance between the entity and the party leader | |
command m_get_distance_from_player m_asmcall (_ASM_distancefromplayer) | |
// Disables collisions with the entity | |
command m_disable_collision m_asmcall (0xC0A82F) | |
// Enables collisions with the entity | |
command m_enable_collision m_asmcall (0xC0A838) | |
// Calls the NPC's primary text script (undefined behavior if entity is not an NPC) | |
command m_call_npc_text m_asmcall (0xC4681A) | |
// Forces a refresh on the entity's graphics (use current frame) | |
// Well, I could just use 0xC0A480, but that does unnecessary setup wasting 33 cycles | |
command m_refresh_graphics m_asmcall (_ASM_refreshgraphics) | |
// Forces a refresh on the entity's graphics (use frame 0) | |
command m_refresh_graphics_frame0 m_asmcall (0xC0A4BF) | |
// Forces a refresh on the entity's graphics (use frame 1) | |
command m_refresh_graphics_frame1 m_asmcall (0xC0A4B2) | |
// Stores the entity's movement speed into the RESULT register | |
command m_get_speed m_asmcall (0xC0A691) | |
//***************************************************************************** | |
// PRIVATE ASM ROUTINES | |
//***************************************************************************** | |
//----- Local variables ------// | |
define _scr_ptr = 0x80 | |
define _scr_stack = 0x84 | |
// 0x86 is never used. It's probably safe to use, but I'm not risking it. | |
define _obj_offset = 0x88 | |
define _scr_offset = 0x8A | |
define _temp1 = 0x8C | |
define _temp2 = 0x8E | |
define _temp3 = 0x90 | |
define _temp4 = 0x92 | |
define _pc = 0x94 // $94 should not be used as a temp, it's already used to hold the "program counter" of the movement script | |
define _temp5 = 0x96 | |
define _temp6 = 0x98 | |
define _temp7 = 0x9A | |
define _temp8 = 0x9C | |
define _temp9 = 0x9E | |
define self_offset = 0x1A44 | |
define camera_x = 0x9877 | |
define camera_y = 0x987B | |
//----- Script variables ------// | |
define SCR_stack_offset = 0x12E6 | |
define SCR_pc = 0x13FE // Script program counter | |
define SCR_pb = 0x148A // Script program bank | |
define SCR_result = 0x1516 | |
//----- Entity variables ------// | |
define OBJ_map_x = 0x0B8E | |
define OBJ_map_y = 0x0BCA | |
define OBJ_vel_x = 0x0CF6 | |
define OBJ_vel_y = 0x0D32 | |
define OBJ_vel_xf = 0x0DAA | |
define OBJ_vel_yf = 0x0DE6 | |
define OBJ_anim_frame = 0x10F2 | |
define OBJ_speed = 0x2B32 | |
//----- MACROS ------// | |
// Ceils an 8.8 fixed-point number that's loaded in the accumulator | |
// Bit magic suggested by Alcaro on SnesLab ( https://canary.discord.com/channels/485971752992636929/486247695795879946/865718830603829248 ) | |
command _CEIL { | |
DEC | |
ORA_i (0x00FF) | |
INC | |
} | |
// Fetch byte and increment PC (8-bit accumulator) | |
command _READBYTE8 { | |
LDA_dly (_scr_ptr) | |
INY | |
} | |
// Fetch byte and increment PC (16-bit accumulator) | |
command _READBYTE { | |
_READBYTE8 | |
AND_i (0x00FF) | |
} | |
// Fetch word and increment PC | |
command _READWORD { | |
LDA_dly (_scr_ptr) | |
INY | |
INY | |
} | |
//----- Routines ------// | |
// Return distance from player | |
_ASM_distancefromplayer: { | |
LDX_d (_obj_offset) | |
LDA_a (camera_x) | |
SEC | |
SBC_x (OBJ_map_x) | |
BPL (4) | |
EOR_i (0xFFFF) | |
INC | |
STA_d (_temp1) | |
LDA_a (camera_y) | |
SEC | |
SBC_x (OBJ_map_y) | |
BPL (4) | |
EOR_i (0xFFFF) | |
INC | |
CLC | |
ADC_d (_temp1) | |
// return abs(OBJ_map_x - camera_x) + abs(OBJ_map_y - camera_y) | |
RTL | |
} | |
// return (result > argument) | |
_ASM_resultgreater: { | |
_READWORD | |
STY_d (_pc) | |
CMP_x (SCR_result) | |
LDA_i (0) // FALSE | |
BCS (1) | |
INC // TRUE | |
RTL | |
} | |
// ceil(movespeed) | |
_ASM_ceilspeed: { | |
LDX_d (_obj_offset) | |
LDA_x (OBJ_speed) | |
_CEIL | |
XBA | |
AND_i (0x00FF) | |
RTL | |
} | |
// max(result, value) | |
_ASM_mathmax: { | |
_READWORD | |
STY_d (_pc) | |
CMP_x (SCR_result) | |
BCS (3) | |
LDA_x (SCR_result) // 3 bytes | |
RTL | |
} | |
_ASM_mosaicin: { | |
_READWORD | |
PHA | |
_READWORD | |
TAX | |
_READWORD | |
STY_d (_pc) | |
TAY | |
PLA | |
JML (0xC087CE) | |
} | |
// Refresh graphics using current animation frame | |
_ASM_refreshgraphics: { | |
LDY_d (_obj_offset) | |
LDA_y (OBJ_anim_frame) | |
STA_a (0x2892) | |
JML (0xC0A4C4) | |
} | |
//***************************************************************************** | |
// PRIVATE MOVEMENT SCRIPT ROUTINES | |
//***************************************************************************** | |
_SCR_moveuntilatdest: { | |
m_asmcall (0xC46ADB) // Get angle towards destination | |
m_asmcall (0xC47044) // Set velocity based on angle (does not modify RESULT) | |
m_asmcall (0xC46B0A) // Set movement direction based on angle | |
m_asmcall (0xC0A65F) // Set facing direction | |
m_refresh_graphics | |
_loop: m_pause (1) // Wait 1 frame | |
m_asmcall (0xC0A8DC) // Move towards destination and check for proximity | |
m_jeq (_loop) // Go back if still not near destination | |
m_zerovel // Zero velocities when done | |
m_rtl | |
} | |
_SCR_initbasicmoving: { | |
m_set_speed_to_result | |
m_onmove (0xA360) // Move if not blocked and update surface flags | |
m_set_anim (0) | |
m_refresh_graphics_frame0 | |
m_task_long (MovTask_Anim16_DestroyIfFar) | |
m_task_long (MovTask_HandleCollision) | |
m_zerovel | |
m_rtl | |
} | |
_SCR_waituntiltouch: { | |
m_pause (1) | |
m_asmcall (0xC0D15C) // Return TRUE if this entity is colliding with the player | |
m_jeq (_SCR_waituntiltouch) | |
m_rtl | |
} | |
_SCR_waituntilnearself: { | |
m_pause (1) | |
m_asmcall (0xC46EF8) // Return TRUE if player is near self in radius (var2, var3) -- always FALSE when teleporting | |
m_jeq (_SCR_waituntilnearself) | |
m_rtl | |
} | |
_SCR_waituntilnear: { | |
m_pause (1) | |
m_asmcall (0xC46E74) // Return TRUE if player is near (var0, var1) in radius (var2, var3) -- always FALSE when teleporting | |
m_jeq (_SCR_waituntilnear) | |
m_rtl | |
} | |
_SCR_waitfade: { | |
m_pause (1) | |
m_get_mem16 (0x0028) // Screen fade amount | |
m_and_result (0x00FF) // 8-bit variable, so AND it with 0xFF | |
m_jne (_SCR_waitfade) // Go back if still fading in or out... | |
m_rtl | |
} | |
//***************************************************************************** | |
// CUSTOM MOVEMENT SCRIPT INSTRUCTION IMPLEMENTATION | |
//***************************************************************************** | |
// IMPLEMENTATION: m_task_long [31] | |
// $C097DC is the entry point for movement instruction 0x31 | |
// It's safe to overwrite until $C097EE (18 bytes) | |
ROM[0xC097DC] = { | |
JSR (0x99DD) // Call the original "m_task" movement instruction implementation | |
// Before we continue, we need to keep this in mind: | |
// 1. If there are no more script slots available, "m_task" fails silently (it just advances the program counter by 2) | |
// 2. In case of failure, the carry flag will be set. Otherwise, it will be clear | |
// 3. The offset of the task script will be in X, but only if "m_task" didn't fail | |
BCS (5) // Just increment PC by one if "m_task" failed "BCS_a (_ret)" | |
// No need for 8-bit accumulator, the high byte of the program bank is completely ignored in all cases | |
LDA_dly (_scr_ptr) // Fetch bank byte of task address | |
STA_x (SCR_pb) // Store it to the program bank of the new task script | |
_ret: INY | |
RTS | |
// 12 out of 18 bytes | |
} | |
// IMPLEMENTATION: m_store_result [32] | |
// $C097EF is the entry point for movement instruction 0x32 | |
// It's safe to overwrite until $C09801 (18 bytes) | |
ROM[0xC097EF] = { | |
TYX | |
LDY_d (_scr_offset) | |
LDA_y (SCR_result) | |
// Scripts have a 16 byte stack | |
// Our local storage will be at the absolute top of the stack, lowering the script stack capacity to 14 bytes... | |
LDY_i (14) | |
STA_diy (_scr_stack) | |
TXY | |
RTS | |
// 13 out of 18 bytes | |
} | |
// IMPLEMENTATION: m_load_result [33] | |
// $C09802 is the entry point for movement instruction 0x33 | |
// It's safe to overwrite until $C09825 (35 bytes) | |
ROM[0xC09802] = { | |
TYX | |
// Scripts have a 16 byte stack | |
// Our local storage will be at the absolute top of the stack, lowering the script stack capacity to 14 bytes... | |
LDY_i (14) | |
LDA_diy (_scr_stack) | |
LDY_d (_scr_offset) | |
STA_y (SCR_result) | |
TXY | |
RTS | |
// 13 out of 35 bytes | |
} | |
// IMPLEMENTATION: m_ondestroy [34] | |
// $C09826 is the entry point for movement instruction 0x34 | |
// It's safe to overwrite until $C09849 (35 bytes) | |
ROM[0xC09826] = { | |
LDX_d (_obj_offset) | |
_READWORD // 4 bytes | |
STA_x (OBJ_destructor_lo) | |
_READBYTE // 6 bytes | |
STA_x (OBJ_destructor_hi) | |
RTS | |
// 19 out of 35 bytes | |
} | |
// Patch so that the game calls the destructor when an entity is destroyed | |
// Initialize destructor to NULL pointer on entity creation | |
ROM[0xC020E7] = { | |
JSL (_nulldestructor) | |
NOP | |
NOP | |
} | |
_nulldestructor: { | |
STZ_x (OBJ_destructor_lo) | |
STZ_x (OBJ_destructor_hi) | |
// ORIGINAL CODE | |
STZ_x (0x2AF6) | |
STZ_x (0x28DA) | |
// ORIGINAL CODE | |
RTL | |
} | |
// "destroy current entity" (used by movement scripts) | |
/* | |
* C0/2109: A2 00 00 LDX #$0000 | |
* C0/210C: A5 02 LDA $02 | |
*/ | |
ROM[0xC02109] = { | |
JSL (_calldestructor) | |
NOP | |
} | |
// "destroy arbitrary entity" (used by ASM) | |
/* | |
* C0/2157: A2 00 00 LDX #$0000 | |
* C0/215A: A5 02 LDA $02 | |
*/ | |
ROM[0xC02157] = { | |
JSL (_calldestructor) | |
NOP | |
} | |
_calldestructor: { | |
LDY_d (0x0E) | |
LDA_y (OBJ_destructor_lo) | |
ORA_y (OBJ_destructor_hi) | |
BEQ_a (_ret) // Return if destructor is a NULL pointer | |
// Allocate a few local variables for the destructor | |
PHD | |
TDC | |
SEC | |
SBC_i (32) // Give DP locals $00-$1F for free to the destructor | |
TCD | |
LDA_y (OBJ_destructor_lo) | |
STA_a (0x00BC) | |
LDA_y (OBJ_destructor_hi) | |
STA_a (0x00BE) | |
TYA // Pass the entity offset to the destructor | |
JSL (0xC09279) // Call ASM pointer from $00BC | |
PLD | |
_ret: // ORIGINAL CODE | |
LDX_i (0) | |
LDA_d (0x02) | |
// ORIGINAL CODE | |
RTL | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asm65816 | |
import movscr_codes | |
/* | |
* Movement script examples | |
* | |
* This file includes 3 simple sample scripts that you can use | |
* as a reference for building your very own scripts. | |
* | |
* NOTE: This file will also overwrite the "Who are you talking to?" | |
* text, causing it to spawn 3 sprites using these 3 sample scripts | |
*/ | |
// Repoint "Who are you talking to?" text | |
ROM[0xC7C588] = goto(StartTests) | |
StartTests: { | |
"[1F 15 {short 206} {short DVD_LOGO} {byte 1}]" // Taxi | |
"[1F 15 {short 25} {short TOUCH_SOUND} {byte 1}]" // Robot | |
"[1F 15 {short 3} {short UNIT_TESTS} {byte 1}]" // Jeff | |
eob | |
} | |
//***************************************************************************** | |
// SAMPLE #1 (TEST) | |
define DVD_LOGO = 895 | |
define next_obj_x = 0x2848 // Next frame object's X position (see $C09EFF) | |
define next_obj_y = 0x284A // Next frame object's Y position (see $C09EFF) | |
// Bounce around walls, DVD Logo style | |
M_DvdLogo: { | |
m_warp_to_leader | |
m_disable_collision | |
m_set_speed (0x0200) | |
m_set_anim (0) | |
m_refresh_graphics_frame0 | |
m_task_long (MovTask_Anim16_DestroyIfFar) | |
m_get_random_angle | |
m_asmcall (0xC47044) // Set velocity based on angle | |
m_asmcall (0xC46B0A) // Set entity movement direction based on angle. Returns the direction | |
m_asmcall (0xC0A65F) // Set entity facing if not blocked | |
loop: m_asmcall (_ASM_BounceDvd) // Returns zero if there wasn't a wall hit | |
m_jeq (nohit) | |
// There was a wall hit, reverse the facing | |
m_reverse_facing | |
m_refresh_graphics | |
nohit: m_pause (1) | |
m_jmp (loop) | |
_ASM_BounceDvd: | |
JSL (0xC09F04) // Store pos+vel into $2848 and $284A | |
TAX // Set Z flag on accumulator value | |
BEQ_a (_Return) // Didn't move, return | |
STZ_d (0x00) // Clear "hit wall" flag | |
LDY_d (_obj_offset) | |
LDX_y (OBJ_map_y) | |
LDA_a (next_obj_x) | |
JSL (0xC05F82) // Get surface flags at coordinate | |
LDY_d (_obj_offset) | |
AND_i (0x0080) // SOLID? | |
BEQ_a (_CheckY) // No, check Y axis | |
// Yes, negate X velocities | |
INC_d (0x00) // Set "hit wall" flag | |
SEC | |
LDA_i (0) | |
SBC_y (OBJ_vel_xf) | |
STA_y (OBJ_vel_xf) | |
LDA_i (0) | |
SBC_y (OBJ_vel_x) | |
STA_y (OBJ_vel_x) | |
_CheckY: | |
LDX_a (next_obj_y) | |
LDA_y (OBJ_map_x) | |
JSL (0xC05F82) | |
AND_i (0x0080) | |
BEQ_a (_ReturnValue) | |
INC_d (0x00) // Set "hit wall" flag | |
LDY_d (_obj_offset) | |
SEC | |
LDA_i (0) | |
SBC_y (OBJ_vel_yf) | |
STA_y (OBJ_vel_yf) | |
LDA_i (0) | |
SBC_y (OBJ_vel_y) | |
STA_y (OBJ_vel_y) | |
_ReturnValue: | |
LDA_d (0x00) | |
_Return: | |
RTL | |
} | |
//***************************************************************************** | |
// SAMPLE #2 (TOUCH SOUND) | |
define TOUCH_SOUND = 896 | |
M_TouchSound: { | |
m_warp_to_leader | |
m_add_xpos (-32) | |
m_add_ypos (32) | |
m_set_anim (0) | |
m_refresh_graphics_frame0 | |
m_task_long (MovTask_Anim16_DestroyIfFar) | |
loop: m_wait_until_touch | |
m_sound (73) // "ping" sound (Sky Runner and Devil's Machine shield) | |
m_pause (32) | |
m_jmp (loop) | |
} | |
//***************************************************************************** | |
// SAMPLE #3 (UNIT TESTS) | |
// Very limited tests, only checks the "happy path" | |
define UNIT_TESTS = 897 | |
M_UnitTests: { | |
m_warp_to_leader | |
m_add_xpos (32) | |
m_add_ypos (32) | |
m_set_anim (0) | |
m_refresh_graphics_frame0 | |
m_task_long (MovTask_Anim16_DestroyIfFar) | |
m_ondestroy (_ASM_TestDestructor) | |
m_wait_until_touch | |
m_textcall2 (STR_StartingTests) | |
m_jsr (SUB_TestResultGreater) | |
m_jeq (l1) // Skip m_choose_random if m_result_greater failed | |
m_jsr (SUB_TestChooseRandom) | |
l1: m_jsr (SUB_TestFade) | |
m_jsr (SUB_TestStorage) | |
loop: m_set_dest_leader | |
m_face_dest | |
m_refresh_graphics | |
m_pause (8) | |
m_jmp (loop) | |
_ASM_TestDestructor: | |
MText(_STR_Destructor) | |
RTL | |
_STR_Destructor: | |
window_open(1) | |
"@Test destructor called!" wait | |
window_closetop eob | |
} | |
TestFailed: { | |
FAILED | |
m_rts | |
} | |
//***************************************************************************** | |
// TEST m_result_greater | |
//***************************************************************************** | |
SUB_TestResultGreater: { | |
m_textcall2 (STR_ResultGreater) | |
m_set_result (1234) | |
m_result_greater (1233) | |
m_jeq (TestFailed) | |
m_set_result (1234) | |
m_result_greater (1234) | |
m_jne (TestFailed) | |
m_set_result (1234) | |
m_result_greater (1235) | |
m_jne (TestFailed) | |
SUCCESS | |
m_rts | |
} | |
//***************************************************************************** | |
// TEST m_choose_random | |
//***************************************************************************** | |
// Because of the random nature, I'm only testing if the chosen number is in range | |
SUB_TestChooseRandom: { | |
m_textcall2 (STR_ChooseRandom) | |
m_loop (200) // 200 iterations. This is because of the random nature of the test | |
m_choose_random_2 (0, 1) | |
m_result_greater (1) | |
m_jne (TestFailed) | |
m_choose_random_3 (0, 1, 2) | |
m_result_greater (2) | |
m_jne (TestFailed) | |
m_choose_random_4 (0, 1, 2, 3) | |
m_result_greater (3) | |
m_jne (TestFailed) | |
m_choose_random_5 (0, 1, 2, 3, 4) | |
m_result_greater (4) | |
m_jne (TestFailed) | |
m_choose_random_6 (0, 1, 2, 3, 4, 5) | |
m_result_greater (5) | |
m_jne (TestFailed) | |
m_choose_random_7 (0, 1, 2, 3, 4, 5, 6) | |
m_result_greater (6) | |
m_jne (TestFailed) | |
m_choose_random_8 (0, 1, 2, 3, 4, 5, 6, 7) | |
m_result_greater (7) | |
m_jne (TestFailed) | |
m_endloop | |
SUCCESS | |
m_rts | |
} | |
//***************************************************************************** | |
// TEST m_fadein, m_wait_fade, m_fadeout and m_mosaic_out | |
//***************************************************************************** | |
SUB_TestFade: { | |
m_textcall2 (STR_Fade) | |
m_fadeout (1, 2) | |
m_wait_fade | |
m_fadein (1, 2) | |
m_wait_fade | |
m_pause (30) | |
m_mosaic_out (1, 2, 0x03) | |
m_mosaic_in (1, 2, 0x03) | |
SUCCESS | |
m_rts | |
} | |
//***************************************************************************** | |
// TEST m_store_result, m_load_result | |
//***************************************************************************** | |
SUB_TestStorage: { | |
m_textcall2 (STR_Storage) | |
m_set_result (1234) | |
m_store_result // Store 1234 | |
m_set_result (5678) // Set the result to something else | |
m_jsr (dummy1) // Mess around with the stack... | |
m_load_result // Load 1234 back | |
m_add_result (-1234) | |
m_jne (TestFailed) // Fail if 1234-1234 != 0 | |
SUCCESS | |
m_rts | |
// Mess aorund with the stack | |
dummy1: m_jsl (dummy2) | |
m_rts | |
dummy2: m_loop (10) | |
m_endloop | |
m_rtl | |
} | |
//***************************************************************************** | |
// STRINGS | |
//***************************************************************************** | |
STR_StartingTests: window_open(1) "@Starting tests..." newline end | |
STR_ResultGreater: window_open(1) "@m-result-greater..." newline eob | |
STR_ChooseRandom: window_open(1) "@m-choose-random..." newline eob | |
STR_Fade: window_open(1) "@m-fade..." newline eob | |
STR_Storage: window_open(1) "@m-store-result..." newline eob | |
STR_Success: "@Success." wait window_closetop eob | |
STR_Failed: "@Failed." wait window_closetop eob | |
//***************************************************************************** | |
// VARIOUS HELPER MACROS | |
//***************************************************************************** | |
command SUCCESS { | |
m_textcall2 (STR_Success) | |
m_set_result (1) | |
} | |
command FAILED { | |
m_textcall2 (STR_Failed) | |
m_set_result (0) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment