Urban Runner (CD2DVD / GOB) question
Moderator: ScummVM Team
Urban Runner (CD2DVD / GOB) question
I'm interested if it's possible to make a DVD out of it (English version) to avoid in-game swapping.
Tried the basics of putting all files to 1 disc.
The problem lies when the switch disk dialog pops up: it always selects the first CD?.ITK file it finds instead of the correct CD3.ITK or CD4.ITK.
Changing MDO.DEF to 'CDROM:NO' loads from HD (faster testing). Same problem though.
Having the file NO_CD.TXT seems to bypass this dialogue but requires the files to be decompressed already (Filemon).
Merging the CD1-4.ITK files isn't doable - VMDs with same names but different sizes, no packing used.
Looking through Intro.stk ($2E52A onwards), I can see {16}[file_name][00]. Then there's {63}{17}[xxxx] and other weird opcodes. Tinkered a lot but no dice.
Cheat Engine says that ~2E52A-2E54B but not 2E54C gets accessed (using NO_CD.txt approach). Didn't get far either with lack of proper opcode analysis / understanding.
Read the 'gob' engine several times. Don't really understand the flow. Does the scripting engine use relative jumps? I don't see what opcode(s) trigger the FindFirst / FindNext searching.
I'd compile ScummVM and slowly work/debug the issue first but it doesn't play with MSVC 6.
Thanks for any insight someone can provide.
Tried the basics of putting all files to 1 disc.
The problem lies when the switch disk dialog pops up: it always selects the first CD?.ITK file it finds instead of the correct CD3.ITK or CD4.ITK.
Changing MDO.DEF to 'CDROM:NO' loads from HD (faster testing). Same problem though.
Having the file NO_CD.TXT seems to bypass this dialogue but requires the files to be decompressed already (Filemon).
Merging the CD1-4.ITK files isn't doable - VMDs with same names but different sizes, no packing used.
Looking through Intro.stk ($2E52A onwards), I can see {16}[file_name][00]. Then there's {63}{17}[xxxx] and other weird opcodes. Tinkered a lot but no dice.
Cheat Engine says that ~2E52A-2E54B but not 2E54C gets accessed (using NO_CD.txt approach). Didn't get far either with lack of proper opcode analysis / understanding.
Read the 'gob' engine several times. Don't really understand the flow. Does the scripting engine use relative jumps? I don't see what opcode(s) trigger the FindFirst / FindNext searching.
I'd compile ScummVM and slowly work/debug the issue first but it doesn't play with MSVC 6.
Thanks for any insight someone can provide.
Re: Urban Runner (CD2DVD / GOB) question
You could always grab a copy of VC++ 2008 Express Edition which is free - http://www.microsoft.com/express/vc/ IIRC the SVN repository already includes VS2008 projects.shorthand wrote:I'd compile ScummVM and slowly work/debug the issue first but it doesn't play with MSVC 6.
- DrMcCoy
- ScummVM Developer
- Posts: 595
- Joined: Sat Dec 17, 2005 1:33 pm
- Location: Braunschweig, Germany
- Contact:
Re: Urban Runner (CD2DVD / GOB) question
I can't help you there directly, I'm afraid. I haven't really wandered that far into Urban Runner's "territory" yet.shorthand wrote:The problem lies when the switch disk dialog pops up: it always selects the first CD?.ITK file it finds instead of the correct CD3.ITK or CD4.ITK.
Depends on what you mean by "jumps". There's no direct "jump ahead 5 bytes" command, but the basic unit, so to speak, is a block of n commands. So if that block is encapsulated by, say, an "if"-command, in case of a false-evaluation, the following n commands are ignored.shorthand wrote:Does the scripting engine use relative jumps?
It's probably either openItk() or checkData(), checking if the file existed, if no, open the next one.shorthand wrote:I don't see what opcode(s) trigger the FindFirst / FindNext searching.
I've got sources for a STK/ITK-extractor and TOT-decompiler I wrote here, might be of some use to you. Just copy the files to the ScummVM tools sources and add them to your compiler's build system (look at Makefile.diff how it needs to be build on unixoid system).
The decompiler won't cleanly decompile Urban Runner's scripts, though, because I haven't haven't yet even identified what new opcodes it uses. With a lot of playing around with it, you could maybe find which and how many arguments missing opcodes use.
Because the gob engine also lets scripts call specific offsets of other scripts (by name, or even by "last used", i.e. "jump at offset n in the script I was before this one"), and functions aren't indexed in the script file, the decompiler only finds functions that are called in the main execution path.
One last warning: Never ever insert or delete bytes from the scripts, that'll mess everything up.

