|
7 | 7 | import java.util.List; |
8 | 8 | import java.util.logging.Logger; |
9 | 9 |
|
| 10 | +import org.ruru.ffta2editor.model.battle.SBN; |
| 11 | +import org.ruru.ffta2editor.model.battle.SBN.Command; |
| 12 | +import org.ruru.ffta2editor.model.unitSst.SstHeaderNode; |
10 | 13 | import org.ruru.ffta2editor.model.unitSst.UnitAnimation; |
11 | 14 | import org.ruru.ffta2editor.model.unitSst.UnitAnimation.UnitAnimationFrame; |
12 | 15 | import org.ruru.ffta2editor.model.unitSst.UnitSst; |
13 | | -import org.ruru.ffta2editor.model.unitSst.UnitSst.SstHeaderNode; |
14 | 16 | import org.ruru.ffta2editor.utility.LZSS; |
15 | 17 |
|
16 | 18 | import javafx.beans.property.BooleanProperty; |
@@ -207,7 +209,7 @@ private void portAnimations(int i, ArrayList<Pair<Integer, byte[]>> compressedAn |
207 | 209 | byte animationId = (byte)(animation.getKey() >>> 8); |
208 | 210 | byte animationType = (byte)(animation.getKey() & 0xFF); |
209 | 211 | SstHeaderNode newNode = new SstHeaderNode(unitSst.size, animationType, animationId, 0); |
210 | | - newNode.compressedValue = compressedAnimation; |
| 212 | + newNode.value = compressedAnimation; |
211 | 213 | unitSst.insert(newNode); |
212 | 214 |
|
213 | 215 | int oldValue = App.naUnitAnimTable.get(4+1 + i*entryLength + animationId); |
@@ -497,6 +499,124 @@ public void applyMaxLevelPatch() { |
497 | 499 |
|
498 | 500 | } |
499 | 501 |
|
| 502 | + @FXML |
| 503 | + public void applyMPGainPatch() { |
| 504 | + if (App.archive != null) { |
| 505 | + |
| 506 | + TextInputDialog dialog = new TextInputDialog(Integer.toString(10)); |
| 507 | + dialog.setTitle("MP gain"); |
| 508 | + dialog.setHeaderText("Flat MP per turn"); |
| 509 | + var result = dialog.showAndWait(); |
| 510 | + if (!result.isPresent()) return; |
| 511 | + |
| 512 | + int flatRegen; |
| 513 | + try { |
| 514 | + flatRegen = Integer.parseInt(result.get()); |
| 515 | + if (flatRegen < 0) throw new Exception("Value must be 0 or higher"); |
| 516 | + } catch (Exception e) { |
| 517 | + Alert loadAlert = new Alert(AlertType.ERROR); |
| 518 | + loadAlert.setTitle("MP gain patch"); |
| 519 | + loadAlert.setHeaderText(e.toString()); |
| 520 | + loadAlert.show(); |
| 521 | + return; |
| 522 | + } |
| 523 | + |
| 524 | + dialog.setHeaderText("%Max MP per turn"); |
| 525 | + result = dialog.showAndWait(); |
| 526 | + if (!result.isPresent()) return; |
| 527 | + |
| 528 | + int percentage; |
| 529 | + try { |
| 530 | + percentage = Integer.parseInt(result.get()); |
| 531 | + if (percentage < 0 || 100 < percentage) throw new Exception("Value must be between 0 and 100"); |
| 532 | + } catch (Exception e) { |
| 533 | + Alert loadAlert = new Alert(AlertType.ERROR); |
| 534 | + loadAlert.setTitle("MP gain patch"); |
| 535 | + loadAlert.setHeaderText(e.toString()); |
| 536 | + loadAlert.show(); |
| 537 | + return; |
| 538 | + } |
| 539 | + int divisor = percentage != 0 ? 100 / percentage : 99999; |
| 540 | + |
| 541 | + |
| 542 | + ByteBuffer btlprocessFile = App.archive.getFile("battle/btlprocess.sbn"); |
| 543 | + SBN btlprocess = new SBN(btlprocessFile.rewind()); |
| 544 | + |
| 545 | + int insertion_point = 0x160c; |
| 546 | + int i = 0; |
| 547 | + for (; i < btlprocess.commands.size(); i++) { |
| 548 | + if (btlprocess.commands.get(i).address == insertion_point) break; |
| 549 | + } |
| 550 | + |
| 551 | + ByteBuffer flatParams = ByteBuffer.allocate(6).order(ByteOrder.LITTLE_ENDIAN); |
| 552 | + flatParams.putShort((short)0); |
| 553 | + flatParams.putInt(flatRegen); |
| 554 | + ByteBuffer divisorParams = ByteBuffer.allocate(6).order(ByteOrder.LITTLE_ENDIAN); |
| 555 | + divisorParams.putShort((short)0); |
| 556 | + divisorParams.putInt(divisor); |
| 557 | + |
| 558 | + ArrayList<Command> newCommands = new ArrayList<>(); |
| 559 | + newCommands.add(new Command(0, (byte)0x0, (byte)0x8, flatParams.array())); |
| 560 | + newCommands.add(new Command(0, (byte)0x2, (byte)0x8, new byte[]{0x00, 0x00, (byte)0xfe, (byte)0xff, 0x01, 0x00})); |
| 561 | + newCommands.add(new Command(0, (byte)0x1c, (byte)0x4, new byte[]{0x01, 0x00})); |
| 562 | + newCommands.add(new Command(0, (byte)0x32, (byte)0x4, new byte[]{(byte)0xff, (byte)0xff})); |
| 563 | + newCommands.add(new Command(0, (byte)0x31, (byte)0x4, new byte[]{0x18, 0x06})); |
| 564 | + newCommands.add(new Command(0, (byte)0x1c, (byte)0x4, new byte[]{(byte)0xff, (byte)0xff})); |
| 565 | + newCommands.add(new Command(0, (byte)0x2b, (byte)0x4, new byte[]{0x00, 0x00})); |
| 566 | + newCommands.add(new Command(0, (byte)0x0, (byte)0x8, divisorParams.array())); |
| 567 | + newCommands.add(new Command(0, (byte)0x9, (byte)0x2, new byte[]{})); |
| 568 | + newCommands.add(new Command(0, (byte)0x6, (byte)0x2, new byte[]{})); |
| 569 | + |
| 570 | + int additionalBytes = newCommands.stream().mapToInt(x -> x.size).sum(); |
| 571 | + newCommands.add(new Command(0, (byte)0x2d, (byte)0x10, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})); |
| 572 | + |
| 573 | + |
| 574 | + if (btlprocess.commands.get(i).opcode == 0x30) { |
| 575 | + // Already applied |
| 576 | + System.out.println("Already applied"); |
| 577 | + ByteBuffer params = ByteBuffer.wrap(btlprocess.commands.get(i).parameters).order(ByteOrder.LITTLE_ENDIAN); |
| 578 | + params.getShort(); |
| 579 | + int jumpAddress = params.getInt(); |
| 580 | + for (; i < btlprocess.commands.size(); i++) { |
| 581 | + if (btlprocess.commands.get(i).address == insertion_point+jumpAddress) break; |
| 582 | + } |
| 583 | + int j = 0; |
| 584 | + for (; i < btlprocess.commands.size(); i++, j++) { |
| 585 | + btlprocess.commands.set(i, newCommands.get(j)); |
| 586 | + } |
| 587 | + if (i < btlprocess.commands.size() || j < newCommands.size()) { |
| 588 | + System.err.println(String.format("Sizes don't match: %d < %d or %d < %d", i, btlprocess.commands.size(), j, newCommands.size())); |
| 589 | + } |
| 590 | + } else { |
| 591 | + System.out.println("Not applied yet"); |
| 592 | + for (Command c : newCommands) { |
| 593 | + btlprocess.commands.add(c); |
| 594 | + } |
| 595 | + |
| 596 | + ByteBuffer params = ByteBuffer.allocate(6).order(ByteOrder.LITTLE_ENDIAN); |
| 597 | + params.putShort((short)0); |
| 598 | + params.putInt(btlprocess.endAddress - insertion_point); |
| 599 | + //btlprocess.commands.set(i, new Command(0, (byte)0x30, (byte)0x8, params.array())); |
| 600 | + btlprocess.commands.get(i).opcode = 0x30; |
| 601 | + btlprocess.commands.get(i).size = 0x8; |
| 602 | + btlprocess.commands.get(i).parameters = params.array(); |
| 603 | + } |
| 604 | + |
| 605 | + |
| 606 | + ByteBuffer newBtlprocess = btlprocess.toByteBuffer(); |
| 607 | + |
| 608 | + App.archive.setFile("battle/btlprocess.sbn", newBtlprocess); |
| 609 | + |
| 610 | + |
| 611 | + String alertText = String.format("MP gain set to %d + %d%% Max MP per turn", flatRegen, percentage); |
| 612 | + Alert loadAlert = new Alert(AlertType.INFORMATION); |
| 613 | + loadAlert.setTitle("MP gain patch"); |
| 614 | + loadAlert.setHeaderText(alertText); |
| 615 | + loadAlert.show(); |
| 616 | + } |
| 617 | + |
| 618 | + } |
| 619 | + |
500 | 620 | public void loadPatches() { |
501 | 621 | patchedExpandedTopSprites.set(App.arm9.getInt(0x000b5ab4) != 0xe5d00018); |
502 | 622 | patchedSignedEquipmentStats.set(App.arm9.getInt(0x000cfcd8) != 0xe5d01017); |
|
0 commit comments