rofl0r / agsutils

contains utils for AGS: game extractor, repacker, disassembler and assembler
44 stars 14 forks source link

Problems with agssemble #2

Open adrimazon opened 6 years ago

adrimazon commented 6 years ago

Hello.

I'm trying to assemble a room.S into room.O, with agssemble.out, but I get an error. The error message reads:

./Assembler.c:138: get_variable_offset: Assertion '0' failed.

Please, could you tell me what wrong might be happening or give me a hint about how to fix it?

I haven't modified the files. They are the same ones that I extracted with agscriptxtract.out, a few minutes ago.

Thanks for your attention.

rofl0r commented 6 years ago

relevant code:

static int get_variable_offset(AS* a, char* name) {
        /* return globaldata offset of named variable */
        size_t i = 0; 
        struct variable item;
        for(; i < List_size(a->variable_list); i++) {
                assert(List_get(a->variable_list, i, &item));
                if(!strcmp(item.name, name))
                        return item.offset;
        }
        assert(0); 
        return 0;  
}

it means a named variable was not found in the global variable list; probably due to a bug somewhere else. you could add code before the assert(0) like dprintf(2, "variable not found: %s\n", name); and then look at the asm and try to figure out why it's not found in the global variable list.

adrimazon commented 6 years ago

Ok, thank you. I added that line to the code and now I know what variables the assembler doesn't find. However, I'm not sure what to do with that information. I couldn't find those variables nor in the rooms neither in globalscripts and if I add them as int, it compiles, but the game crashes with the message that I attach.

error ags

I have compared hexadecimally the original room and the recompiled one and the new one lacks much information. Is it possible that the problem is that the room is not being well decompiled from the beginning?

Here is one of the rooms I'm having troubles with:

https://drive.google.com/open?id=1HAIqxB7C35YJdwoMCr1M9OZha2eQl2yQ

And here the DTA:

https://drive.google.com/open?id=1H4ds6heFwduiI86d9Ih-pHs0Ha4f7BEs

EDIT: Maybe the problem is that some rooms have double background?

rofl0r commented 6 years ago

interesting error message. maybe @ivan-mogilko has an idea why it could be raised? you might also want to try older versions of AGS. the "missing information" you're refering to is debug info; every line of "AGS asm" is preluded with a linenumber statement, which these tools do not save currently. but it would probably not be very hard to add it.

ghost commented 6 years ago

Hello. Noticed this by pure coincidence today :).

The "old-style strings" in AGS were fixed sized arrays of 200 chars. In script their type is declared as lowercase "string", as opposed to modern "String" type (dynamically sized string). If the game was made with very old version of AGS, their presence is a natural thing, otherwise - it may be some mistake.

Regarding the error itself, unfortunately my memory on this is quite vague, because I was not dealing with that part of the engine code for a few years, so I had to reinvestigate. If I read code correctly, during compilation these strings are appended by 4-byte value which stores the address (offset in a huge global data array) of the beginning of a string. And the address of this value itself is stored in the "fixups" table. So, when loading compiled script, engine registers these strings in following way: it takes an address of this 4-byte control value from a table, finds it and reads an offset of actual string data from this value. Then it does this check:

if (glvar.ScAddress - data_addr != 200 /* size of old AGS string */)
{
    cc_error("unexpected old-style string's alignment");
}

Where glvar.ScAddress is an address of a control value, and data_addr is an address of the beginning of the string.

So question here is, whether this is a badly compiled script, or the engine is too restrictive in this case. I do not have any answer right now, this is something to investigate.

adrimazon commented 6 years ago

Hello. First of all, thank you both, @rofl0r and @ivan-mogilko, for your help. In fact, this game has been created with AGS 3.2. In addition, for my limited knowledge of the tool, on the one hand most of its rooms have double background, and on the other hand some of the texts are called through a function named DisplayMessage, which I don't know which file it refers to and I don't know if it is possible to recover them in some way. Do you think it would be possible to adapt the current desassembly/assembly tools to use them with this weird type of rooms?

If you need more information or any other file do not hesitate to ask me.