- DrMcCoy
- ScummVM Developer
- Posts: 595
- Joined: Sat Dec 17, 2005 1:33 pm
- Location: Braunschweig, Germany
- Contact:
Ah, and you should remove the line in degob_script.cpp:796, that's a function offset I needed when debugging something in Woodruff. ^^
Code: Select all
_funcOffsets.push_back(16098);
Got your code to work in VC++ 2008 Express.
This was the main problem the compiler had:
I'm amazed at how detailed your auto-analysis is.
Will be looking this stuff over carefully over the weeks.
Here's a prelim report:
This was the main problem the compiler had:
Code: Select all
//static const OpcodeGoblinEntryV4 opcodesGoblin[73] = {
static const OpcodeGoblinEntryV4 opcodesGoblin[72] = {
Will be looking this stuff over carefully over the weeks.
Here's a prelim report:
Code: Select all
00033716: o1_fillRect(101, 8, 96, 624, 272, 240);
00033737: if (var32_9688==11) {
00033749: o3_getTotTextItemPart(363, var8_12580, 0);
00033758: } else {
00033763: o3_getTotTextItemPart(364, var8_12580, 0);
00033771: }
00033778: var16_436 = 0;
00033786: var16_728 = 180;
00033794: var16_736 = 160;
00033801: var32_7708 = 0;
00033809: var32_7764 = var16_450;
00033810: o1_istrlen(var_0, var8_12580[var32_7708} of 60]);
Script_v1::o1_callSub
00033823: ERROR: Unknown block type 120 (1941)!
- DrMcCoy
- ScummVM Developer
- Posts: 595
- Joined: Sat Dec 17, 2005 1:33 pm
- Location: Braunschweig, Germany
- Contact:
Oh, seems like I can't count.shorthand wrote:This was the main problem the compiler had:Code: Select all
//static const OpcodeGoblinEntryV4 opcodesGoblin[73] = { static const OpcodeGoblinEntryV4 opcodesGoblin[72] = {

