Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - dangarfield

Pages: [1]
1
FF7 Tools / [PC] Mark.dat Online Editor
« on: 2023-01-16 12:11:35 »
Mark.dat Online Editor

For those who want to edit the selection triangle in game:
- Go to https://dangarfield.github.io/ff7-mark-dat-editor/
- Edit in the editor, download your new mark.dat
- Replace file in `data/battle` directory (don't forget to backup)
- Run game
- No installation required

Code: https://github.com/dangarfield/ff7-mark-dat-editor

Default editor view:


After editing:


In game view:

2
Hi, I'm trying to find the active selection triangle model (inverted tetrahedron) and potential animation data.

Eg: the yellow icon that sits above cloud here:


I've been through all 5k files in magic.lgp with no luck, I'm pretty sure it's not in the battle.lgp already.

Any ideas?

3
I have a few questions about battle operations that would be great to get clarity with on:

Note: DWORD = 4 bytes. But I'm just using 1BYTE, 2BYTE, 3BYTE, 4BYTE notation because it's clearer for the non-windows programmer in me.

1. Does a stack only exist for each single 'turn' of an actor?
    Eg, is it correct to say:
    - A stack only exists for an actor's turn and is only processing that actor's commands
    - Before an actor's turn, the stack is cleared
    - Multiple 'attacks' etc, can be chained, the actor's turn only ends when it hits the END op code (0x73). The last position of the last action is lost, eg always go from 0x0000 of main script etc for each main turn
    - All local variables (0x0000 - 0x03FF) (and global variables) are persisted between each actor's turns. Local variables are set to 0 at beginning of battle only

2. Types and what is pushed on stack from address. 2x mainly
Is it correct to say the following when invoking some commands:

LOAD ADDRESS: 1x commands
    The following commands are effectively all the same:
Code: [Select]
    - 10 03 83
    - 11 03 83
    - 12 03 83
    - 13 03 83
  ->   push address '0x0383' to the stack ALWAYS as a 2BYTE even though the type '10' -> 1bit as 1BYTE, '11' -> 1BYTE, '12' -> 2BYTE, '13' -> 4BYTE.
  ->   stack:    12 03 83
    eg, is the x in `1x` always a 2 in what is added to the stack? is does the x remain as the same in the op code, but the engine just knows that it will always be a 2BYTE value regardless of what the 1x's x value is?

LOAD VALUES: 0x commands

    If arg is 0x0000-0x3FFF, the values are fetched and pushed as 0x variable, eg: (assume arg 0x0123 has value of 0x2345)
Code: [Select]
        Command -> 00 01 23 -> get bit value of 0x2345 store as 00 (bit) -> stack: 00 01 (0x2345 first bit = 1)
        Command -> 01 01 23 -> get byte value of 0x2345 store as 01 (byte) -> stack: 01 45 (0x2345 first byte 0x45)
        Command -> 02 01 23 -> get 2byte value of 0x2345 store as 02 (2byte) -> stack: 02 23 45
        Command -> 03 01 23 -> get 4byte value of 0x2345 store as 03 (4byte) -> stack: 03 00 00 23 45

    If arg is 0x4000-0xFFFF, the values are for ALL objects in battle eg: (assume only player 3 & enemy 1, with current HP of 0x567 and 0x789 respectively)
Code: [Select]
        Command -> 00 41 60 -> get bit value for each actor store as 20 (bit) -> stack: 20 00 00 01 00 01 00 00 00 00 00
              or is this a simple bit mask in a 2BYTE, eg 0xb0000010100 -> 0x0014 (eg, 20 00 14, up to a potential max of 20 03 FF)
        Command -> 01 41 60 -> get byte value for each actor store as 21 (byte) -> stack: 21 00 00 67 00 89 00 00 00 00 00
        Command -> 02 41 60 -> get 2byte value for each actor store as 22 (2byte) -> stack: 22 0000 0000 0567 0000 0789 0000 0000 0000 0000 0000
        Command -> 03 41 60 -> get 4byte value for each actor store as 24 (4byte) -> stack: 23 00000000 00000000 00000567 00000000 00000789 00000000 00000000 00000000 00000000 00000000

3. Global values bit masks

Take 0x20A0 - Bit mask of actors indicating actors the current actor considers as enemies
Assumed command - 02 20 A0 -> Push value to stack of 0x20A0, store value as a 2Byte value
Assumed enemies - All 3 players only
Is the result value added to stack 0b0000000111 (eg 0x0007) -> 20 00 07
 or because it's a x=2 command, each actor has a 2 byte value, eg:
 -> 22 0001 0001 0001 0000 0000 0000 0000 0000 0000 0000



4. Example reversing walkthrough

I'm sure that I will have a myriad more questions, but I would love to able to fish for myself. Would anyone be able to make a brief video / tutorial to show how I can step through this in debugger? I'm also willing to document and video the process for others once I know.

I can code and have decomposed most field and scene assets, but have very little experience with windows based reverse engineering (of running applications), but I think that a smaller tutorial would benefit a lot of people.
A good example would be: Stepping through the Grand Horn's AI in game, op by op, showing the ops and the resultant stack values (Grand Horn appears to be the simplest / shortest AI).

Thanks as always.

Note: I'm actually writing the whole of FF7 in a web based engine. All fields and menu engines are working. I've extracted and created models for all battle models etc, pretty much extracted in a readable way most field assets, now, I'm interested in making the battle engine. All is promising and it will work, just need some pointers in the battle stack.

Additonal links that I've found useful for future reference:
https://pastebin.com/raw/mjfRFNsZ
https://forums.qhimm.com/index.php?topic=3290.msg45951#msg45951
https://forums.qhimm.com/index.php?topic=18668.75
https://wiki.ffrtt.ru/index.php/FF7/Battle/Battle_Scenes/Battle_AI_Addresses
https://wiki.ffrtt.ru/index.php/FF7/Battle/Battle_Mechanics
https://wiki.ffrtt.ru/index.php/FF7/Battle/Battle_Scenes#AI_Data
https://wiki.ffrtt.ru/index.php/FF7/Battle/Battle_Scenes/Battle_Script
https://faqs.neoseeker.com/Games/PS4/final_fantasy_vii_dynamixdj.txt

4
Hi,

I'm just adding battle models (battle.lgp) and scene.bin exporting to kujata (see https://dangarfield.github.io/kujata-webapp/battle-models for previews) and fenrir and I'm unsure about how to correlate the battle models to the enemy IDs.
I assume there is a table in the exe / some data file but I haven't found it yet in the battle directory.

Eg:
Elfadunk - Scene.bin ID: 76 (0x4C) - battle.lgp model: cyaa
Mandragora - Scene.bin ID: 79 (0x4F) - battle.lgp model: dbaa
Levrikon - Scene.bin ID: 80 (0x50) - battle.lgp model: dcaa

I can approximate this roughly (aa = 0, ab = 1, ac = 2... cy = 25 + 25 + 24 + 3 = 76, but I just wanted to check that there isn't a better way of looking this up.
Also the same for the playable character files. Any locations in exe memory or data files I should be looking?

5
Hi,

I'm just playing around LINE field op code (0xD0) and have a few questions about the game behaviour.
I'll update this after:
http://wiki.ffrtt.ru/index.php?title=FF7/Field/Script/Opcodes/D0_LINE

There are generally 6 scripts (other than the init and main) if the entity is a LINE (taken from Makou Reactor):

  script index 2 -> S1 - [OK]
  script index 3 -> S2 - Move
  script index 4 -> S3 - Move
  script index 5 -> S4 - Go
  script index 6 -> S5 - Go 1x
  script index 7 -> S6 - Go away

[OK]
Occurrences - This is often present, but mostly contains a single RET op code.
Behaviour - I'm sure this is triggered when the player is close to the line and presses the [OK] button, eg blin59

Move
 - Occurrences
The script index 2 Move is often present, but again mostly contains a single RET op code.
The script index 3 Move is not often present but when it is, the script index 2 typically isn't, again, always ends with a RET.
There are 11 occurrences when both index 2 & 3 Move are present and both have more than one single RET op code.
10 of these contain exactly the same ops in both (fields - hyou4, hyou5_4)  - A REQEW and a RET with exactly the same params. Every one of these leads to a MAPJUMP.
1 of these (field - del12) contains 2 ops in the index 2 Move script (UC,MENU, and no RET). The index 3 Move script contains 11 ops including a final RET op

As a result of the above, I believe that it is relatively safe to assume the following logic:

 - Behaviour
This is triggered every time the player is close to the line.
If the index 2 Move is present, it executes until it receives a RET or finishes all of the ops, then
If the index 3 Move is present, it executes until it receives a RET or finishes all of the ops.

Go
Occurrences - This is often present, and always contains a final RET op code.
Behaviour - I'm sure this is triggered every time the player leaves the line

Go 1x
Occurrences - This is occasioanlly present, and always contains a final RET op code.
Behaviour - I'm sure this is triggered when the player leaves the line, but only once for the duration of the time in the field. Come examples are doors remaining open after they are programmatically triggered. bugin2.

Go away
Occurrences - Can be present alongside Go and Go 1x. Always contains a final RET op code.
Behaviour - Very similar to Go, but the distance that the player has to be away from the point is large (maybe 4x). Examples are the jumps on las0_6

It's worth noting that any combination of Go, Go 1x and Go away can be present an executable on any script.

Here is a JSON file containing a little more details on the occurrences, frequencies and combinations of the LINE op code usage: https://github.com/dangarfield/ff7-fenrir/blob/master/workings-out/output/line-occurences.json


Updates:
- Updated Move occurrences and behaviour- Should be final
- Updated Go, Go 1x & Go Move - Should be final

No further updates required.

Thanks,
Dan Garfield

6
I'm having two problems working with fields, this is the first of them, please can you help?

It's to do with the treatment of 0x000000 colours from the palettes, which depending on the bit mask should be transparent, but I can see in Makou Reactor, you get the correct colour. Here's an example:

2 images, One is Makou Reactor output, the second is my attempt. Map - mds5_1



Note: This is purely one tile on one layer. There are no other tiles that render in the destination position so all of the data has to be in the tile / palette. The example below are the first two pixels in the top left corner of the top left tile.

Tile details:
 Tile 383
 x destinationX -256 -> normalisedOverlayX 0
 y destinationY -256 -> normalisedOverlayY 0
 depth 1 z 4095 (eg tile.id)
 palette 3 (paletteId)
 texture sourceX 0 sourceY 128 -> 0,0 bytePosition 65536
 layer 0 z 4095 id 4095
 param 0
 state 0
 blending 0
 typeTrans 0

Pixel at tile position 0,1 is perfect:
 x 0 1 -> 1
 y 128 0 -> 0
  textureByteOffset 32769
  textureByteID 1 (ref to page/palette)
  paletteByte 4261 -> 0x0010A5
  color usePalette=true
  hex { r: 41, g: 41, b: 33, a: 255, hex: '292921' }

Pixel at tile position 0,0 is wrong:
  x 0 0 -> 0
  y 128 0 -> 0
  textureByteOffset 32768
  textureByteID 224 (ref to page/palette)
  paletteByte 0 -> 0x000000
  color usePalette=true
  hex { r: 0, g: 0, b: 0, a: 0, hex: '000000' }

Current logic for textureByteValue to hex is:

let COEFF_COLOR = 255 / 31 // eg translate 5 bit color to 8 bit
const getColorForPalette = (bytes) => { // abbbbbgggggrrrrr
    const color = {
        r: Math.round((bytes & 31) * COEFF_COLOR),
        g: Math.round((bytes >> 5 & 31) * COEFF_COLOR),
        b: Math.round((bytes >> 10 & 31) * COEFF_COLOR)
    }
    color.a = color.r === 0 && color.g === 0 && color.b === 0 ? 0 : 255
    color.hex = `${stringUtil.toHex2(color.r)}${stringUtil.toHex2(color.g)}${stringUtil.toHex2(color.b)}`
    return color
}

I was currently thinking about whether this is black or fully transparent, eg using the alpha bit above, but the desired pixel is a dark brown (around 0x302921) and there are a number of other pixels that follow this pattern also.

What am I missing? Can you point me in the right direction please. Even if it's just pointing towards a few lines of Makou Reactor. Whilst I've been through it a number of times, I can't easily see the answer. Thanks


7
Hi all,

I'm just having a look at reconstructing fields on a layer by layer approach for something I'm doing and am adding some code to picklejars' kujata repo. Whilst I do have a few questions that I may post to this community to help me understand and I'm am constantly looking through the Makou Reactor source code for tips, there is something that I just want to run by you.

I've decoded all fields except these:
'blin67_4',
  'nivgate2',
  'nivgate3',
  'nivl_e3',
  'gldst',
  'gldinfo',
  'rckt3',
  'kuro_11',
  'hyoumap',
  'gaiin_6',
  'trnad_52',
  'junone22',
  'rckt32',
  'jtemplc'.

The reason being is that the palette lengths are '12' bits, headers something like:
{
  length: 12,
  palX: 0,
  palY: 480,
  colorsPerPage: 256,
  pageCount: 0,
}

The thing here is pageCount = 0. So there are no palettes. None (other than the 6 colors on the flevel.background.palette object). So my question is, how do we overcome this? How do we get the rendered data? I've tried swapping calculating the colour from the texture value itself instead of accessing a palette, but no luck.

Any ideas? Apologies if I have missed something in Makou Reactor.

Thanks,
Dan

Pages: [1]