øAslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&topic=1883.msg22746e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/index81cd.htmlslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&topic=1883.420e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/index81cd.html.zx "g^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ P,©OKtext/htmlISO-8859-1gzip0|Ö©ÿÿÿÿÿÿÿÿTue, 10 Mar 2020 05:30:11 GMT0ó°° ®0®P®€§²ð® "g^ÿÿÿÿÿÿÿÿVK© Grimoire LD's Notes, Patches, and Hacks (Dark Knight/Paladin Swap In Battle!)

Author Topic: Grimoire LD's Notes, Patches, and Hacks (Dark Knight/Paladin Swap In Battle!)  (Read 78679 times)

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
The idea you present would work, IF there was a YY portion. None of the four unused/redundant Event Instructions have a YY portion to draw from and to add a YY portion to an instruction that did not originally have it to any of the existing Event Instructions would need a large rewrite to Events all together.

Hm, well if that's the only problem (besides the issue of deciphering how to read flag values) I have a very hack-ish solution:

"Do the following action if Flag XX is (on/off)"

Top bit of XX indicates whether you're looking for on or off, the rest indicate the flag number (since it seems all the used flags besides 255 are under 128 ^_^)

That way if you want multiple conditional instructions, it can still be done, though rather tediously:

Code: [Select]
If "saved Yang" is ON do the next action
 Placement 4: Yang toggles visibility
If "saved Yang" is ON do the next action
 Placement 4: Yang moves up
If "saved Yang" is ON do the next action
 Show Message: "Yang: Leave it to me"
If "saved Yang" is OFF do the next action
 Show Message: "Cecil: If only Yang were here"

Also I do like the stop-gap solution you proposed for my more immediate problem of switching to paladin/DK cecil, but I think if we can somehow swing a more general "conditional" instruction, it would vastly improve the expressiveness of the event code generally and open a lot of new doors.

This is a workable idea and quite easy (in theory) to put together. The first step would involve decrementing the value to -80 to reach the proper event Flag check and then reloading the  byte and checking to see if it is negative (which it will be if it is 80) to branch to the Event Flag Check. 80 will check to see if it is On while 00 will check to see if it is Off. But again, this does require reverse-engineering as you put it. So... I'll get on that and see what I can find. Hopefully it won't be too much math.

Alright, that was easy to find...

$00/EF81   20 CB E2   JSR $E2CB  [$00:E2CB]   A:00EF   X:0000   Y:0002   P:envMxdiZc - Jump to Event Instruction Jump Routine (Looks like this is already prepared as well)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$00/E2CB   E8    INX   A:00EF   X:0000   Y:0002   P:envMxdiZc - +1 to X.
$00/E2CC   86 B3   STX $B3    [$00:06B3]   A:00EF   X:0001   Y:0002   P:envMxdizc - store X in 06B3.
$00/E2CE   BD D5 09   LDA $09D5,x[$00:09D6]   A:00EF   X:0001   Y:0002   P:envMxdizc - Load Event Instruction Location +X (meaning next byte over) into A (in this case the Flag Number)
$00/E2D1   60    RTS   A:0005   X:0001   Y:0002   P:envMxdizc - Return
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$00/EF84   20 33 F1   JSR $F133  [$00:F133]   A:0005   X:0001   Y:0002   P:envMxdizc
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$00/F133   20 7F F1   JSR $F17F  [$00:F17F]   A:0005   X:0001   Y:0002   P:envMxdizc
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$00/F17F   48    PHA   A:0005   X:0001   Y:0002   P:envMxdizc - Push A onto Stack
$00/F180   4A    LSR A   A:0005   X:0001   Y:0002   P:envMxdizc -
$00/F181   4A    LSR A   A:0002   X:0001   Y:0002   P:envMxdizC -
$00/F182   4A    LSR A   A:0001   X:0001   Y:0002   P:envMxdizc - /8
$00/F183   85 3D   STA $3D    [$00:063D]   A:0000   X:0001   Y:0002   P:envMxdiZC - Store A in 063D.
$00/F185   64 3E   STZ $3E    [$00:063E]   A:0000   X:0001   Y:0002   P:envMxdiZC - Store Zero in 063E.
$00/F187   68    PLA   A:0000   X:0001   Y:0002   P:envMxdiZC - Pull A from Stack,
$00/F188   29 07   AND #$07   A:0005   X:0001   Y:0002   P:envMxdizC - AND 07 Only saves bits 1,2, and 4. Anything above them is set to 00.
$00/F18A   A8    TAY   A:0005   X:0001   Y:0002   P:envMxdizC - Transfer A to Y.
$00/F18B   60    RTS   A:0005   X:0001   Y:0005   P:envMxdizC - Return
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
$00/F136   A9 01   LDA #$01   A:0005   X:0001   Y:0005   P:envMxdizC - Load 01 into A.
$00/F138   C0 00 00   CPY #$0000   A:0001   X:0001   Y:0005   P:envMxdizC - Compare Y to 00.
$00/F13B   F0 05   BEQ $05    [$F142]   A:0001   X:0001   Y:0005   P:envMxdizC - If so, branch to end.
$00/F13D   0A    ASL A   A:0001   X:0001   Y:0005   P:envMxdizC - x2 A
$00/F13E   88    DEY   A:0002   X:0001   Y:0005   P:envMxdizc - 1 Y.
$00/F13F   4C 38 F1   JMP $F138  [$00:F138]   A:0002   X:0001   Y:0004   P:envMxdizc - Jump back to F138.
--------------------------------------------------------------------------------------------------
$00/F142   A6 3D   LDX $3D    [$00:063D]   A:0020   X:0001   Y:0000   P:envMxdiZC  - Load X from 063D (would be the Event Flag byte to look at)
$00/F144   1D 80 12   ORA $1280,x[$00:1280]   A:0020   X:0000   Y:0000   P:envMxdiZC - Add the amount of the flag present from the Event Flag Byte.
$00/F147   9D 80 12   STA $1280,x[$00:1280]   A:0039   X:0000   Y:0000   P:envMxdizC - Store A in the Event Flag.
[/code]

