private List <UInt32> writeSubroutineSkipMapUnlockCheck(AddressMapper addressMapper, VAVAddr entryAddr, VAVAddr returnContinueAddr, VAVAddr returnSkipMapUnlockedCheck) { // precondition: r26 is mapid // r3 is unused // postcondition: r3 is mapid var asm = new List <UInt32>(); asm.Add(PowerPcAsm.or(3, 26, 26)); // r3 <- mapid asm.Add(PowerPcAsm.cmpwi(3, -1)); // mapid == -1 ? asm.Add(PowerPcAsm.beq(entryAddr, asm.Count, returnSkipMapUnlockedCheck)); // goto skipMapUnlockedCheck asm.Add(PowerPcAsm.b(entryAddr, asm.Count, returnContinueAddr)); // else goto returnContinueAddr return(asm); }
protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors) { var tableAddr = writeTable(mapDescriptors); // --- Game::GameSequenceDataAdapter::GetNumMapsInZone --- var subroutineGetNumMapsInZone = allocate(writeSubroutineGetNumMapsInZone(mapDescriptors), "SubroutineGetNumMapsInZone"); var hijackAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8020f3ac); stream.Seek(addressMapper.toFileAddress(hijackAddr), SeekOrigin.Begin); // li r3,0x6 -> b subroutineGetNumMapsInZone stream.Write(PowerPcAsm.b(hijackAddr, subroutineGetNumMapsInZone)); // --- Game::GameSequenceDataAdapter::GetMapsInZone --- hijackAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8020f454); var returnAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8020f554); var subroutineGetMapsInZone = allocate(writeSubroutineGetMapsInZone(addressMapper, mapDescriptors, tableAddr, VAVAddr.NullAddress, returnAddr), "SubroutineGetMapsInZone"); stream.Seek(addressMapper.toFileAddress(subroutineGetMapsInZone), SeekOrigin.Begin); stream.Write(writeSubroutineGetMapsInZone(addressMapper, mapDescriptors, tableAddr, subroutineGetMapsInZone, returnAddr)); // re-write the routine again since now we know where it is located in the main dol stream.Seek(addressMapper.toFileAddress(hijackAddr), SeekOrigin.Begin); // cmpwi r29,0x0 -> b subroutineGetMapsInZone stream.Write(PowerPcAsm.b(hijackAddr, subroutineGetMapsInZone)); // --- Write Table Meta Information --- stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020f458), SeekOrigin.Begin); stream.Write((uint)tableAddr); stream.Write((short)0); stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020F45E), SeekOrigin.Begin); stream.Write((short)mapDescriptors.Count); // --- Fix Wifi Map Selection --- // bl GameSequenceDataAdapter::GetMapOrigin(r3) -> nop stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80185ac4), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop()); // or r31,r3,r3 -> or r31,r4,r4 stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80185ac8), SeekOrigin.Begin); stream.Write(PowerPcAsm.or(31, 4, 4)); // li r5,0x1 -> li r5,0x2 stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80185b10), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(5, 2)); // bl GameSequenceDataAdapter::GetMapOrigin(r3) -> nop stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8024b1b8), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop()); // bl GameSequenceDataAdapter::GetMapOrigin(r3) -> nop stream.Seek(addressMapper.toFileAddress((BSVAddr)0x802498a8), SeekOrigin.Begin); for (int i = 0; i < 8; i++) { stream.Write(PowerPcAsm.nop()); } // --- Default selected map button in wifi --- // since Standard Mode is selected on default, we use this mapset to find the standard map // TODO need asm hack to determine currently selected MapSet and use rather use that ID short defaultMap = 0; for (short i = 0; i < mapDescriptors.Count; i++) { var mapDescriptor = mapDescriptors[i]; if (mapDescriptor.MapSet == 1 && mapDescriptor.Zone == 0 && mapDescriptor.Order == 0) { defaultMap = i; } } // 0x9 = Castle Trodain // li r3,0x9 -> li r3,0x9 stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8024afc8), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(3, defaultMap)); // TODO 0x13 is some special handling map id. Need to check what is going on with it // li r3,0x13 -> li r3,0x13 stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80243ae4), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(5, 0x13)); // --- Fix out of array bounds error when opening tour mode and viewing the zones and having more than 6 maps in a zone --- // bl Game::GameSequenceDataAdapter::GetNumMapsInZone -> li r3,0x6 stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021f880), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(3, 0x6)); // bl Game::GameSequenceDataAdapter::GetNumMapsInZone -> li r3,0x6 stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021ff4c), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(3, 0x6)); }