local ObjectPosYList = {} local ObjectTypeList = {} local ff_frame = -1 local result_text = {} local start_enemy_index = "" --敵のロード処理 function LoadEnemies() --オブジェクト種類保存配列初期化 ObjectTypeList = {} ObjectPosYList = {} result_text = {} --ボス出現中フラグ local BossCurrentStrategy = memory.readbyte(0x3E) --移動中フラグ local ScreenMovedFlag = memory.readbyte(0x8D) --ボス戦中か if(BossCurrentStrategy ~= 0x00)then return end --移動していないか if(AND(ScreenMovedFlag,0x01) == 0x00)then return end --右向きに移動中か if(AND(ScreenMovedFlag,0x01) == 0x00)then return end if(AND(ScreenMovedFlag,0xFE) == 0x00)then --LoadEnemies_Backward() else LoadEnemies_Forward() end end function LoadEnemies_Forward() local ScrollPosX = memory.readbyte(0x1A) --画面右端の座標 local CurrentScreenXMinusOne = AND(0xFF,ScrollPosX + 0xFF) --スクロールする画面番号 local ScrollPosScreen = memory.readbyte(0x1B) if(ScrollPosX ~= 0x00)then ScrollPosScreen = AND(0xFF,ScrollPosScreen + 0x01) end --敵インデックスロード local CurrentEnemyIndex = memory.readbyte(0x8C) start_enemy_index = string.format("StartEnemyIndex$8C=%d",CurrentEnemyIndex) --オブジェクトのX座標 local ObjectPosX = memory.readbyte(0x00) --現在の部屋ポインタ local CurrentRoomPointer = LoadEnemyNumber(CurrentEnemyIndex,ObjectPosX) --ポインタ local RegisterY = 0x00 result_text[tonumber(CurrentEnemyIndex)] = string.format("Start,CurrenEnemyIndexStart = %X",CurrentEnemyIndex) while(true)do --オブジェクトの画面番号 local ObjectScreenNumber = memory.readbyte(CurrentRoomPointer+RegisterY) --画面端の判定 if(ObjectScreenNumber < ScrollPosScreen)then --何もしない elseif(ObjectScreenNumber - ScrollPosScreen ~= 0x00)then result_text[tonumber(CurrentEnemyIndex)] = string.format("End,ScreenNumber[$%X]%X > [$1B]%X",CurrentRoomPointer+RegisterY,ObjectScreenNumber,ScrollPosScreen) return; else --オブジェクトのX座標 ObjectPosX = memory.readbyte(CurrentRoomPointer+RegisterY+0x01) if(ObjectPosX - CurrentScreenXMinusOne == 0x00)then --何もしない elseif(ObjectPosX - CurrentScreenXMinusOne > 0x00)then result_text[tonumber(CurrentEnemyIndex)] = string.format("End,ObjectPosX[$%X]=%X > %X",CurrentRoomPointer+RegisterY+0x01,ObjectPosX,CurrentScreenXMinusOne) return end end --オブジェクトのX座標 ObjectPosX = memory.readbyte(CurrentRoomPointer+RegisterY+0x01) --オブジェクトのY座標 local ObjectPosY = memory.readbyte(CurrentRoomPointer+RegisterY+0x02) --オブジェクトの種類 local ObjectType = memory.readbyte(CurrentRoomPointer+RegisterY+0x03) local ObjectFireDelay = memory.readbyte(0xA40C+ObjectType) --オブジェクト出現処理へ result_text[tonumber(CurrentEnemyIndex)] = SpawnObject(ObjectType,CurrentEnemyIndex,ObjectPosX,ObjectPosY) .. string.format(" [%X][$%X:%X<=$1B:%X]",ObjectFireDelay,CurrentRoomPointer+RegisterY,ObjectScreenNumber,ScrollPosScreen) --ポインタインクリメント CurrentEnemyIndex = AND(0xFF,CurrentEnemyIndex + 1) RegisterY = AND(0xFF,RegisterY + 4) if(CurrentEnemyIndex == 0x00)then result_text[tonumber(CurrentEnemyIndex)] = string.format("End,CurrenEnemyIndexEndex = %X",CurrentEnemyIndex) return end end end function SpawnObject(ObjectType,EnemyIndex,ObjectPosX,ObjectPosY) --オブジェクトの種類がFFのときは再描画的処理へ if(ObjectType == 0xFF)then return "ObjectType == 0xFF" --オブジェクトのY座標がFEのときは特殊処理へ elseif(ObjectPosY == 0xFE)then return "ObjectPosY == 0xFE" end local temp for temp = 0x0F, 0x00, -1 do if(EnemyIndex - memory.readbyte(0x7B + temp) == 0)then return string.format("($7B+%X) == 0x00",temp) end end --オブジェクトを入れる場所があるか探す local FreeObjectPointer = FindFreeObject(0x10) --あった場合はオブジェクト出現! if(FreeObjectPointer >= 0)then --出力テーブルに保存 ObjectSpriteNum = 0x6E0 + FreeObjectPointer ObjectTypeList[ObjectSpriteNum] = ObjectType --FindFreeObjectのためにObjectPosYを保存 ObjectPosYNum = 0x600 + FreeObjectPointer ObjectPosYList[ObjectPosYNum] = ObjectPosY return string.format("SpawnObject %X[X=%d,Y=%d]",ObjectType,ObjectPosX,ObjectPosY) else return string.format("FindFreeObject is Full") end end --オブジェクトを-いれる場所があるか探す function FindFreeObject(ObjectPtr) while(true)do --0x600:ObjectPosY --ObjectPosYが0xF8に一致した場合 if(memory.readbyte(0x600+ObjectPtr) == 0xF8)then if(ObjectPosYList[0x600+ObjectPtr] == nil)then --オブジェクトを入れる場所を返す return ObjectPtr end end ObjectPtr = ObjectPtr + 1 --全オブジェクトが埋まっていた場合はオブジェクトを入れる場所がない local TotalObjects = memory.readbyte(0x54); if(ObjectPtr == TotalObjects)then return -1 end end end --敵番号ロード処理 function LoadEnemyNumber(CurrentEnemyIndex,ObjectPosX) local CurrentRoomPointerH = AND(0xFF,bit.lshift(ObjectPosX,2)) local CurrentRoomPointerL = AND(0xFF,bit.lshift(CurrentEnemyIndex,2)) local CurrentStagePtr = AND(0xFF,bit.lshift(memory.readbyte(0x31),1)) --CurrentRoomPointer算出。ここの処理がバンク5のとき誤りの値となる CurrentRoomPointerL = memory.readbyte(0xA452 + CurrentStagePtr) + CurrentRoomPointerL CurrentRoomPointerH = AND(CurrentRoomPointerH,0x03) + memory.readbyte(0xA453 + CurrentStagePtr); local CurrentRoomPointer = CurrentRoomPointerH * 0x100 + CurrentRoomPointerL --CurrentRoomPointerを返す return CurrentRoomPointer; end function printf(param1,param2,param3) local xadj, yadj = 0, 5 -- 行数表示 gui.text(5+xadj,5+yadj,"Param1->:"..string.format("[%X]",param1) ) gui.text(5+xadj,15+yadj,"Param2->:"..string.format("[%X]",param2) ) gui.text(5+xadj,25+yadj,"Param3->:"..string.format("[%X]",param3) ) end memory.registerexec(0xc666, 0x03, function(address) local pc = memory.getregister("pc") if(pc == 0xc666)then ff_frame = movie.framecount() gui.text(5,10,tostring(0xc666)) end end ) memory.registerexec(0xd8a0, 0x03, function(address) local pc = memory.getregister("pc") local b1 = memory.readbyte(pc) if (pc == 0xd8a0 and b1 == 0x85) then --セーブ --local state = savestate.create() --savestate.save(state) --いったんバンク2に切り替え memory.writebyte(0xC006,0x02) --敵呼び出し LoadEnemies() --バンク6に戻す memory.writebyte(0xC006,0x06) --ロード --savestate.load(state) end end ) function order_pairs(tab) local sorted = {} for key in pairs(tab) do table.insert(sorted,key) end table.sort(sorted) local i=0 return function() i = i + 1 if i > #sorted then return nil,nil else local key=sorted[i] return key,tab[key] end end end gui.register( function() gui.text(5,35,start_enemy_index) --出力 local xadj, yadj = 0, 5 i=1 for j,k in order_pairs(result_text) do gui.text(5+xadj,(35+(i*10))+yadj,string.format("[%s]->%s",j,k)) i=i+1 end end ) while true do emu.frameadvance() end