Very nicely done Square! This is very simple and effective.

It it quite simple really, I'll explain what Square did to look at it as well as I can...

It looks at raw hex of the Event Flag. (in this case it was 05)

It then takes that 05 and divides it by 8. This is how it finds what Event Flag Byte it is meant to be changing.

From there it stores the original flag hex and puts it into the stack and quickly withdraws it after the Event Flag Byte is found.

Once it is withdrawn it is AND'd to assure that the value is correct (remember the Event Flag Byte has already been chosen) making the last valid value as 07. Which corresponds with the last bit of a boolean)

A is transferred to Y and then is set to 01. This sets it for the proper path of being put successfully into the Event Flag Byte.

Y is compared to 00 to pass the branching condition which will occur when the original value (5 in this case) is successfully reached as an Event Flag Bit, in this case 05 would be the 5th Bit, which is 20 and that is where it is stored in the first Event Flag Byte as a 20.

I would basically just have to copy this code for the proper flag checks and your idea should be rather simple to put together PinkPuff! But I don't think I can handle that tonight. I'll give it a go tomorrow though.


avalanche

  • Mom Bomb
  • *
  • Posts: 122
    • View Profile
Can anyone think of any events that use the "move camera up one space then down again" instruction?

This one is used in some events that really want to shake the screen for effect. I think when the Enterprise is crash landing in the underground, maybe the Leviathan... It it usually combined with the horizontal screen shake rumble.

LordGarmonde

  • Baigan
  • *
  • Posts: 271
  • Gender: Male
  • "Power only breeds war..."
    • View Profile
...
I would basically just have to copy this code for the proper flag checks and your idea should be rather simple to put together PinkPuff! But I don't think I can handle that tonight. I'll give it a go tomorrow though.

Oh that's pretty nifty Grimoire LD.  :cycle:         -Best of luck with it; I'm excited to see how it comes out.  :childish:
"Now I know; and knowing makes it even more confusing..."

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
Can anyone think of any events that use the "move camera up one space then down again" instruction?

This one is used in some events that really want to shake the screen for effect. I think when the Enterprise is crash landing in the underground, maybe the Leviathan... It it usually combined with the horizontal screen shake rumble.

Ah, you're right. I hadn't considered that.. that means we have 3 free Event Instructions, (+Gil/-Gil/Nothing) not 4, my mistake.

