DiztinGUIsh icon indicating copy to clipboard operation
DiztinGUIsh copied to clipboard

Labels & Mirroring for assembling

Open IsoFrieze opened this issue 5 years ago • 5 comments

Since labels are assigned to PC offsets instead of SNES addresses, some problems arise due to the mirroring of certain memory locations in the SNES address space.

For example, if JML $808055 and JML $008055 both exist in the ROM, these will be assembled into different bytecode: 5C 55 80 80 vs 5C 55 80 00. However, both of these effective addresses map to the same PC offset, so if this offset is given a label, these two instructions will be identical, and will assemble identically.

Another example, SRAM is mapped to the lower half of banks $70-$7D in LoROM. The higher half is mapped to ROM. An effective address of $7DFFFF points to (the last byte in the bank) ROM. An autogenerated label will 'unmirror' this effective address to, say, $0DFFFF. But if this address is used as a negative index base to SRAM ($7DFFFF+1 = $7D0000), the effective address should refer to SRAM for this instruction, even though it points to ROM.

I think most of this will be fixed by mapping labels to ROM address, which will also allow for RAM addresses to be labeled as well.

IsoFrieze avatar Apr 23 '19 22:04 IsoFrieze

Gradius III also uses $7DFFFF as negative reference to the WRAM. Overall, negative reference labels will often cause trouble in both ROM and RAM.

VitorVilela7 avatar Apr 24 '19 05:04 VitorVilela7

A recent commit (https://github.com/Dotsarecool/DiztinGUIsh/commit/1883a3758cb35307c54def469361a22ccc7c18f3) changed labels to associate them with SNES addresses instead of PC offsets. This will help with the first issue. I'm planning to allow for setting an intermediate address offset per instruction, which will help with the second issue. So you can specify an offset of -1 for an instruction such as LDA $7DFFFF,X, which will disassemble as LDA.L WRAM_ADDR-1,X. Both of these should be available for v1.0.2.0.

IsoFrieze avatar Sep 17 '19 00:09 IsoFrieze

ah. I just caught up and hit this, and I think it's the cause of #17. the sample labels and comments are still stored as PC offsets in ExportDisassembly.cs despite labels being stored with SNES addresses, so it causes the sample disassembly to not display the labels correctly.

I also had a few (shakier) ideas for how to deal with the mirroring issues, using some kind of "Resolving" constraints so the code can find the multiple mirrored addresses possible, and then pick the one that matches the actual bytes in the file.

I think it'd be cool to have the main way to get a label value be by storing a reference to the RomByte a label refers to, and then compute the address from the RomByte. Then we're never storing the label address directly. That would allow you to do things like mark a section of ROM (or later, RAM) as a data structure or table, and then when you can resolve back to the original name of the data stucture. Then we could add expressions in there, as long as it resolved back to the original bytes.

i.e. if you have a data structure like this: struct PlayerInfo Hitpoints -> 2 bytes Magicpoints -> 2 bytes Flags skip -> 1 byte

Lets say we tell Diz that we have this data structure as a table of 3 players whose data was stored in RAM starting at 0x7E0050, and there's an instruction to read the 3d player's Magicpoints. The actual ROM bytes might say: STA 0x7E005C

Diz could know that because snes offset 0x7E005C is inside the table, that this must be part of that data structure and would generate this code for Asar for the struct:

struct PlayerInfo $7E0050
    Hitpoints skip 2
    Magicpoints skip 1
    Flags skip 1
endstruct

and for that instruction, it would write to the asm file the following:

STA PlayerInfo[2].Magicpoints     ; resolves to 0x7E005C

binary1230 avatar Oct 10 '20 02:10 binary1230

OK, I've begun the early work on sorta this and related stuff.

It'll be in my fork under branch "feature_expression_parsing", where i'm starting work on a simple expression parser (I will probably use a library called Sprache for this)

I'm building out the GUI, but the underlying stuff is working for a demo scenario.

Example: Say you had a line like this in the disassembly at ROM offset 0x18AF6:

LDA #$10

And you wanted the constant "$10" to actually be the name of a variable, like "PLAYER_1". Now you can do this: (GUI will do this under the hood)

constants.Constants["PLAYER_1"] = new DizConstant() {Value = 0x10};
expressions.Expressions[0x18AF6] = new DizExpression() {Expression = "#PLAYER_1"};

Now, when you use the table view, or do the asm export, it'll output:

LDA #PLAYER_1

One important aspect for now is, Diz will force you to use an expression that evaluates to the original bytes in the ROM. (we might make an option to turn that off in the future, could be useful in the case of writing patches).

That constraint can also help us deal with the mirroring issue. if an expression could compute to multiple valid mirrored addresses, then for the disassembly we can select the single address that matches the bytes in the ROM.

That's the current status, I need to output a list of defines for asar to consume, and implement some simple expression parsing so you can things like PLAYER_1+20 or WRAM_ADDR-1 or whatever.

binary1230 avatar Dec 13 '20 13:12 binary1230

a lot of this is going to be able to handled nicely by the new ByteSource mapping functionality in #48

binary1230 avatar May 23 '21 05:05 binary1230