Update move expansion: add level-up list length expansion

This commit is contained in:
Benjamin Popp 2021-03-12 19:56:35 -06:00
parent a1ae7fb83f
commit a43101cc8e
2 changed files with 100 additions and 14 deletions

View File

@ -25,14 +25,14 @@ BPEE0.scripts.shiny.odds-1 067C56,06E76C,06E7E2,06EBE4,172F46
# -1: GetHoennPokedexCount,GetPokedexRatingText
# -2: GetPokedexRatingText
# -3: HasAllHoennMons,GetPokedexRatingText
AXPV0.scripts.pokedex.regional.length 0406FA,08D6BA,08D6E2,10D5E8
AXPV0.scripts.pokedex.regional.length-1 090FB4,10D5A8
AXPV0.scripts.pokedex.regional.length-2 10D570
AXPV0.scripts.pokedex.regional.length-3 090FE6,10D56C
AXPV1.scripts.pokedex.regional.length 04071A,08D6DA,08D702,10D608
AXPV1.scripts.pokedex.regional.length-1 090FD4,10D5C8
AXPV1.scripts.pokedex.regional.length-2 10D590
AXPV1.scripts.pokedex.regional.length-3 091006,10D58C
AXVE0.scripts.pokedex.regional.length 0406FA,08D6BA,08D6E2,10D5E8
AXVE0.scripts.pokedex.regional.length-1 090FB4,10D5A8
AXVE0.scripts.pokedex.regional.length-2 10D570
AXVE0.scripts.pokedex.regional.length-3 090FE6,10D56C
AXVE1.scripts.pokedex.regional.length 04071A,08D6DA,08D702,10D608
AXVE1.scripts.pokedex.regional.length-1 090FD4,10D5C8
AXVE1.scripts.pokedex.regional.length-2 10D590
AXVE1.scripts.pokedex.regional.length-3 091006,10D58C
AXPE0.scripts.pokedex.regional.length 0406FA,08D6BA,08D6E2,10D5E8
AXPE0.scripts.pokedex.regional.length-1 090FB4,10D5A8
AXPE0.scripts.pokedex.regional.length-2 10D570
@ -213,3 +213,4 @@ AXVE1.data.pokemon.type.length*8 0A0214,0A0310
AXPE1.data.pokemon.type.length+5 3C1235
AXPE1.data.pokemon.type.length*8 0A0214,0A0310

View File