Alright then PinkPuff with this knowledge let's see if I can build your event instruction... For continuity purposes I'll build it right out of my "Are all characters dead or petrified?" routine, as I said, it won't interfere with anything unless it's built into an event where the entire party has died (in which case you should set the healing instructions to occur immediately after the battle. This event instruction would also serve purpose for the Side Project to give some presence to the optional party for Zeromus.

Hmm... well after working on this for a little while I noticed a glaring issue...

There's no easy way to tell the game that an event instruction has been skipped and since they're of variable length this means that either...

1. A hack of this sort would need to be set to only skip Either 1 Byte Event Instructions OR Two Byte Instructions.

2. Create an "artificial" YY. This can be done in a fairly easy fashion, but it would involve manipulating the basic movement patterns... as the amount of instructions to skip. So let's say this... in the editor (at the moment. You might be able to program this into the editor with full capability PinkPuff) You would use "Load Graphic" and say you set it to 85, this implies that the game will look to see if Yang has been freed from brainwashing (80 acting as the "On Check", 5 Acting as the Event Flag to check) Secondly you put "Placement 1 Faces Up" Immediately After this would then be the "YY" and that would technically be 04 +1 Instructions skipped (since it will be using the basic Event Routine Progress your choice will Always have to be (Value skipped +1))

I'd much rather try and work out of 2, than 1, since 1 is too binding. I'll see what I can do.


And the first part is done! I now have part of it successfully implemented, here is my redone "check if dead/petrified" and then here is my "Is Event Flag XX on? If so, skip the next (as designated by next event instruction byte over) actions.

Code: [Select]
$00/FD71 AD 03 10 LDA $1003  [$00:1003] A:00FD X:0000 Y:0002 P:envMxdiZc - Load Slot 1's Status Byte 1.
$00/FD74 29 C0 AND #$C0 A:0040 X:0000 Y:0002 P:envMxdizc - Get rid of all bits that are not Petrify or Dead
$00/FD76 F0 1F BEQ $1F    [$FD97] A:0040 X:0000 Y:0002 P:envMxdizc - If 00, branch to Flag Check Portions.
$00/FD78 AD 43 10 LDA $1043  [$00:1043] A:0040 X:0000 Y:0002 P:envMxdizc (Do this for the next four slots)
$00/FD7B 29 C0 AND #$C0 A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD7D F0 18 BEQ $18    [$FD97] A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD7F AD 83 10 LDA $1083  [$00:1083] A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD82 29 C0 AND #$C0 A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD84 F0 11 BEQ $11    [$FD97] A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD86 AD C3 10 LDA $10C3  [$00:10C3] A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD89 29 C0 AND #$C0 A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD8B F0 0A BEQ $0A    [$FD97] A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD8D AD 03 11 LDA $1103  [$00:1103] A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD90 29 C0 AND #$C0 A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD92 F0 03 BEQ $03    [$FD97] A:0080 X:0000 Y:0002 P:eNvMxdizc
$00/FD94 4C 04 EB JMP $EB04  [$00:EB04] A:0080 X:0000 Y:0002 P:eNvMxdizc - Branch to Event Switch Routine
-----------------------------------------------------------------------------------------------------------------------------
$00/FD97 20 CB E2 JSR $E2CB  [$00:E2CB] A:0000 X:0000 Y:0002 P:envMxdiZc - Jump to Event Instruction position
00/FD9A 10 31 BPL $31    [$FDCD] A:0084 X:0001 Y:0002 P:eNvMxdizc - Branch if the Value is Positive (Flag is Off Portion)
----------------------------------------------------------------------------------------------------------------------------------
$00/FD9C 29 7F AND #$7F A:0084 X:0001 Y:0002 P:eNvMxdizc - Clear all negative bits.
$00/FD9E 20 7F F1 JSR $F17F  [$00:F17F] A:0004 X:0001 Y:0002 P:envMxdizc - Jump to Event Flag Byte Placement Routine
$00/FDA1 A9 01 LDA #$01 A:0004 X:0001 Y:0004 P:envMxdizC - Load 01 into A.
$00/FDA3 C0 00 00 CPY #$0000 A:0001 X:0001 Y:0004 P:envMxdizC - Compare Y to 00 (due to subroutine above, it is now the amount of times it needs to loop to reach appropriate Event Flag)
$00/FDA6 F0 04 BEQ $04    [$FDAC] A:0001 X:0001 Y:0004 P:envMxdizC - If 00 branch.
$00/FDA8 0A ASL A A:0001 X:0001 Y:0004 P:envMxdizC - x2 A
$00/FDA9 88 DEY A:0002 X:0001 Y:0004 P:envMxdizc -1 Y
$00/FDAA 80 F7 BRA $F7    [$FDA3] A:0002 X:0001 Y:0003 P:envMxdizc - Loop back to FDA3.
------------------------------------------------------------------------------------------------------------------
$00/FDAC A6 3D LDX $3D    [$00:063D] A:0010 X:0001 Y:0000 P:envMxdiZC - Load Event Flag Bit into X.
$00/FDAE 48 PHA A:0010 X:0000 Y:0000 P:envMxdiZC - Push Event flag onto Stack
$00/FDAF BD 80 12 LDA $1280,x[$00:1280] A:0010 X:0000 Y:0000 P:envMxdiZC - Load Event Flag Byte
$00/FDB2 AA TAX A:0019 X:0000 Y:0000 P:envMxdizC - Transfer Event Flag Byte to X.
$00/FDB3 85 FF STA $FF    [$00:06FF] A:0019 X:0019 Y:0000 P:envMxdizC - Store Event Flag Byte into 06FF.
$00/FDB5 68 PLA A:0019 X:0019 Y:0000 P:envMxdizC - Pull Event Flag Bit from Stack.
$00/FDB6 2D FF 06 AND $06FF  [$00:06FF] A:0010 X:0019 Y:0000 P:envMxdizC - Test it against the Event Flag Byte to see if it goes through.
$00/FDB9 D0 01 BNE $01    [$FDBC] A:0010 X:0019 Y:0000 P:envMxdizC - If it is not 00, proceed.
-------------------------------------------------------------------------------------------------------------------------
$00/FDBB 60 RTS A:006D X:006B Y:0000 P:envMxdizc - Return
----------------------------------------------------------------------------------------------------------------------
$00/FDBC AE D3 09 LDX $09D3  [$00:09D3] A:006D X:006B Y:0000 P:envMxdizc - Load  X from Event Placements.
$00/FDBF BF 00 82 12 LDA $128200,x[$12:826B] A:0010 X:006B Y:0000 P:envMxdizC - Load A from Next Byte over (This is the dummy movement bit I mentioned above, which would correspond to how many instructions are skipped)
$00/FDC3 86 FF STX $FF    [$00:06FF] A:0001 X:006B Y:0000 P:envMxdizC - Store X in 06FF.
$00/FDC5 65 FF ADC $FF    [$00:06FF] A:0001 X:006B Y:0000 P:envMxdizC - Add the value of Event Placements onto A (Dummy Movement Bit set to 01, + Event Placement)
$00/FDC7 8D D3 09 STA $09D3  [$00:09D3] A:006D X:006B Y:0000 P:envMxdizc - Store this into the current Progress of Event Placement.

Whew! Now that was an interesting experiment and it seems to work great! I just need to throw in a check for "Is Event Flag XX Off?" Which as you can see, is already planned. I just need to get to it. So I think I can conclude this experiment to be a success!


 :edit: Let's get to the "If Event Flag is OFF then, shall we?

Code: [Select]

And that's done... it's is clean as I can get it, I'm sure someone else could condense it more, but it works perfectly fine as is, I rewrote the code to make it work with the Event Flag OFF Option.

[code]
$00/FD97 20 CB E2 JSR $E2CB  [$00:E2CB] A:000C X:0000 Y:0000 P:envMxdizc  - Jump to Event Instruction Pull Routine
$00/FD9A 29 7F AND #$7F A:000C X:0000 Y:0000 P:envMxdizc - Get rid of negative bit.
$00/FD9C 20 7F F1 JSR $F17F  [$00:F17F] A:000C X:0000 Y:0000 P:envMxdizc - Jump to Event Flag Byte Placement routine.
$00/FD9F A9 01 LDA #$01 A:000C X:0000 Y:0000 P:envMxdizc -  Load 01 into A.
$00/FDA1 C0 00 00 CPY #$0000 A:000C X:0000 Y:0000 P:envMxdizc - Compare Y to 0000 (Reaches Event Flag bit eventually)
$00/FDA4 F0 04 BEQ $04    [$FDAA] A:000C X:0000 Y:0000 P:envMxdizc - Branch if 00.
----------------------------------------------------------------------------------------------------------------
$00/FDA6 0A ASL A A:000C X:0000 Y:0000 P:envMxdizc - x2 A
$00/FDA7 88 DEY A:000C X:0000 Y:0000 P:envMxdizc - -1 Y
$00/FDA8 80 F7 BRA $F7    [$FDA1] A:000C X:0000 Y:0000 P:envMxdizc - Loop back.
---------------------------------------------------------------------------------------------------------------
$00/FDAA A6 3D LDX $3D    [$00:063D] A:000C X:0000 Y:0000 P:envMxdizc - Load Event Flag Bit into X.
$00/FDAC 48 PHA A:000C X:0000 Y:0000 P:envMxdizc - Push Event Flag onto Stack.
$00/FDAD AD D6 09 LDA $09D6  [$00:09D6] A:000C X:0000 Y:0000 P:envMxdizc - Load Event Flag Byte into X.
$00/FDB0 10 0D BPL $0D    [$FDBF] A:000C X:0000 Y:0000 P:envMxdizc - If positive, branch.
----------------------------------------------------------------------------------------------------------------------
$00/FDB2 BD 80 12 LDA $1280,x[$00:1280] A:000C X:0000 Y:0000 P:envMxdizc - Load Event Flag Byte Placement into A.
$00/FDB5 AA TAX A:000C X:0000 Y:0000 P:envMxdizc - Transfer Event Flag Byte into X.
$00/FDB6 85 FF STA $FF    [$00:06FF] A:000C X:0000 Y:0000 P:envMxdizc - Store A in 06FF.
$00/FDB8 68 PLA A:000C X:0000 Y:0000 P:envMxdizc - Pull Event Flag Bit from Stack
$00/FDB9 2D FF 06 AND $06FF  [$00:06FF] A:000C X:0000 Y:0000 P:envMxdizc - Get rid of all bits not present in 06FF in A.
$00/FDBC D0 0E BNE $0E    [$FDCC] A:000C X:0000 Y:0000 P:envMxdizc - Branch if Not 00 (Meaning Event Flag is On) to rest of routine
--------------------------------------------------------------------------------------------------------------------
$00/FDBE 60 RTS A:000C X:0000 Y:0000 P:envMxdizc
-----------------------------------------------------------------------------------------------------------------
$00/FDBF BD 80 12 LDA $1280,x[$00:1280] A:000C X:0000 Y:0000 P:envMxdizc
$00/FDC2 AA TAX A:000C X:0000 Y:0000 P:envMxdizc
$00/FDC3 85 FF STA $FF    [$00:06FF] A:000C X:0000 Y:0000 P:envMxdizc
$00/FDC5 68 PLA A:000C X:0000 Y:0000 P:envMxdizc
$00/FDC6 2D FF 06 AND $06FF  [$00:06FF] A:000C X:0000 Y:0000 P:envMxdizc
$00/FDC9 F0 01 BEQ $01    [$FDCC] A:000C X:0000 Y:0000 P:envMxdizc - (As above, except it is looking for a match within 06FF's bits and the Event Flag bit it is searching for)
----------------------------------------------------------------------------------------------------------
$00/FDCB 60 RTS A:000C X:0000 Y:0000 P:envMxdizc - Return
--------------------------------------------------------------------------------------------------------
$00/FDCC AE D3 09 LDX $09D3  [$00:09D3] A:000C X:0000 Y:0000 P:envMxdizc- Load X from Event Progress Placement.
$00/FDCF BF 00 82 12 LDA $128200,x[$12:8200] A:000C X:0000 Y:0000 P:envMxdizc - Load A from Event Placement +X (Dummy Movement Bit acting as the numerical value of actions to skip)
$00/FDD3 86 FF STX $FF    [$00:06FF] A:000C X:0000 Y:0000 P:envMxdizc - Store X in 06FF.
$00/FDD5 65 FF ADC $FF    [$00:06FF] A:000C X:0000 Y:0000 P:envMxdizc - Add 06FF onto A. (Event Placement + Dummy Movement Bit)
$00/FDD7 8D D3 09 STA $09D3  [$00:09D3] A:000C X:0000 Y:0000 P:envMxdizc  - Store A in Event Progress Placement.
$00/FDDA 60 RTS A:000C X:0000 Y:0000 P:envMxdizc - Return

And there we are! Now you may have Event Flags control actions taken within events and have different effects depending on whether it is On or Off and thrown in is the Dead/Petrified characters check.

« Last Edit: March 19, 2015, 04:00:50 PM by Grimoire LD »

Pinkpuff

  • Flan Princess
  • *
  • Posts: 924
  • Find a Megalixir in Unprecedented Crisis!
    • View Profile
Grimoire, you are indeed a miracle worker!!

So let me see if I understand this correctly...
  • The instruction in question is the one currently interpreted as "Load Graphic"
  • It will now essentially become "If flag XX is [ON/OFF] (based on top bit of XX; 1 = on, 0 = off), do the next YY actions"
  • The YY in this description is not a parameter in the usual sense but is read by the next byte following the instruction
  • If the specified flag matches the specified value, it will do the next number of bytes worth of actions (not counting the "fake parameter" byte)
  • If it does not, it will skip them (also skipping the "fake parameter" byte)

If this is correct, what I can do as far as the editor is concerned is get it to detect the patch on startup and set a flag in the editor which will tell it how to interpret the "Load Graphic" command (which I guess should now default to "Crash Game"?); that way it will be readable for both patched and unpatched roms.

Speaking of which, this could definitely be its own standalone patch, "Grimoire LD's Event Instruction Expansion Patch" or something
Let's dance!

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
Grimoire, you are indeed a miracle worker!!

So let me see if I understand this correctly...
  • The instruction in question is the one currently interpreted as "Load Graphic"
  • It will now essentially become "If flag XX is [ON/OFF] (based on top bit of XX; 1 = on, 0 = off), do the next YY actions"
  • The YY in this description is not a parameter in the usual sense but is read by the next byte following the instruction
  • If the specified flag matches the specified value, it will do the next number of bytes worth of actions (not counting the "fake parameter" byte)
  • If it does not, it will skip them (also skipping the "fake parameter" byte)

If this is correct, what I can do as far as the editor is concerned is get it to detect the patch on startup and set a flag in the editor which will tell it how to interpret the "Load Graphic" command (which I guess should now default to "Crash Game"?); that way it will be readable for both patched and unpatched roms.

Speaking of which, this could definitely be its own standalone patch, "Grimoire LD's Event Instruction Expansion Patch" or something

  • If the specified flag matches the specified value, it will do the next number of bytes worth of actions (not counting the "fake parameter" byte)
  • If it does not, it will skip them (also skipping the "fake parameter" byte)

    Close, but not quite.

    If the Specified Flag matches the Specified Value it will Skip the Next number of bytes worth of actions dependent on the fake parameter.
    If it does not match, it will play them, let me go by your example of Yang...

    "Crash Game 05" (Is Event Flag (05) "Yang free from Brainwashing?" OFF )
    "Character 1 Moves Left" (Dummy Parameter, meaning 01 (+1 from Carry) in this instance).
    "Show Message  XX" (Two bytes, so it needs to skip two bytes, if not active.) "Cecil: If only Yang were here..."
    (Continue event from here)

    Then let'use another example...

    Show Message "King: Cecil! It is good to see you."
    "Crash Game 133" (Is event Flag  (05)"Yang free from Brainwashing?" ON)
    NPC 2 Face Left (Dummy Parameter, tells the game to skip the next 17 (+1) instructions. Skipping to end of the event.
    Toggle Visibility of Yang NPC (1)
    Move Yang Right (1)
    Show Message "King: We feared the worst when we heard what happened with Leviathan!" (2)
    Show Message "Yang: I assure you my lord, I am no worse for wear!" (2)
    Clear Event Flag 05 (2) 8 Bytes used so it will display this message once and unless the previous flag is turned back on, it will not play again.
    "Crash Game 2XX" (2)(Is Event Flag (unused) OFF?)
    NPC 1 Face Right (1) (5  (+1) Skips)
    Show Message: (2)"King: You've returned not a moment too soon, Yang. A Dragon in Mt. Hobbs is disrupting our daily training. As our High Monk I ask you to vanquish it."
    Show Message: "(2) Yang: You have my word."
    Activate Event Flag XX (2) (Unused one from above)
    END

    (The next portion of the side quest as in getting the reward would be in a separate event, that just uses the normal Flag Check for speech)

    Because it is positive it will check to see if this Event Flag is Off, in order to play those instructions.

    I hope that made a bit more sense.

    As for creating a patch, that seems like a good idea. With this "dummy parameter" I set up I have a bit more freedom in what I want to do with the remaining unused event instructions.

    I really like the idea of implementing its use in the editor so it won't look so strange when compiled into a readable format.

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
Alright, so next will turn "Decrement x100 Gil" into Gain Stat (X) by Y amount, for Z Character.

This will be approached with the Dummy Movement Bit as all for the character.

Here is the plan...

XY.

X =

08=Strength
10=Agility
20=Vitality
40=Wisdom
80=Will

Y = Stat Increase (up to 7)

Z will be looked at on an Actor Basis so if you want Dark Knight Cecil to gain +5 Strength you would use Movement Byte 00 (Move Left). If the character is not present then they simply will not gain the stat.



But that plan will come for another day. As of now here is the Party Dead/Flag Check Patch.

(Please let me know if this patch actually works. I tried something a little different for the patching process so I'm not sure if it will work correctly.)

As always the patch must be unheadered!

If anyone has other ideas for new Event Instructions let me know and I'll see what I can do.

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
If I'm understanding correctly, you could actually make the max stat increase 8.
0,1,2,3,4,5,6,7 would raise the stat 1,2,3,4,5,6,7,8 respectively. You wouldn't use the instruction to raise a stat by zero, after all.
Also, would this be able to raise multiple stats with one instruction? For instance, if I made my parameter "CX" would it raise both Wis and Will by X?
Also, I don't really understand what you're saying about Z...
I'm going to disappear for about a week - got some real world stuff I need to do - so this will be my last message for a while.
Some cool stuff happening here, though. I look forward to seeing what develops!

Pinkpuff

  • Flan Princess
  • *
  • Posts: 924
  • Find a Megalixir in Unprecedented Crisis!
    • View Profile
Ok so if it matches it will skip, and if it does not match, it will execute them...
Let's dance!

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
If I'm understanding correctly, you could actually make the max stat increase 8.
0,1,2,3,4,5,6,7 would raise the stat 1,2,3,4,5,6,7,8 respectively. You wouldn't use the instruction to raise a stat by zero, after all.
Also, would this be able to raise multiple stats with one instruction? For instance, if I made my parameter "CX" would it raise both Wis and Will by X?
Also, I don't really understand what you're saying about Z...
I'm going to disappear for about a week - got some real world stuff I need to do - so this will be my last message for a while.
Some cool stuff happening here, though. I look forward to seeing what develops!

Hah, I didn't think about that Chillyfeez, I just assumed it would be easier to use the half-byte in its basic sense, but I could throw in a "+1" to the entire thing to make it whatever is chosen +1.

Now Z is using the same system I used for the Flag Check, using a Dummy Movement bit to choose the actor that would get the stat boost. And yes, as you pointed out you could use this to increase two or more (or all) stats by Y.

Ok so if it matches it will skip, and if it does not match, it will execute them...

That is purely if it is a Positive.

If the bit reads Negative it will look to Not Match the Event Flag to Skip Instructions, it the correct Event Flag is ON then the instructions will play. If the bit reads Positive it will be the opposite. It will look to see if a certain Event Flag is OFF otherwise it will skip the instructions.

Pinkpuff

  • Flan Princess
  • *
  • Posts: 924
  • Find a Megalixir in Unprecedented Crisis!
    • View Profile
Ok so if it matches it will skip, and if it does not match, it will execute them...

That is purely if it is a Positive.

If the bit reads Negative it will look to Not Match the Event Flag to Skip Instructions, it the correct Event Flag is ON then the instructions will play. If the bit reads Positive it will be the opposite. It will look to see if a certain Event Flag is OFF otherwise it will skip the instructions.

What in the world?...

Ok so if the high bit of XX is 1, it will play on a match (ON) and skip on a mismatch (OFF), but if the high bit of XX is 0, it will skip on a match (OFF) and play on a mismatch (ON)?

 :edit: I tried downloading and applying the patch but it looks like it messed with many of my events... (yes I used an unheadered rom)... are you sure the patch changes nothing else besides those instructions?
« Last Edit: March 20, 2015, 12:16:48 PM by Pinkpuff »
Let's dance!

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
Ok so if it matches it will skip, and if it does not match, it will execute them...

That is purely if it is a Positive.

If the bit reads Negative it will look to Not Match the Event Flag to Skip Instructions, it the correct Event Flag is ON then the instructions will play. If the bit reads Positive it will be the opposite. It will look to see if a certain Event Flag is OFF otherwise it will skip the instructions.

What in the world?...

Ok so if the high bit of XX is 1, it will play on a match (ON) and skip on a mismatch (OFF), but if the high bit of XX is 0, it will skip on a match (OFF) and play on a mismatch (ON)?

 :edit: I tried downloading and applying the patch but it looks like it messed with many of my events... (yes I used an unheadered rom)... are you sure the patch changes nothing else besides those instructions?

Yes, you have it right now.

Hmm, I was worried that might be the case, what events are messed up out of curiosity?

Pinkpuff

  • Flan Princess
  • *
  • Posts: 924
  • Find a Megalixir in Unprecedented Crisis!
    • View Profile
Ok so if the high bit of XX is 1, it will play on a match (ON) and skip on a mismatch (OFF), but if the high bit of XX is 0, it will skip on a match (OFF) and play on a mismatch (ON)?

Yes, you have it right now.

So suppose I want some event instructions to play when a certain flag is OFF and skip when it's ON. How do I express that using this?

Because the way I understand it, if I send it the flag + 0x00 then it will play the event on a mismatch (i.e. if the flag is ON). But if I send it the flag + 0x80 then it will play the event on a match (i.e. if the flag is... ON). So regardless of whether I add 0x80 or not, it will play when the flag is ON, and skip when it's OFF, making the high bit toggle completely redundant as far as I can tell...

Hmm, I was worried that might be the case, what events are messed up out of curiosity?

Tons of them...
  • "Receiving the pan" contains a YES/NO box
  • "Do you have the clerics permission" is empty
  • "Open a door" contains a battle with Rubicant
  • So does "Locked"
  • So does "Namingway"
  • "Opening Events" adds and then immediately removes a bunch of actors
Among a bunch more... I can make an exhaustive list if needed.
Let's dance!

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
Ok so if the high bit of XX is 1, it will play on a match (ON) and skip on a mismatch (OFF), but if the high bit of XX is 0, it will skip on a match (OFF) and play on a mismatch (ON)?

Yes, you have it right now.

So suppose I want some event instructions to play when a certain flag is OFF and skip when it's ON. How do I express that using this?

Because the way I understand it, if I send it the flag + 0x00 then it will play the event on a mismatch (i.e. if the flag is ON). But if I send it the flag + 0x80 then it will play the event on a match (i.e. if the flag is... ON). So regardless of whether I add 0x80 or not, it will play when the flag is ON, and skip when it's OFF, making the high bit toggle completely redundant as far as I can tell...

Hmm, I was worried that might be the case, what events are messed up out of curiosity?

Tons of them...
  • "Receiving the pan" contains a YES/NO box
  • "Do you have the clerics permission" is empty
  • "Open a door" contains a battle with Rubicant
  • So does "Locked"
  • So does "Namingway"
  • "Opening Events" adds and then immediately removes a bunch of actors
Among a bunch more... I can make an exhaustive list if needed.

Ah, I should have known better than to try and use my Side-Project Rom for that. That's the core of the screw ups. Sorry about that. I should have just made an unaltered ROM (remove the header) and patched it with an unaltered ROM. Those reports at first scared me that I Really did screw up something with the entire event system, but thankfully that is not the case.

I had thought though since the two ROMs I used were copies of one another with the only differences being (admittedly Namingway) and the new event instruction space the only changes carried over would be the differences, but it seems the entire thing was carried over. Eh, maybe I misunderstand something fundamentally about IPS.

Now as for your query about the flags...

(Admittedly even I'm getting a bit tripped up here)

IF you want the event instructions to Skip when a Flag is ON you would use 0x00. (This looks for a mismatch which implies the Flag to Check is Off and to Skip instructions if So)
IF you want the event instructions to skip when a Flag is OFF you would use 0x80. (This looks for a match which implies the Flag to Check is On and to Skip Instructions if So)

Quote
So suppose I want some event instructions to play when a certain flag is OFF and skip when it's ON. How do I express that using this?

Something like that was listed in my example.

"Crash Game 2XX" (2)(Is Event Flag (unused) OFF?)
NPC 1 Face Right (1) (If Not 5  (+1) Skips)
Show Message: (2)"King: You've returned not a moment too soon, Yang. A Dragon in Mt. Hobbs is disrupting our daily training. As our High Monk I ask you to vanquish it."
Show Message: "(2) Yang: You have my word."
Activate Event Flag XX (2) (Unused one from above)
END

I do hope that makes a little more sense, I probably made this more obtuse than it should have been (as is often my failing with hacking)


Alright, now  this patch was made from two fresh ROMs (with the headers removed with the only differences being the new event instruction and a location in the pointer table to the new event instruction.

(1 KB so that seems like it should be the ticket)

Pinkpuff

  • Flan Princess
  • *
  • Posts: 924
  • Find a Megalixir in Unprecedented Crisis!
    • View Profile
IF you want the event instructions to Skip when a Flag is ON you would use 0x00. (This looks for a mismatch which implies the Flag to Check is Off and to Skip instructions if So)
IF you want the event instructions to skip when a Flag is OFF you would use 0x80. (This looks for a match which implies the Flag to Check is On and to Skip Instructions if So)

A given event flag is "OFF" when it has a value of 0 correct? So when the high bit of the XX parameter is 0 (i.e. we added 0x00 / didn't add anything / just the raw flag number), then the high bit matches when the flag also has a value of 0, meaning it is OFF... right? In the above, you seem to be saying that an OFF flag (0) mismatches a high bit of 0...

Something like that was listed in my example.

"Crash Game 2XX" (2)(Is Event Flag (unused) OFF?)
NPC 1 Face Right (1) (If Not 5  (+1) Skips)
Show Message: (2)"King: You've returned not a moment too soon, Yang. A Dragon in Mt. Hobbs is disrupting our daily training. As our High Monk I ask you to vanquish it."
Show Message: "(2) Yang: You have my word."
Activate Event Flag XX (2) (Unused one from above)
END

What is "2XX" in this example? double XX? can't be.. 0x200 + XX? Also seems like it can't be that either....

Sorry if I'm being bothersome about this, but I need to make sure I fully and correctly understand what's going on before I can code it into the editor...

Alright, now  this patch was made from two fresh ROMs (with the headers removed with the only differences being the new event instruction and a location in the pointer table to the new event instruction.

(1 KB so that seems like it should be the ticket)

The events are no longer messed up. Looks like a success so far! Time to start toying with the new instruction  :childish:

 :edit: After some initial experimentation, this is how I would describe what this instruction appears to be doing:

If the flag value matches the high bit of the XX parameter, skip a number of bytes worth of instructions specified by the next byte. This includes skipping that byte (perfect).
If the flag value does not match the high bit of the XX parameter, execute all the next instructions... including the "dummy parameter" byte. In other words, if the byte following the "Crash Game XX" instruction said "Placement 1 moves up", then placement 1 will indeed move up (not ideal).
« Last Edit: March 21, 2015, 09:16:38 AM by Pinkpuff »
Let's dance!