Jump to content
Sign in to follow this  
Iran

PortableRA Beta

Recommended Posts

I was always a bit suspicious of the design of my parser. Too much boilerplate which is haskell is just unacceptable. I just had a epiphany on how to fix everything, so I'll give you a build once I am done.

 

Sadly my miniRA download (I have full ra elsewhere) and my campaign mix were on /tmp, which is RAMFS so I accidentally deleted it by rebooting.

Share this post


Link to post

Another bug.

 

In the main menu, escaping or returning to the first main menu restarts the background music. That means going between skirmish, campaign etc constantly restarts it.

 

 

IMHO selling the tech center but keeping the tech is a bug.

 

 

 

Also small map issue. One of the more glaring misplaced tiles, last mission for soviets.

 

Edited by r34ch

Share this post


Link to post

"In the main menu, escaping or returning to the first main menu restarts the background music. That means going between skirmish, campaign etc constantly restarts it."

 

That's intended and hard-coded, unless my patch changes the behavior from 3.03.

 

I'll make a note about the misplaced tile and I'll fix it. Did you test the fixed 13 a mission and checked the behavior in 13b?

 

Yesterday I started playing around with using Syringe (also used by Arda and Ares) and Open Watcom to re-implement parts of the game in C++, as an example of what I've done I've hooked all CrateClass functions and made them call a wrapper of their own function or my re-implementation of the function. It's feasible to do with Syringe but I got to figure out a few things.

 

https://gist.github.com/Iran/5123791

Edited by Iran

Share this post


Link to post

hat's intended and hard-coded, unless my patch changes the behavior from 3.03.

Ok, I'll rephrase that as a feature request. :P

 

Did you test the fixed 13 a mission and checked the behavior in 13b?

I'm working up the will power to replay those missions again. I'll report back in the next day or two.

Share this post


Link to post

Haha, yeah that's why I was asking people to test it, the mission is so boring and annoying. Well both versions are.

Edited by Iran

Share this post


Link to post

Really interested in your C++ reverse engineering! How much work do you think it would take to make one big disassembly of RA and then slowly transform it into inline assembly in C++ interspersed with stuff like your gist and Arda?

 

In general disassembling x86 is non deterministic, but with the symbols we have might provide enough known instruction start/end locations to get a pretty decent dissasembly. From there converting to inline assembly is pretty straight forward.

Share this post


Link to post

I'm using CChyper's disassembly which uses WW's symbols for the game. I'm gonna drop Syringe as I don't need it (though it's a really nice tool), I've already converted my code to JMP hook the start of functions and I'm currently only using Syringe as DLL injector. Once I feel like I'll see about patching the game to load my DLL if found.

 

Don't expect to see anything useful coming out of this anytime soon. It's a fun project for me though.

Share this post


Link to post

Wait, does Hyper have a full disassembly, or something partial like an IDB database?

Edited by Sonarpulse

Share this post


Link to post

Well I consider a "full disassembly" one that's fully annotated with everything every part of every function does. His disassembly (an IDA database) has 95+% of all symbols (variable names and function names) and has annotations here and there.

Share this post


Link to post

Here's RawFileClass: https://github.com/Iran/RA95pp/blob/master/src/RawFileClass.cpp

 

Example output from my hooks:

 

 

[2013/March/10] [11:27:05] calling RawFileClass::Set_Name(), arg = ABLDGIN1.AUD.