You mean of the scripts by the decompiler?shorthand wrote:I'm amazed at how detailed your auto-analysis is.
No, there's no real analysis going on, that's basically just a 1:1 mapping of the scripts.
Hmm, either the expression parser got extented or istrlen() changed, so that that isn't a real callSub. Or a new block type was introduced (rather unlikely).shorthand wrote:Here's a prelim report:Code: Select all
[...] 00033810: o1_istrlen(var_0, var8_12580[var32_7708} of 60]); Script_v1::o1_callSub 00033823: ERROR: Unknown block type 120 (1941)!
Thanks to your help, managed to change INTRO.STK to correctly load the correct CD*.ITK file from a DVD. No more CD nags.
Notes plus byte changes:
http://rapidshare.com/files/140109679/c ... d.txt.html
Allowed the bad 'dummy' calls to pass through.
Hard crash towards the later blocks.
Unsure if I can define some broad limits on this behavior. I'll try dancing around it though.
Notes plus byte changes:
http://rapidshare.com/files/140109679/c ... d.txt.html
Allowed the bad 'dummy' calls to pass through.
Hard crash towards the later blocks.
Code: Select all
00018276: repeat {
00018281: var32_7764 = 0;
00018288: o1_istrlen(var_0, var8_12580[var32_7708} of 60]);
00018299: *** URBAN callSub(1941);
00018302: if (var32_7768<var32_7764) {
00018315: var32_7768 = var32_7764;
00018324: }
00018336: } until (var32_7708==var16_442);
00012591: o2_createSprite(3093, 5378, 25344, -27369);
00012600: *** URBAN callSub(5987);
00012603: if (%) {
00038675: }
00030325: o1_loadCursor(-2, 119);
*** URBAN WARNING: o1_callSub: Offset 0 points into the header
- DrMcCoy
- ScummVM Developer
- Posts: 595
- Joined: Sat Dec 17, 2005 1:33 pm
- Location: Braunschweig, Germany
- Contact:
Poking it a bit, it seems OpcodeFunc 0.1 got changed, can be "dummied" by a function that takes 2 bytes as argument(s).
(You've apparently figured that out, too)
It's o2_createSprite(spriteIndex, width, height, flags). And unless the sprites array got extremly boosted (from 50 to > 3094) and lots of flags got added; or the negative flags value is some kind of magic value, the arguments don't make much sense.
(You've apparently figured that out, too)
There's probably something else wrong.shorthand wrote:Code: Select all
00012591: o2_createSprite(3093, 5378, 25344, -27369);
It's o2_createSprite(spriteIndex, width, height, flags). And unless the sprites array got extremly boosted (from 50 to > 3094) and lots of flags got added; or the negative flags value is some kind of magic value, the arguments don't make much sense.
Did some work with WLOADER.
ur_disasm = generic ideas on where to find data
v5_26 = o2_createSprite + special handling code
v5_45 = o1_istrlen + special handling code
Those two are out of my league but here's the trace notes for your expertise.
http://rapidshare.com/files/140410663/Desktop.7z.html
I'll check into this another day:
00030325: o1_loadCursor(-2, 119);
If you know how many args they should take for the exception cases, I'll try doing some further degob work.
ur_disasm = generic ideas on where to find data
v5_26 = o2_createSprite + special handling code
v5_45 = o1_istrlen + special handling code
Those two are out of my league but here's the trace notes for your expertise.
http://rapidshare.com/files/140410663/Desktop.7z.html
I'll check into this another day:
00030325: o1_loadCursor(-2, 119);
If you know how many args they should take for the exception cases, I'll try doing some further degob work.
- DrMcCoy
- ScummVM Developer
- Posts: 595
- Joined: Sat Dec 17, 2005 1:33 pm
- Location: Braunschweig, Germany
- Contact:
Well, I crawled a bit through the Urban Runner disassembly and found that OpcodeFunc 0.1 is still a callSub and that istrlen(), createSprite() and loadCursor() changed instead.
In the SVN repository are now updated degob-sources with (still incomplete, of course) support for Urban Runner scripts. You should be able to decompile MENU.TOT, though.
You'd probably need to add degob_script_urban.cpp to the MSVC project files if none of my fellow team members who use that compiler (I don't) haven't done it already.
In the SVN repository are now updated degob-sources with (still incomplete, of course) support for Urban Runner scripts. You should be able to decompile MENU.TOT, though.
You'd probably need to add degob_script_urban.cpp to the MSVC project files if none of my fellow team members who use that compiler (I don't) haven't done it already.
Just finished the analysis also.
All scripts run fine except MENU.TOT (if you allow the createSprite subCall error, the rest goes through)
03 = loadCursor
- arg1 = FFFF --> (2)+(2+2+5) + 2+1 bytes
- arg1 = FFFE --> (2)+(2) + 2+1 bytes
- arg1 = 0000-FFFD --> 2+1 bytes (normal)
26 = createSprite
- arg3 > 0 --> incredibly nasty looking
- arg3 = 0 --> normal function
45 = istrlen
- arg1 = 80 --> $80 + VarIndex + VarIndex (some type of recursion)
- arg1 = 00 --> VarIndex + VarIndex (normal)
http://rapidshare.com/files/140604226/desktop.7z.html
I got what I needed though. Thanks a whole lot!
All scripts run fine except MENU.TOT (if you allow the createSprite subCall error, the rest goes through)
03 = loadCursor
- arg1 = FFFF --> (2)+(2+2+5) + 2+1 bytes
- arg1 = FFFE --> (2)+(2) + 2+1 bytes
- arg1 = 0000-FFFD --> 2+1 bytes (normal)
26 = createSprite
- arg3 > 0 --> incredibly nasty looking
- arg3 = 0 --> normal function
45 = istrlen
- arg1 = 80 --> $80 + VarIndex + VarIndex (some type of recursion)
- arg1 = 00 --> VarIndex + VarIndex (normal)
http://rapidshare.com/files/140604226/desktop.7z.html
I got what I needed though. Thanks a whole lot!