197 | | { 0x00, "c1_goToLine", true }, |
198 | | { 0x01, "c1_setReturn", true }, |
199 | | { 0x02, "c1_pushRetRec", true }, |
200 | | { 0x03, "c1_push", true }, |
201 | | { 0x04, "c1_push", true }, |
202 | | { 0x05, "c1_pushVar", true }, |
203 | | { 0x06, "c1_pushFrameNeg", true }, |
204 | | { 0x07, "c1_pushFramePos", true }, |
205 | | { 0x08, "c1_popRetRec", true }, |
206 | | { 0x09, "c1_popVar", true }, |
207 | | { 0x0A, "c1_popFrameNeg", true }, |
208 | | { 0x0B, "c1_popFramePos", true }, |
209 | | { 0x0C, "c1_addToSP", true }, |
210 | | { 0x0D, "c1_subFromSP", true }, |
211 | | { 0x0E, "c1_execOpcode", true }, |
212 | | { 0x0F, "c1_ifNotGoTo", true }, |
213 | | { 0x10, "c1_negate", true }, |
214 | | { 0x11, "c1_evaluate", true }, |
| 194 | { 0x00, "goToLine", true }, |
| 195 | { 0x01, "setReturn", true }, |
| 196 | { 0x02, "pushRetRec", true }, |
| 197 | { 0x03, "push", true }, |
| 198 | { 0x04, "push", true }, |
| 199 | { 0x05, "pushVar", true }, |
| 200 | { 0x06, "pushFrameNeg", true }, |
| 201 | { 0x07, "pushFramePos", true }, |
| 202 | { 0x08, "popRetRec", true }, |
| 203 | { 0x09, "popVar", true }, |
| 204 | { 0x0A, "popFrameNeg", true }, |
| 205 | { 0x0B, "popFramePos", true }, |
| 206 | { 0x0C, "addToSP", true }, |
| 207 | { 0x0D, "subFromSP", true }, |
| 208 | { 0x0E, "execOpcode", true }, |
| 209 | { 0x0F, "ifNotGoTo", true }, |
| 210 | { 0x10, "negate", true }, |
| 211 | { 0x11, "evaluate", true }, |
230 | | { 0x68, "0x68", "int" } |
| 227 | { 0x00 ,"o1_Magic_In_Mouse_Item" }, |
| 228 | { 0x01 ,"o1_Character_Says" }, |
| 229 | { 0x02 ,"o1_Pause_Ticks" }, |
| 230 | { 0x03 ,"o1_Draw_Scene_Anim_Shape" }, |
| 231 | { 0x04 ,"o1_Query_Game_Flag" }, |
| 232 | { 0x05 ,"o1_Set_Game_Flag" }, |
| 233 | { 0x06 ,"o1_Reset_Game_Flag" }, |
| 234 | { 0x07 ,"o1_Run_NPC_Script" }, |
| 235 | { 0x08 ,"o1_Set_Special_Exit_List" }, |
| 236 | { 0x09 ,"o1_Block_In_Walkable_Region" }, |
| 237 | { 0x0A ,"o1_Block_Out_Walkable_Region" }, |
| 238 | { 0x0B ,"o1_Walk_Player_To_Point" }, |
| 239 | { 0x0C ,"o1_Drop_Item_In_Scene" }, |
| 240 | { 0x0D ,"o1_Draw_Anim_Shape_Into_Scene" }, |
| 241 | { 0x0E ,"o1_Create_Mouse_Item" }, |
| 242 | { 0x0F ,"o1_Save_Page_To_Disk" }, |
| 243 | { 0x10 ,"o1_Load_Page_From_Disk" }, |
| 244 | { 0x11 ,"o1_Scene_Anim_On" }, |
| 245 | { 0x12 ,"o1_Scene_Anim_Off" }, |
| 246 | { 0x13 ,"o1_Elapsed_Seconds" }, |
| 247 | { 0x14 ,"o1_Mouse_Is_Pointer" }, |
| 248 | { 0x15 ,"o1_Destroy_Mouse_Item" }, |
| 249 | { 0x16 ,"o1_Run_Scene_Anim_Until_Done" }, |
| 250 | { 0x17 ,"o1_Fade_Special_Palette" }, |
| 251 | { 0x18 ,"o1_Play_AdLib_Sound" }, |
| 252 | { 0x19 ,"o1_Play_AdLib_Score" }, |
| 253 | { 0x1A ,"o1_Phase_In_Same_Scene" }, |
| 254 | { 0x1B ,"o1_Set_Scene_Phasing_Flag" }, |
| 255 | { 0x1C ,"o1_Reset_Scene_Phasing_Flag" }, |
| 256 | { 0x1D ,"o1_Query_Scene_Phasing_Flag" }, |
| 257 | { 0x1E ,"o1_Scene_To_Direction" }, |
| 258 | { 0x1F ,"o1_Set_Birthstone_Gem" }, |
| 259 | { 0x20 ,"o1_Place_Item_In_Generic_Map_Scene" }, |
| 260 | { 0x21 ,"o1_Set_Brandon_Status_Bit" }, |
| 261 | { 0x22 ,"o1_Pause_Seconds" }, |
| 262 | { 0x23 ,"o1_Get_Characters_Location" }, |
| 263 | { 0x24 ,"o1_Run_NPC_Subscript" }, |
| 264 | { 0x25 ,"o1_Magic_Out_Mouse_Item" }, |
| 265 | { 0x26 ,"o1_Internal_Anim_On" }, |
| 266 | { 0x27 ,"o1_Force_Brandon_To_Normal" }, |
| 267 | { 0x28 ,"o1_Poison_Death_Now" }, |
| 268 | { 0x29 ,"o1_Set_Scale_Mode" }, |
| 269 | { 0x2A ,"o1_Open_WSA_File" }, |
| 270 | { 0x2B ,"o1_Close_WSA_File" }, |
| 271 | { 0x2C ,"o1_Run_WSA_From_Beginning_To_End" }, |
| 272 | { 0x2D ,"o1_Display_WSA_Frame" }, |
| 273 | { 0x2E ,"o1_Enter_New_Scene" }, |
| 274 | { 0x2F ,"o1_Set_Special_Enter_X_And_Y" }, |
| 275 | { 0x30 ,"o1_Run_WSA_Frames" }, |
| 276 | { 0x31 ,"o1_Pop_Brandon_Into_Scene" }, |
| 277 | { 0x32 ,"o1_Restore_All_Object_Backgrounds" }, |
| 278 | { 0x33 ,"o1_Set_Custom_Palette_Range" }, |
| 279 | { 0x34 ,"o1_Custom_Print_Talk_String" }, |
| 280 | { 0x35 ,"o1_Restore_Custom_Print_Background" }, |
| 281 | { 0x36 ,"o1_Hide_Mouse" }, |
| 282 | { 0x37 ,"o1_Show_Mouse" }, |
| 283 | { 0x38 ,"o1_Get_Character_X" }, |
| 284 | { 0x39 ,"o1_Get_Character_Y" }, |
| 285 | { 0x3A ,"o1_Change_Characters_Facing" }, |
| 286 | { 0x3B ,"o1_Copy_WSA_Region" }, |
| 287 | { 0x3C ,"o1_Text_Print" }, |
| 288 | { 0x3D ,"o1_Random" }, |
| 289 | { 0x3E ,"o1_Load_Sound_File" }, |
| 290 | { 0x3F ,"o1_Display_WSA_Frame_On_HidPage" }, |
| 291 | { 0x40 ,"o1_Display_WSA_Sequential_Frames" }, |
| 292 | { 0x41 ,"o1_Draw_Character_Standing" }, |
| 293 | { 0x42 ,"o1_Internal_Anim_Off" }, |
| 294 | { 0x43 ,"o1_Change_Characters_X_And_Y" }, |
| 295 | { 0x44 ,"o1_Clear_Scene_Animator_Beacon" }, |
| 296 | { 0x45 ,"o1_Query_Scene_Animator_Beacon" }, |
| 297 | { 0x46 ,"o1_Refresh_Scene_Animator" }, |
| 298 | { 0x47 ,"o1_Place_Item_In_Off_Scene" }, |
| 299 | { 0x48 ,"o1_Wipe_Down_Mouse_Item" }, |
| 300 | { 0x49 ,"o1_Place_Character_In_Other_Scene" }, |
| 301 | { 0x4A ,"o1_Get_Key" }, |
| 302 | { 0x4B ,"o1_Specific_Item_In_Inventory" }, |
| 303 | { 0x4C ,"o1_Pop_Mobile_NPC_Into_Scene" }, |
| 304 | { 0x4D ,"o1_Mobile_Character_In_Scene" }, |
| 305 | { 0x4E ,"o1_Hide_Mobile_Character" }, |
| 306 | { 0x4F ,"o1_Unhide_Mobile_Character" }, |
| 307 | { 0x50 ,"o1_Set_Characters_Location" }, |
| 308 | { 0x51 ,"o1_Walk_Character_To_Point" }, |
| 309 | { 0x52 ,"o1_Special_Event_Display_Brynns_Note" }, |
| 310 | { 0x53 ,"o1_Special_Event_Remove_Brynns_Note" }, |
| 311 | { 0x54 ,"o1_Set_Logic_Page" }, |
| 312 | { 0x55 ,"o1_Fat_Print" }, |
| 313 | { 0x56 ,"o1_Preserve_All_Object_Backgrounds" }, |
| 314 | { 0x57 ,"o1_Update_Scene_Animations" }, |
| 315 | { 0x58 ,"o1_Scene_Animation_Active" }, |
| 316 | { 0x59 ,"o1_Set_Characters_Movement_Delay" }, |
| 317 | { 0x5A ,"o1_Get_Characters_Facing" }, |
| 318 | { 0x5B ,"o1_Bkgd_Scroll_Scene_And_Masks_Right" }, |
| 319 | { 0x5C ,"o1_Find_Brightest_Fireberry" }, |
| 320 | { 0x5D ,"o1_Set_Fireberry_Glow_Palette" }, |
| 321 | { 0x5E ,"o1_Set_Death_Handler_Flag" }, |
| 322 | { 0x5F ,"o1_Drink_Potion_Animation" }, |
| 323 | { 0x60 ,"o1_Make_Amulet_Appear" }, |
| 324 | { 0x61 ,"o1_Draw_Item_Shape_Into_Scene" }, |
| 325 | { 0x62 ,"o1_Set_Characters_Current_Frame" }, |
| 326 | { 0x63 ,"o1_Wait_For_Confirmation_Mouse_Click" }, |
| 327 | { 0x64 ,"o1_Page_Flip" }, |
| 328 | { 0x65 ,"o1_Set_Scene_File" }, |
| 329 | { 0x66 ,"o1_What_Item_In_Marble_Vase" }, |
| 330 | { 0x67 ,"o1_Set_Item_In_Marble_Vase" }, |
| 331 | { 0x68 ,"o1_Add_Item_To_Inventory" }, |
| 332 | { 0x69 ,"o1_Int_Print" }, |
| 333 | { 0x6A ,"o1_Shake_Screen" }, |
| 334 | { 0x6B ,"o1_Create_Amulet_Jewel" }, |
| 335 | { 0x6C ,"o1_Set_Scene_Anim_Curr_XY" }, |
| 336 | { 0x6D ,"o1_Poison_Brandon_And_Remaps" }, |
| 337 | { 0x6E ,"o1_Fill_Flask_With_Water" }, |
| 338 | { 0x6F ,"o1_Get_Characters_Movement_Delay" }, |
| 339 | { 0x70 ,"o1_Get_Birthstone_Gem" }, |
| 340 | { 0x71 ,"o1_Query_Brandon_Status_Bit" }, |
| 341 | { 0x72 ,"o1_Play_Flute_Animation" }, |
| 342 | { 0x73 ,"o1_Play_Winter_Scroll_Sequence" }, |
| 343 | { 0x74 ,"o1_Get_Idol_Gem" }, |
| 344 | { 0x75 ,"o1_Set_Idol_Gem" }, |
| 345 | { 0x76 ,"o1_Total_Items_In_Scene" }, |
| 346 | { 0x77 ,"o1_Restore_Brandons_Movement_Delay" }, |
| 347 | { 0x78 ,"o1_Set_Mouse_Pos" }, |
| 348 | { 0x79 ,"o1_Get_Mouse_State" }, |
| 349 | { 0x7A ,"o1_Set_Entrance_Mouse_Cursor_Track" }, |
| 350 | { 0x7B ,"o1_Item_Appears_On_Ground" }, |
| 351 | { 0x7C ,"o1_Set_No_Draw_Shapes_Flag" }, |
| 352 | { 0x7D ,"o1_Fade_Entire_Palette" }, |
| 353 | { 0x7E ,"o1_Item_On_Ground_Here" }, |
| 354 | { 0x7F ,"o1_Query_Cauldron_State" }, |
| 355 | { 0x80 ,"o1_Set_Cauldron_State" }, |
| 356 | { 0x81 ,"o1_Query_Crystal_State" }, |
| 357 | { 0x82 ,"o1_Set_Crystal_State" }, |
| 358 | { 0x83 ,"o1_Set_Palette_Range" }, |
| 359 | { 0x84 ,"o1_Shrink_Brandon_Down" }, |
| 360 | { 0x85 ,"o1_Grow_Brandon_Up" }, |
| 361 | { 0x86 ,"o1_Set_Brandon_Scale_X_And_Y" }, |
| 362 | { 0x87 ,"o1_Reset_Scale_Mode" }, |
| 363 | { 0x88 ,"o1_Get_Scale_Depth_Table_Value" }, |
| 364 | { 0x89 ,"o1_Set_Scale_Depth_Table_Value" }, |
| 365 | { 0x8A ,"o1_Message" }, |
| 366 | { 0x8B ,"o1_Check_Click_On_NPC" }, |
| 367 | { 0x8C ,"o1_Get_Foyer_Item" }, |
| 368 | { 0x8D ,"o1_Set_Foyer_Item" }, |
| 369 | { 0x8E ,"o1_Dispel_Magic_Animation" }, |
| 370 | { 0x8F ,"o1_Set_No_Item_Drop_Region" }, |
| 371 | { 0x90 ,"o1_Walk_Malcolm_On" }, |
| 372 | { 0x91 ,"o1_Passive_Protection" }, |
| 373 | { 0x92 ,"o1_Set_Playing_Loop" }, |
| 374 | { 0x93 ,"o1_Brandon_To_Stone_Sequence" }, |
| 375 | { 0x94 ,"o1_Brandon_Healing_Sequence" }, |
| 376 | { 0x95 ,"o1_Protect_Command_Line" }, |
| 377 | { 0x96 ,"o1_Pause_Music_Seconds" }, |
| 378 | { 0x97 ,"o1_Reset_Mask_Region" }, |
| 379 | { 0x98 ,"o1_Set_Palette_Change_Flag" }, |
| 380 | { 0x99 ,"o1_Fill_Rect" }, |
| 381 | { 0x9A ,"o1_Dummy" } |
| 510 | |
| 511 | int32 Script::param(int32 index) { |
| 512 | if (_stackPos - index - 1 >= ARRAYSIZE(_stack) || _stackPos - index - 1 < 0) |
| 513 | return -0xFFFF; |
| 514 | return _stack[_stackPos - index - 1]; |
| 515 | } |
| 516 | |
| 517 | const char* Script::stringAtIndex(int32 index) { |
| 518 | if (index < 0 || (uint32)index >= _chunks[kText]._size) |
| 519 | return 0; |
| 520 | |
| 521 | uint16 offset = TO_BE_16(((uint16*)_chunks[kText]._data)[index]); |
| 522 | return (const char *)(_chunks[kText]._data + offset); |
| 523 | } |
| 524 | |
| 525 | const char* Script::getParamsOnStack(void) { |
| 526 | static char buffer[1024]; |
| 527 | memset(buffer, 0, 1024 * sizeof(char)); |
| 528 | |
| 529 | strcpy(buffer, " "); |
| 530 | |
| 531 | for (int32 pos = 0; param(pos) != -0xFFFF; ++pos) { |
| 532 | if (pos != 0) |
| 533 | strcat(buffer, ", "); |
| 534 | char _buffer[128]; |
| 535 | sprintf(_buffer, "[%d | %s]", param(pos), paramString(pos)); |
| 536 | strcat(buffer, _buffer); |
| 537 | } |
| 538 | |
| 539 | strcat(buffer, " "); |
| 540 | |
| 541 | return buffer; |
| 542 | } |
| 543 | |
| 544 | void Script::execCommand(uint32 command) { |
| 545 | #define COMMAND(x) { &Script::x } |
| 546 | typedef void (Script::*CommandProc)(); |
| 547 | struct CommandEntry { |
| 548 | CommandProc proc; |
| 549 | }; |
| 550 | |
| 551 | // now we create a list of all Command/Opcode procs and so |
| 552 | static CommandEntry commandProcs[] = { |
| 553 | // 0x00 |
| 554 | COMMAND(goToLine), |
| 555 | COMMAND(setReturn), |
| 556 | COMMAND(pushRetRec), |
| 557 | COMMAND(push), |
| 558 | // 0x04 |
| 559 | COMMAND(push), |
| 560 | COMMAND(pushVar), |
| 561 | COMMAND(pushFrameNeg), |
| 562 | COMMAND(pushFramePos), |
| 563 | // 0x08 |
| 564 | COMMAND(popRetRec), |
| 565 | COMMAND(popVar), |
| 566 | COMMAND(popFrameNeg), |
| 567 | COMMAND(popFramePos), |
| 568 | // 0x0C |
| 569 | COMMAND(addToSP), |
| 570 | COMMAND(subFromSP), |
| 571 | COMMAND(execOpcode), |
| 572 | COMMAND(ifNotGoTo), |
| 573 | // 0x10 |
| 574 | COMMAND(negate), |
| 575 | COMMAND(evaluate) |
| 576 | }; |
| 577 | |
| 578 | static uint16 _numCommands = ARRAYSIZE(commandProcs); |
| 579 | static CommandEntry* _commands = commandProcs; |
| 580 | |
| 581 | if (command < _numCommands) { |
| 582 | CommandProc currentProc = _commands[command].proc; |
| 583 | (this->*currentProc)(); |
| 584 | } |
| 585 | } |
| 586 | |
| 587 | void Script::goToLine(void) { |
| 588 | _instructionPos = _argument << 1; |
| 589 | } |
| 590 | |
| 591 | void Script::setReturn(void) { |
| 592 | _returnValue = _argument; |
| 593 | } |
| 594 | |
| 595 | void Script::pushRetRec(void) { |
| 596 | if (!_argument) { |
| 597 | pushStack(_returnValue); |
| 598 | } else { |
| 599 | int32 rec = ((int16)_tempPos << 16) | ((_instructionPos >> 1) + 1); |
| 600 | pushStack(rec); |
| 601 | _tempPos = _instructionPos; |
| 602 | } |
| 603 | } |
| 604 | |
| 605 | void Script::push(void) { |
| 606 | pushStack(_argument); |
| 607 | } |
| 608 | |
| 609 | void Script::pushVar(void) { |
| 610 | printf("position = %d ", _stackPos); |
| 611 | int32 value = _registers[_argument]; |
| 612 | printf("value = %d ", value); |
| 613 | pushStack(value); |
| 614 | } |
| 615 | |
| 616 | void Script::pushFrameNeg(void) { |
| 617 | pushStack(_stack[_tempPos + _argument]); |
| 618 | } |
| 619 | |
| 620 | void Script::pushFramePos(void) { |
| 621 | pushStack(_stack[_tempPos - _argument]); |
| 622 | } |
| 623 | |
| 624 | void Script::popRetRec(void) { |
| 625 | if (!_argument) { |
| 626 | _returnValue = popStack(); |
| 627 | } else { |
| 628 | if (_stackPos <= 0) { |
| 629 | _instructionPos = 0xFFFF; |
| 630 | return; |
| 631 | } |
| 632 | int32 rec = popStack(); |
| 633 | |
| 634 | _tempPos = (int16)((rec & 0xFFFF0000) >> 16); |
| 635 | _instructionPos = (rec & 0x0000FFFF) * 2; |
| 636 | } |
| 637 | } |
| 638 | |
| 639 | void Script::popVar(void) { |
| 640 | _registers[_argument] = popStack(); |
| 641 | } |
| 642 | |
| 643 | void Script::popFrameNeg(void) { |
| 644 | _stack[_tempPos + _argument] = popStack(); |
| 645 | } |
| 646 | |
| 647 | void Script::popFramePos(void) { |
| 648 | _stack[_tempPos - _argument] = popStack(); |
| 649 | } |
| 650 | |
| 651 | void Script::addToSP(void) { |
| 652 | _stackPos -= _argument; |
| 653 | } |
| 654 | |
| 655 | void Script::subFromSP(void) { |
| 656 | _stackPos += _argument; |
| 657 | } |
| 658 | |
| 659 | void Script::execOpcode(void) { |
| 660 | } |
| 661 | |
| 662 | void Script::ifNotGoTo(void) { |
| 663 | if (!popStack()) { |
| 664 | _instructionPos = _argument << 1; |
| 665 | } |
| 666 | } |
| 667 | |
| 668 | void Script::negate(void) { |
| 669 | switch(_argument) { |
| 670 | case 0: |
| 671 | topStack() = !topStack(); |
| 672 | break; |
| 673 | |
| 674 | case 1: |
| 675 | topStack() = -topStack(); |
| 676 | break; |
| 677 | |
| 678 | case 2: |
| 679 | topStack() = ~topStack(); |
| 680 | break; |
| 681 | |
| 682 | default: |
| 683 | printf("ERROR: unkown negate instruction %d\n", _argument); |
| 684 | break; |
| 685 | }; |
| 686 | } |
| 687 | |
| 688 | void Script::evaluate(void) { |
| 689 | int32 x, y; |
| 690 | int32 res = false; |
| 691 | |
| 692 | x = popStack(); |
| 693 | y = popStack(); |
| 694 | |
| 695 | switch(_argument) { |
| 696 | case 0: |
| 697 | res = x && y; |
| 698 | break; |
| 699 | |
| 700 | case 1: |
| 701 | res = x || y; |
| 702 | break; |
| 703 | |
| 704 | case 2: |
| 705 | res = x == y; |
| 706 | break; |
| 707 | |
| 708 | case 3: |
| 709 | res = x != y; |
| 710 | break; |
| 711 | |
| 712 | case 4: |
| 713 | res = x < y; |
| 714 | break; |
| 715 | |
| 716 | case 5: |
| 717 | res = x <= y; |
| 718 | break; |
| 719 | |
| 720 | case 6: |
| 721 | res = x > y; |
| 722 | break; |
| 723 | |
| 724 | case 7: |
| 725 | res = x >= y; |
| 726 | break; |
| 727 | |
| 728 | case 8: |
| 729 | res = x + y; |
| 730 | break; |
| 731 | |
| 732 | case 9: |
| 733 | res = x - y; |
| 734 | break; |
| 735 | |
| 736 | case 10: |
| 737 | res = x * y; |
| 738 | break; |
| 739 | |
| 740 | case 11: |
| 741 | res = x / y; |
| 742 | break; |
| 743 | |
| 744 | case 12: |
| 745 | res = x >> y; |
| 746 | break; |
| 747 | |
| 748 | case 13: |
| 749 | res = x << y; |
| 750 | break; |
| 751 | |
| 752 | case 14: |
| 753 | res = x & y; |
| 754 | break; |
| 755 | |
| 756 | case 15: |
| 757 | res = x | y; |
| 758 | break; |
| 759 | |
| 760 | case 16: |
| 761 | res = x % y; |
| 762 | break; |
| 763 | |
| 764 | case 17: |
| 765 | res = x ^ y; |
| 766 | break; |
| 767 | |
| 768 | default: |
| 769 | printf("ERROR: unknown evaluate command %d\n", _argument); |
| 770 | break; |
| 771 | }; |
| 772 | |
| 773 | pushStack(res); |
| 774 | } |
| 775 | |