[2013/March/10] [11:27:05] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:05] calling RawFileClass::Set_Name(), arg = REDALERT.MIX.
[2013/March/10] [11:27:05] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:05] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:05] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:05] calling RawFileClass::Set_Name(), arg = ABLDGIN1.AUD.
[2013/March/10] [11:27:05] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:05] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:05] calling RawFileClass::Seek(), arg1 = 0, arg2 = 1.
[2013/March/10] [11:27:06] calling RawFileClass::Set_Name(), arg = CONSCMP1.AUD.
[2013/March/10] [11:27:06] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:06] calling RawFileClass::Set_Name(), arg = REDALERT.MIX.
[2013/March/10] [11:27:06] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:06] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:06] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:06] calling RawFileClass::Set_Name(), arg = CONSCMP1.AUD.
[2013/March/10] [11:27:06] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:06] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:06] calling RawFileClass::Seek(), arg1 = 0, arg2 = 1.
[2013/March/10] [11:27:12] CrateClass::Put_Crate called, ret = 1
[2013/March/10] [11:27:47] calling RawFileClass::Set_Name(), arg = ABLDGIN1.AUD.
[2013/March/10] [11:27:47] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:47] calling RawFileClass::Set_Name(), arg = REDALERT.MIX.
[2013/March/10] [11:27:47] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:47] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:47] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:47] calling RawFileClass::Set_Name(), arg = ABLDGIN1.AUD.
[2013/March/10] [11:27:47] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:47] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:47] calling RawFileClass::Seek(), arg1 = 0, arg2 = 1.
[2013/March/10] [11:27:48] calling RawFileClass::Set_Name(), arg = CONSCMP1.AUD.
[2013/March/10] [11:27:48] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:48] calling RawFileClass::Set_Name(), arg = REDALERT.MIX.
[2013/March/10] [11:27:48] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:48] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:48] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:48] calling RawFileClass::Set_Name(), arg = CONSCMP1.AUD.
[2013/March/10] [11:27:48] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:48] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:48] calling RawFileClass::Seek(), arg1 = 0, arg2 = 1.
[2013/March/10] [11:27:50] calling RawFileClass::Set_Name(), arg = NODEPLY1.AUD.
[2013/March/10] [11:27:50] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:50] calling RawFileClass::Set_Name(), arg = REDALERT.MIX.
[2013/March/10] [11:27:50] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:50] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:50] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:50] calling RawFileClass::Set_Name(), arg = NODEPLY1.AUD.
[2013/March/10] [11:27:50] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:50] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:50] calling RawFileClass::Seek(), arg1 = 0, arg2 = 1.
[2013/March/10] [11:27:51] calling RawFileClass::Set_Name(), arg = TRAIN1.AUD.
[2013/March/10] [11:27:51] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:51] calling RawFileClass::Set_Name(), arg = REDALERT.MIX.
[2013/March/10] [11:27:51] calling RawFileClass::Set_Name(), arg = SPEECH.MIX.
[2013/March/10] [11:27:51] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:51] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:51] calling RawFileClass::Set_Name(), arg = TRAIN1.AUD.
[2013/March/10] [11:27:51] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:51] calling RawFileClass::Seek(), arg1 = 0, arg2 = 0.
[2013/March/10] [11:27:51] calling RawFileClass::Seek(), arg1 = 0, arg2 = 1.
[2013/March/10] [11:28:16] CrateClass::Put_Crate called, ret = 1
[2013/March/10] [11:29:14] CrateClass::Put_Crate called, ret = 1
[2013/March/10] [11:30:28] CrateClass::Put_Crate called, ret = 1

Share this post


Link to post

For me a full dissasembly is one that you can reassemble and run, can assembly file be generated from his IDB database generate which does that?

Share this post


Link to post

When alt tabbing the game, a new music track loads each time.

 

 

As for your mission. It is still bugged. If you capture the chronosphere, nothing happens. You just gain the chronosphere, its power drain but no chronoshift ability.

If you paradrop infantry by it without destroying all the radar domes, you get text saying 'chronosphere self destruct' but it doesn't get destroyed. However the AI will start to attack it as it has been uncovered and once destroyed will trigger mission failure.

 

On the original 'bugged' mission though, the chronosphere self destructs when infantry paradrop near it.

Share this post


Link to post

What's suppsed to happen is that the Chronosphere self-destructs when you capture it because there's a "hidden Radar Dome" that Kukov didn't warn you about, this is explained in the briefing for the next (and final) Soviet mission.

 

So it seems someone needs to fix up the mission.

 

Did you check out the original version of the other version of the mission? I want you to check if capturing a Radar Dome on that mission causes it to get self-destruct and you then winning the mission.

 

Anyway I'm looking for people who want to fix this mission for me and if the other version of it is bugged too, that mission too.

 