@ -23,28 +23,88 @@ namespace HavenSoft.HexManiac.Core.ViewModels.QuickEditItems {
return viewPort is IEditableViewPort;
}
public static IReadOnlyDictionary<string, int> GetNumberOfRelearnableMoves = new Dictionary<string, int> {
{ "AXVE0", 0x040574 },
{ "AXPE0", 0x040574 },
{ "AXVE1", 0x040594 },
{ "AXPE1", 0x040594 },
{ "BPRE0", 0x043E2C },
{ "BPGE0", 0x043E2C },
{ "BPRE1", 0x043E40 },
{ "BPGE1", 0x043E40 },
{ "BPEE0", 0x06e25c },
};
public static IReadOnlyDictionary<string, int[]> MaxLevelUpMoveCountLocations = new Dictionary<string, int[]> { // each of these stores the max number of level-up moves, minus 1
{ "AXVE0", new[] { 0x0404E8, 0x040556, 0x0406A4 } },
{ "AXPE0", new[] { 0x0404E8, 0x040556, 0x0406A4 } },
{ "AXVE1", new[] { 0x040508, 0x040576, 0x0406C4 } },
{ "AXPE1", new[] { 0x040508, 0x040576, 0x0406C4 } },
{ "BPRE0", new[] { 0x043DA0, 0x043E0E, 0x043F5C } },
{ "BPGE0", new[] { 0x043DA0, 0x043E0E, 0x043F5C } },
{ "BPRE1", new[] { 0x043DB4, 0x043E22, 0x043F70 } },
{ "BPGE1", new[] { 0x043DB4, 0x043E22, 0x043F70 } },
{ "BPEE0", new[] { 0x06E1D0, 0x06E23E, 0x06E38C } },
};
public ErrorInfo Run(IViewPort viewPortInterface) {
var viewPort = (IEditableViewPort)viewPortInterface;
var model = viewPort.Model;
var token = viewPort.ChangeHistory.CurrentChange;
var parser = viewPort.Tools.CodeTool.Parser;
// fix limit for move effects
var error = RefactorMoveByteFieldInTable(parser, viewPort.Model, token, MoveDataTable, "power", 9);
if (error.HasError) return error;
error = RefactorByteToHalfWordInTable(parser, viewPort.Model, token, MoveDataTable, "effect");
var error = ExpandMoveEffects(parser, model, token);
if (error.HasError) return error;
// update limiters
ReplaceAll(parser, viewPort.Model, token,
// update limiters for move names
error = ReplaceAll(parser, viewPort.Model, token,
new[] { "mov r0, #177", "lsl r0, r0, #1", "cmp r1, r0" },
new[] { "mov r0, #177", "lsl r0, r0, #9", "cmp r1, r0" });
if (error.HasError) return error;
// update max level-up moves from 20 to 40
var code = model.GetGameCode();
error = AddStackSpace(parser, viewPort.Model, token, GetNumberOfRelearnableMoves[code], 48, 40);
if (error.HasError) return error;
foreach (var address in MaxLevelUpMoveCountLocations[code]) token.ChangeData(viewPort.Model, address, 40 - 1);
// TODO update levelup moves
var table = model.GetTable(LevelMovesTableName) as ArrayRun;
viewPort.Refresh();
return ErrorInfo.NoError;
}
public static ErrorInfo ExpandMoveEffects(ThumbParser parser, IDataModel model, ModelDelta token) {
// make move effects 2 bytes instead of 1 byte
var table = model.GetTable(MoveDataTable);
var fieldNames = table.ElementContent.Select(seg => seg.Name).ToArray();
Func<ErrorInfo> shiftField(int i) => () => RefactorMoveByteFieldInTable(parser, model, token, MoveDataTable, fieldNames[i], i + 1);
var error = ChainErrors(
shiftField(8), shiftField(7), shiftField(6), shiftField(5),
shiftField(4), shiftField(3), shiftField(2), shiftField(1),
() => RefactorByteToHalfWordInTable(parser, model, token, MoveDataTable, fieldNames[0]));
if (error.HasError) return error;
// update offset pointers (because the PP field moved)
foreach (OffsetPointerRun pointerRun in table.PointerSources
.Select(address => model.GetNextRun(address))
.Where(pointer => pointer is OffsetPointerRun)
) {
model.WritePointer(token, pointerRun.Start, table.Start + 5);
model.ObserveRunWritten(token, new OffsetPointerRun(pointerRun.Start, 5));
}
return ErrorInfo.NoError;
}
public static ErrorInfo ChainErrors(params Func<ErrorInfo>[] actions) {
foreach (var action in actions) {
var result = action();
if (result.HasError) return result;
}
return ErrorInfo.NoError;
}
public static ErrorInfo RefactorMoveByteFieldInTable(ThumbParser parser, IDataModel model, ModelDelta token, string tableName, string fieldName, int newOffset) {
// setup
var table = model.GetTable(tableName) as ArrayRun;
@ -135,6 +195,31 @@ namespace HavenSoft.HexManiac.Core.ViewModels.QuickEditItems {
return ErrorInfo.NoError;
}
public static ErrorInfo AddStackSpace(ThumbParser parser, IDataModel model, ModelDelta token, int funcStart, int stackAddOffset, int stackAddCount) {
for (int i = funcStart; true; i += 2) {
var commandLine = parser.Parse(model, i, 2).Trim().SplitLines().Last().Trim();
if (commandLine.Contains("[sp, ")) {
if (commandLine.StartsWith("str ") || commandLine.StartsWith("ldr ")) {
var currentValue = model[i] * 4;
if (currentValue >= stackAddOffset) {
var newValue = (currentValue + stackAddCount) / 4;
if (newValue > 255) return new ErrorInfo($"{i:X6}: Could not add {stackAddCount}, the result would be larger than 1020.");
token.ChangeData(model, i, (byte)newValue);
}
}
}
if (commandLine.Contains(" sp, ")) {
var writer = new TupleSegment(default, 7);
var value = writer.Read(model, i, 0) * 4;
value += stackAddCount;
writer.Write(model, token, i, 0, value / 4);
}
if (commandLine.StartsWith("bx ")) break;
}
return ErrorInfo.NoError;
}
public static ErrorInfo ReplaceAll(ThumbParser parser, IDataModel model, ModelDelta token, string[] inputCode, string[] outputCode) {
var search = parser.Compile(model, 0, inputCode);
var replace = parser.Compile(model, 0, outputCode);