ghost commented 6 years ago

@adrimazon , are you by a chance doing translations? Someone was asking me about extracting DisplayMessage texts for translating them recently.

These messages are either global messages, if message ID is larger than 500, in which case they are in the main game data file (game28.dta for AGS 3.2), or room message, in which case they are stored in corresponding room file (.crm) in an encoded format* (relatively simple encoding, but cannot be seen by observing binary file contents).

So neither of them are part of the script, and will require separate tool other than disassembler.

adrimazon commented 6 years ago

Yes, I'm actually doing a translation. I thought I had already said it, I'm sorry about that.

Crimson Wizard had already told me something about that encoded format, and he suggested me that maybe I could use this code (https://github.com/adventuregamestudio/ags/blob/master/Common/ac/roomstruct.cpp) to generate some kind of extractor. The problem is that I don't know anything about programming and I don't know anyone who knows enough C# to do it. I don't want to sound shameless, but maybe you could help me out with this?

On a different note, do you think this encoded format may be the problem by which I can't disassemble all rooms with the tools of @Rofl0r?

ghost commented 6 years ago

Well, that was me, that is my nickname on AGS forums.

After I contacted the person who wrote text extractor, asking if he may add this functionality, or upload sources of his tool, he promised to look into this, but did not tell anything since.

I could quickly make a "dirty" extractor for these, but I wanted to wait until he answers something, because it would be much simplier to add new function into existing program.

On a different note, do you think this encoded format may be the problem by which I can't disassemble all rooms with the tools of @rofl0r?

What is the actual problem you are having? Like, what tool you use, and what result is different from what you expected? As far as I know this tool doesn't extract all parts of the room, only scripts.

adrimazon commented 6 years ago

Oh... It's a small world, indeed. I'm going crazy to solve these issues and be able to finish the translation with the quality I demand of myself. I guess there's nothing left to do but wait.

What is the actual problem you are having?

That's what I was saying at the beginning of the issue. I use agscriptxtract.out to decompile the rooms, without problems, I can even translate some words from the parser dictionary and it works well in the game. But when it comes to recompiling some of the rooms, I get errors because some variables are missing. If I simply declare them as int and initialize them to 0, the room compiles, but it doesn't work in the game, with various errors, like the one I attached earlier.

raulpuro commented 6 years ago

Hi,

Sorry for meddling in this conversation, but I think it's a little messy.

There are two problems, the problem of the encrypted texts that has already been discussed.

And there is a second problem with the parser, it is possible to extract the internal dictionary of the game, thanks to its tool, but only changing the words of the internal dictionary gives an error, we believe that in the rooms a comparison of the literal word is made, by example,

if (string == "Palace") {

display ("-----"); } In the internal dictionary we have changed "Palace" for "Palacio" but it does not find the word and it gives an error.

To work properly it is necessary to change all the string of the rooms for the same words in the dictionary, it is an inelegant and very laborious solution but it works.

To be able to change all the string of the rooms, we need to be able to decompile and recompile, but unfortunately it does not work.

I know it is a bit confusing and it is possible that with my vague explanation I have messed up more.

Sorry for the inconvenience caused and having to resort to you but as Adrian says unfortunately we have no programming knowledge.

Greetings.

ghost commented 6 years ago

Guys, this is really becoming awkward, because these problems with translations are not related to agsutils (at least not directly). As more and more information is added, it becomes less clear which of it even belongs here.

@raulpuro, in the past I wrote a version of the engine, that solves the problem with dictionary automatically, without need to change scripts. If you, or @adrimazon contact me on AGS forums again, I could send it to you.

ghost commented 6 years ago

Oh, sorry, on the second thought, I realized you may be already using that engine with a dictionary hack, and why it won't work in your case. This definitely needs another solution. Maybe I will be able to find some automatic solution for this, but cannot make any promises now.

Regarding the problem you are having with rofl0r's agsutils, not sure if I will be able to help much here, I do not know this program well enough.

rofl0r commented 5 years ago

i fixed a bug today which may solve this issue.