@Sonarpulse: it's not possible to do what you want with IDA.

Edited by Iran

Share this post


Link to post

Yeah, that's my problem with IDA. I want to make an disassembler is specifically designed around producing something that can be reassembled every step of the process. It would start by using data constants for indeterminate instructions/regions, and then do dynamic analysis to flesh them out. Probably there would be

  1. "reckless mode" where it would do things like assume both branches from conditional jumps are valid, and thus you can "semi-statically" build a tree with a branch on every conditional jump of known code regions. It should be pretty easy to fill out most the executable this way
  2. "safe mode" to work with deliberately obfuscated programs were it only does dynamic analysis.

Also, it will allow you could build the "safe mode" tree branch by branch so you only fall back on "safe mode" when something goes wrong. Lastly to aid with modifications there will be "pragmas" to makes sure it picks instructions of the right length when multiple machine code representations fit a certain mnemonic, to allow you to modify a region and have it not balk when it realizes something doesn't match, and maybe to constraint certain position to be at exactly this byte, though the first option might make that redundant or otherwise not worth it.

Share this post


Link to post

Oh cool, media fire allows you to update files to not break links. Unfortunately I didn't so it right so there's a new link for you all. That said, I like the way the code works (only boilerplate needed to add a new mix type is the code that detects the mix), and you all get to benefit from some better "--helps"

 

It's not parsing my enum for me, so for now for the -t flag 0 it TD and 1 is RA unencrypted/unchecksummed. When i fix the upstream library it should be "tiberian-dawn" or "red-alert-normal"

 

Linux 32-bit: http://www.mediafire.com/?2zb11vk44p3sqad

Edited by Sonarpulse

Share this post


Link to post

Some more bugs;

 

Allies mission 1, CS, sarin gas crackdown. I had this weird bug. No idea how to reproduce and no save file :/

 

 

I started production of a rifle soldier by accident. I don't know if I had no money at the time but all infantry buttons had 'on hold'. I could resume and pause, but once finished, only one rifle soldier popped out. After that infantry built normally

 

 

 

 

 

 

Hmmm, I need more attachment space :o

 

Who do I ask?

Edited by r34ch

Share this post


Link to post

Hmmm, I need more attachment space :o

 

Who do I ask?

Host images externally. Imgur is the official-ish choice of this site ;)

Share this post


Link to post

Rebooted to windows to build, but ran into some weird linking errors. Posted a bug report so hopefully this will get sorted out.

Share this post


Link to post

r34ch thanks for the bug report. Sadly it's a very rare bug and I don't have any idea what causes it, I've seen and experienced multiple issues like that. Most of the time it causes me to be unable to buy any tanks. This issue also occurs in C&C95. :/

 

So I sadly can't do anything about it.

Share this post


Link to post

No worries.

 

 

 

Ant missions;

 

 

Mission 2, Ants get stuck at this spot (after barrels are destroyed?)

879FuP1.png

 

Units stuck on bridges when destroyed

d8nkw0H.png

 

Cursor bug applies to other units (prob fixed)

mo2yDEI.png

 

 

 

And my favourite, mission 4.

 

Invisible queen.

slAdIww.png

Share this post


Link to post

Cursor bug?

I just assumed its the same 'tech centre' bug that affects tanyas C4. Even though its a friendly(?) structure, you can still target it. Could be a map bug though.

Share this post


Link to post

Ah, does the invisible queen issue happen everytime? Weird no one reported it to be before. :S

 

The game speed in offline games (skirmish and single player) gets multiplied with the game/AI difficulty you chose, on top of the normal game speed slider. This is retarded and I'm gonna patch it. When you play against easy AI in skirmish the gamespeed is sllooowww and when playing against hard its very fast. Same thing with loading savegames. I want to remove this logic and always set the gamespeed for offline games to that of the normal game difficulty (you can still adjust it with the game speed slider like normally). Does anyone have issues with that?

 

I've also found the original landscape photos of a bunch of backgrounds used by C&C1 and RA1 renders, see:

http://cnc-comm.com/community/index.php?topic=2229.0

Edited by Iran

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×