#!/usr/bin/env ruby require "scanf" require "common.rb" filename = ARGV[0] offset = ARGV[1].scanf("%x")[0] NUM_STATES=1206 # Locations of action pointer functions for Heretic 1.0. Hand-constructed. # # ./dump-states heretic.exe 8bf04 ACTION_POINTERS_1_0 = { 78512 => "A_FreeTargMobj", 82048 => "A_RestoreSpecialThing1", 82128 => "A_RestoreSpecialThing2", 78736 => "A_HideThing", 78752 => "A_UnHideThing", 81952 => "A_RestoreArtifact", 76144 => "A_Scream", 76784 => "A_Explode", 76896 => "A_PodPain", 77056 => "A_RemovePod", 77104 => "A_MakePod", 77728 => "A_InitKeyGizmo", 77824 => "A_VolcanoSet", 77856 => "A_VolcanoBlast", 70480 => "A_BeastPuff", 78080 => "A_VolcBallImpact", 77520 => "A_SpawnTeleGlitter", 77600 => "A_SpawnTeleGlitter2", 77680 => "A_AccTeleGlitter", 117648 => "A_Light0", 111168 => "A_WeaponReady", 111760 => "A_Lower", 111920 => "A_Raise", 112640 => "A_StaffAttackPL1", 111696 => "A_ReFire", 112784 => "A_StaffAttackPL2", 111568 => "A_BeakReady", 111856 => "A_BeakRaise", 112272 => "A_BeakAttackPL1", 112448 => "A_BeakAttackPL2", 117184 => "A_GauntletAttack", 112928 => "A_FireBlasterPL1", 113072 => "A_FireBlasterPL2", 115088 => "A_SpawnRippers", 113760 => "A_FireMacePL1", 114624 => "A_FireMacePL2", 113904 => "A_MacePL1Check", 114032 => "A_MaceBallImpact", 114192 => "A_MaceBallImpact2", 114752 => "A_DeathBallImpact", 115568 => "A_FireSkullRodPL1", 115648 => "A_FireSkullRodPL2", 115776 => "A_SkullRodPL2Seek", 115808 => "A_AddPlayerRain", 116336 => "A_HideInCeiling", 115984 => "A_SkullRodStorm", 116272 => "A_RainImpact", 113152 => "A_FireGoldWandPL1", 113296 => "A_FireGoldWandPL2", 116368 => "A_FirePhoenixPL1", 116720 => "A_InitPhoenixPL2", 116736 => "A_FirePhoenixPL2", 117104 => "A_ShutdownPhoenixPL2", 116496 => "A_PhoenixPuff", 116480 => "A_RemovedPhoenixFunc", # anomaly! 117120 => "A_FlameEnd", 117152 => "A_FloatPuff", 115232 => "A_FireCrossbowPL1", 115312 => "A_FireCrossbowPL2", 115456 => "A_BoltSpark", 69984 => "A_Pain", 76400 => "A_NoBlocking", 78608 => "A_AddPlayerCorpse", 78288 => "A_SkullPop", 78704 => "A_FlameSnd", 78448 => "A_CheckSkullFloor", 78480 => "A_CheckSkullDone", 71568 => "A_Feathers", 71456 => "A_ChicLook", 71488 => "A_ChicChase", 71520 => "A_ChicPain", 69872 => "A_FaceTarget", 71376 => "A_ChicAttack", 69200 => "A_Look", 69328 => "A_Chase", 71808 => "A_MummyAttack", 71920 => "A_MummyAttack2", 72048 => "A_MummySoul", 108432 => "A_ContMobjSound", 72016 => "A_MummyFX1Seek", 74640 => "A_BeastAttack", 75632 => "A_SnakeAttack", 75712 => "A_SnakeAttack2", 74752 => "A_HeadAttack", 77344 => "A_BossDeath", 75328 => "A_HeadIceImpact", 75488 => "A_HeadFireGrow", 75168 => "A_WhirlwindSeek", 75792 => "A_ClinkAttack", 75888 => "A_WizAtk1", 75920 => "A_WizAtk2", 75952 => "A_WizAtk3", 75872 => "A_GhostOff", 70592 => "A_ImpMeAttack", 70672 => "A_ImpMsAttack", 70880 => "A_ImpMsAttack2", 70976 => "A_ImpDeath", 71024 => "A_ImpXDeath1", 71072 => "A_ImpXDeath2", 70304 => "A_ImpExplode", 70160 => "A_KnightAttack", 70016 => "A_DripBlood", 72144 => "A_Sor1Chase", 72096 => "A_Sor1Pain", 72192 => "A_Srcr1Attack", 73456 => "A_SorZap", 72480 => "A_SorcererRise", 73488 => "A_SorRise", 73616 => "A_SorSightSnd", 72816 => "A_Srcr2Decide", 72896 => "A_Srcr2Attack", 73392 => "A_Sor2DthInit", 73520 => "A_SorDSph", 73424 => "A_Sor2DthLoop", 73552 => "A_SorDExp", 73584 => "A_SorDBon", 73120 => "A_BlueSpark", 73232 => "A_GenWizard", 73648 => "A_MinotaurAtk1", 73760 => "A_MinotaurDecide", 74112 => "A_MinotaurAtk2", 74352 => "A_MinotaurAtk3", 74032 => "A_MinotaurCharge", 74528 => "A_MntrFloorFire", 77472 => "A_ESound", } # Locations of action pointer functions for Heretic 1.2. Hand-constructed. # # ./dump-states heretic.exe 8e8b4 ACTION_POINTERS_1_2 = { 81008 => "A_FreeTargMobj", 84544 => "A_RestoreSpecialThing1", 84592 => "A_RestoreSpecialThing2", 81232 => "A_HideThing", 81248 => "A_UnHideThing", 84464 => "A_RestoreArtifact", 78576 => "A_Scream", 79248 => "A_Explode", 79360 => "A_PodPain", 79520 => "A_RemovePod", 79568 => "A_MakePod", 80192 => "A_InitKeyGizmo", 80288 => "A_VolcanoSet", 80320 => "A_VolcanoBlast", 72992 => "A_BeastPuff", 80544 => "A_VolcBallImpact", 79984 => "A_SpawnTeleGlitter", 80064 => "A_SpawnTeleGlitter2", 80144 => "A_AccTeleGlitter", 119824 => "A_Light0", 113488 => "A_WeaponReady", 114080 => "A_Lower", 114240 => "A_Raise", 114848 => "A_StaffAttackPL1", 114016 => "A_ReFire", 114992 => "A_StaffAttackPL2", 113888 => "A_BeakReady", 114176 => "A_BeakRaise", 114480 => "A_BeakAttackPL1", 114656 => "A_BeakAttackPL2", 119344 => "A_GauntletAttack", 115136 => "A_FireBlasterPL1", 115280 => "A_FireBlasterPL2", 117280 => "A_SpawnRippers", 115968 => "A_FireMacePL1", 116816 => "A_FireMacePL2", 116112 => "A_MacePL1Check", 116224 => "A_MaceBallImpact", 116384 => "A_MaceBallImpact2", 116944 => "A_DeathBallImpact", 117760 => "A_FireSkullRodPL1", 117840 => "A_FireSkullRodPL2", 117968 => "A_SkullRodPL2Seek", 118000 => "A_AddPlayerRain", 118512 => "A_HideInCeiling", 118176 => "A_SkullRodStorm", 118448 => "A_RainImpact", 115360 => "A_FireGoldWandPL1", 115504 => "A_FireGoldWandPL2", 118544 => "A_FirePhoenixPL1", 118880 => "A_InitPhoenixPL2", 118896 => "A_FirePhoenixPL2", 119264 => "A_ShutdownPhoenixPL2", 118656 => "A_PhoenixPuff", #0000 => "A_RemovedPhoenixFunc", # anomaly! 119280 => "A_FlameEnd", 119312 => "A_FloatPuff", 117424 => "A_FireCrossbowPL1", 117504 => "A_FireCrossbowPL2", 117648 => "A_BoltSpark", 72496 => "A_Pain", 78832 => "A_NoBlocking", 81104 => "A_AddPlayerCorpse", 80752 => "A_SkullPop", 81200 => "A_FlameSnd", 80976 => "A_CheckBurnGone", 80912 => "A_CheckSkullFloor", 80944 => "A_CheckSkullDone", 74080 => "A_Feathers", 73968 => "A_ChicLook", 74000 => "A_ChicChase", 74032 => "A_ChicPain", 72400 => "A_FaceTarget", 73888 => "A_ChicAttack", 71728 => "A_Look", 71856 => "A_Chase", 74288 => "A_MummyAttack", 74400 => "A_MummyAttack2", 74528 => "A_MummySoul", 110816 => "A_ContMobjSound", 74496 => "A_MummyFX1Seek", 77120 => "A_BeastAttack", 78048 => "A_SnakeAttack", 78128 => "A_SnakeAttack2", 77232 => "A_HeadAttack", 79808 => "A_BossDeath", 77824 => "A_HeadIceImpact", 77984 => "A_HeadFireGrow", 77664 => "A_WhirlwindSeek", 78208 => "A_ClinkAttack", 78320 => "A_WizAtk1", 78352 => "A_WizAtk2", 78384 => "A_WizAtk3", 78304 => "A_GhostOff", 73104 => "A_ImpMeAttack", 73184 => "A_ImpMsAttack", 73392 => "A_ImpMsAttack2", 73488 => "A_ImpDeath", 73536 => "A_ImpXDeath1", 73584 => "A_ImpXDeath2", 72816 => "A_ImpExplode", 72672 => "A_KnightAttack", 72528 => "A_DripBlood", 74624 => "A_Sor1Chase", 74576 => "A_Sor1Pain", 74672 => "A_Srcr1Attack", 75936 => "A_SorZap", 74960 => "A_SorcererRise", 75968 => "A_SorRise", 76096 => "A_SorSightSnd", 75296 => "A_Srcr2Decide", 75376 => "A_Srcr2Attack", 75872 => "A_Sor2DthInit", 76000 => "A_SorDSph", 75904 => "A_Sor2DthLoop", 76032 => "A_SorDExp", 76064 => "A_SorDBon", 75600 => "A_BlueSpark", 75712 => "A_GenWizard", 76128 => "A_MinotaurAtk1", 76240 => "A_MinotaurDecide", 76592 => "A_MinotaurAtk2", 76832 => "A_MinotaurAtk3", 76512 => "A_MinotaurCharge", 77008 => "A_MntrFloorFire", 79936 => "A_ESound", } # Action pointers for Heretic 1.3. # # ./dump-states heretic.exe 8e8b4 ACTION_POINTERS_1_3 = { 81072 => "A_FreeTargMobj", 84608 => "A_RestoreSpecialThing1", 84656 => "A_RestoreSpecialThing2", 81296 => "A_HideThing", 81312 => "A_UnHideThing", 84528 => "A_RestoreArtifact", 78640 => "A_Scream", 79312 => "A_Explode", 79424 => "A_PodPain", 79584 => "A_RemovePod", 79632 => "A_MakePod", 80256 => "A_InitKeyGizmo", 80352 => "A_VolcanoSet", 80384 => "A_VolcanoBlast", 73056 => "A_BeastPuff", 80608 => "A_VolcBallImpact", 80048 => "A_SpawnTeleGlitter", 80128 => "A_SpawnTeleGlitter2", 80208 => "A_AccTeleGlitter", 120064 => "A_Light0", 113728 => "A_WeaponReady", 114320 => "A_Lower", 114480 => "A_Raise", 115088 => "A_StaffAttackPL1", 114256 => "A_ReFire", 115232 => "A_StaffAttackPL2", 114128 => "A_BeakReady", 114416 => "A_BeakRaise", 114720 => "A_BeakAttackPL1", 114896 => "A_BeakAttackPL2", 119584 => "A_GauntletAttack", 115376 => "A_FireBlasterPL1", 115520 => "A_FireBlasterPL2", 117520 => "A_SpawnRippers", 116208 => "A_FireMacePL1", 117056 => "A_FireMacePL2", 116352 => "A_MacePL1Check", 116464 => "A_MaceBallImpact", 116624 => "A_MaceBallImpact2", 117184 => "A_DeathBallImpact", 118000 => "A_FireSkullRodPL1", 118080 => "A_FireSkullRodPL2", 118208 => "A_SkullRodPL2Seek", 118240 => "A_AddPlayerRain", 118752 => "A_HideInCeiling", 118416 => "A_SkullRodStorm", 118688 => "A_RainImpact", 115600 => "A_FireGoldWandPL1", 115744 => "A_FireGoldWandPL2", 118784 => "A_FirePhoenixPL1", 119120 => "A_InitPhoenixPL2", 119136 => "A_FirePhoenixPL2", 119504 => "A_ShutdownPhoenixPL2", 118896 => "A_PhoenixPuff", #0000 => "A_RemovedPhoenixFunc", # anomaly! 119520 => "A_FlameEnd", 119552 => "A_FloatPuff", 117664 => "A_FireCrossbowPL1", 117744 => "A_FireCrossbowPL2", 117888 => "A_BoltSpark", 72560 => "A_Pain", 78896 => "A_NoBlocking", 81168 => "A_AddPlayerCorpse", 80816 => "A_SkullPop", 81264 => "A_FlameSnd", 81040 => "A_CheckBurnGone", 80976 => "A_CheckSkullFloor", 81008 => "A_CheckSkullDone", 74144 => "A_Feathers", 74032 => "A_ChicLook", 74064 => "A_ChicChase", 74096 => "A_ChicPain", 72464 => "A_FaceTarget", 73952 => "A_ChicAttack", 71792 => "A_Look", 71920 => "A_Chase", 74352 => "A_MummyAttack", 74464 => "A_MummyAttack2", 74592 => "A_MummySoul", 111056 => "A_ContMobjSound", 74560 => "A_MummyFX1Seek", 77184 => "A_BeastAttack", 78112 => "A_SnakeAttack", 78192 => "A_SnakeAttack2", 77296 => "A_HeadAttack", 79872 => "A_BossDeath", 77888 => "A_HeadIceImpact", 78048 => "A_HeadFireGrow", 77728 => "A_WhirlwindSeek", 78272 => "A_ClinkAttack", 78384 => "A_WizAtk1", 78416 => "A_WizAtk2", 78448 => "A_WizAtk3", 78368 => "A_GhostOff", 73168 => "A_ImpMeAttack", 73248 => "A_ImpMsAttack", 73456 => "A_ImpMsAttack2", 73552 => "A_ImpDeath", 73600 => "A_ImpXDeath1", 73648 => "A_ImpXDeath2", 72880 => "A_ImpExplode", 72736 => "A_KnightAttack", 72592 => "A_DripBlood", 74688 => "A_Sor1Chase", 74640 => "A_Sor1Pain", 74736 => "A_Srcr1Attack", 76000 => "A_SorZap", 75024 => "A_SorcererRise", 76032 => "A_SorRise", 76160 => "A_SorSightSnd", 75360 => "A_Srcr2Decide", 75440 => "A_Srcr2Attack", 75936 => "A_Sor2DthInit", 76064 => "A_SorDSph", 75968 => "A_Sor2DthLoop", 76096 => "A_SorDExp", 76128 => "A_SorDBon", 75664 => "A_BlueSpark", 75776 => "A_GenWizard", 76192 => "A_MinotaurAtk1", 76304 => "A_MinotaurDecide", 76656 => "A_MinotaurAtk2", 76896 => "A_MinotaurAtk3", 76576 => "A_MinotaurCharge", 77072 => "A_MntrFloorFire", 80000 => "A_ESound", } #ACTION_POINTERS = ACTION_POINTERS_1_0 ACTION_POINTERS = ACTION_POINTERS_1_2 #ACTION_POINTERS = ACTION_POINTERS_1_3 def read_int(file) c1 = file.getc c2 = file.getc c3 = file.getc c4 = file.getc result = c1 | (c2 << 8) | (c3 << 16) | (c4 << 24) if result > (1 << 31) result -= (1 << 32) end result end def read_state(file) result = {} result[:spritenum] = read_int(file) result[:frame] = read_int(file) result[:tics] = read_int(file) result[:action] = read_int(file) result[:nextstate] = read_int(file) result[:misc1] = read_int(file) result[:misc2] = read_int(file) result end def action_pointer_to_s(action_ptr) # NULL pointer? if action_ptr == 0 return "NULL" end if ACTION_POINTERS[action_ptr] == nil raise "Action pointer #{action_ptr} unknown!" end return ACTION_POINTERS[action_ptr] end states = [] File.open(filename) do |file| file.seek(offset) NUM_STATES.times do states.push(read_state(file)) end end puts "state_t states[] = {" for state_num in 0...NUM_STATES state = states[state_num] record = sprintf("{%s, %i, %i, %s, %i, %i, %i },", SPRITE_NAMES[state[:spritenum]], state[:frame], state[:tics], action_pointer_to_s(state[:action]), state[:nextstate], state[:misc1], state[:misc2]) printf " %s", record padding = 55 - record.length printf " " * padding printf "// state #%i", state_num printf "\n" end puts "};"