Author Topic: SCI mysteries  (Read 45938 times)

0 Members and 1 Guest are viewing this topic.

Offline troflip

Re: SCI mysteries
« Reply #15 on: April 30, 2015, 03:38:00 PM »
Another mystery. A few scripts in SQ4 load string offsets that don't point directly to the beginnings of strings in the string table.

In main:
    string_2b0d   = "nx.yyy"
and code loads, 2b0e, which would be "x.yyy"

In script 255 (Print):
     string_1671   = "\001PrintD"
and code loads 1672 ("001PrintD") and sets it as the Dialog's name selector value (how strange is that).


x.yyy seems like a version string. I'm wondering if 'n' and '\' are special markup that indicates something to some code in the kernel which looks backwards one byte from the string provided.
« Last Edit: April 30, 2015, 03:43:01 PM by troflip »
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline lskovlun

Re: SCI mysteries
« Reply #16 on: April 30, 2015, 04:59:48 PM »
Another mystery. A few scripts in SQ4 load string offsets that don't point directly to the beginnings of strings in the string table.

In main:
    string_2b0d   = "nx.yyy"
and code loads, 2b0e, which would be "x.yyy"

In script 255 (Print):
     string_1671   = "\001PrintD"
and code loads 1672 ("001PrintD") and sets it as the Dialog's name selector value (how strange is that).


x.yyy seems like a version string. I'm wondering if 'n' and '\' are special markup that indicates something to some code in the kernel which looks backwards one byte from the string provided.
Finding bugs in SCI Viewer now?  :) Seriously, this looks like a classic off-by-one bug to me. Also, which version of SQ4 is this? I don't see this in any of mine.

Offline troflip

Re: SCI mysteries
« Reply #17 on: April 30, 2015, 05:16:34 PM »
SCI Viewer says the interpreter is version 1.000.753
The game says "Space Quest IV   Version 1.052"

I'm pretty sure the 1.052 is filled in by the interpreter/kernel.

The game calls
Code: [Select]
FormatPrint(811 0 gGlobalThatPointsToXYYY)

(and FormatPrint just forwards it to the Format kernel)

Text resource 811/0 starts with:
"Roger Wilco and the Time Rippers\nSpace Quest IV     Version %s"

So somehow the kernel knows to substitute some version number for the string "x.yyy". ScummVM gets it right, so it must have that functionality in it somewhere?


As for bugs in SCI Viewer, I'm not sure what you mean. SCI Viewer correctly knows that SCI1 games use 32-bit entries for the export table (it shows things correctly).
« Last Edit: April 30, 2015, 05:18:31 PM by troflip »
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline troflip

Re: SCI mysteries
« Reply #18 on: April 30, 2015, 05:28:24 PM »
Ok, I figured out what was going on... the game code does actually write to this string (I didn't expect for code to write to the string table, but that's what it does).

My decompiled code shows this in script 803:
Code: [Select]
FileIO(5 gGlobalThatPointsToXYYY 6 = local2 FileIO(0 "version" 1))

Breaking it down, this opens the file called "version" :
Code: [Select]
= local 2 FilIO(0 "version" 1)

Then this reads the contents of the version file into the buffer pointed to by gGlobalThatPointsToXYYY, up to a max of 6 characters:
Code: [Select]
FileIO(5 gGlobalThatPointsToXYYY 6 local2)


Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline Collector

Re: SCI mysteries
« Reply #19 on: April 30, 2015, 05:50:55 PM »
I was wondering if it might not be stored in the VERSION file, since some SCI games check for the file before starting. For fun I just experimented by changing the VERSION file and the game reports the same. This would make sense since some patches changed the game version and sometimes included a new VERSION file.
KQII Remake Pic

Offline lance.ewing

Re: SCI mysteries
« Reply #20 on: May 04, 2015, 06:07:56 PM »
I've noticed a few things about code blocks over the past few weeks. Firstly it seems that procedures often share a code block with methods; more often than not I'd say. This makes sense I guess, since if you have a number of procedures immediately before a class definition, then the code for the methods defined in the class might be all grouped together in the same code block as the procedures. The order of "callable code units" within the code block in such a case would be the procedures followed by the methods. So far so good.

What I've also noticed is that you wouldn't get the methods for one class sharing a code block with the methods of another class. I guess this is a side effect of the compilation process. It would output the class block for one class when it gets to the end of that class definition, i.e. before it outputs the code block for the next class. This means that normally you'd get a pattern where a code block will have either all procedures (let's say if the procedures were at the end of the script) or all methods (where there are no procedures immediately above the class) or procedures at the top of the code block followed by methods. The methods and procedures are output in to the code block in the order in which they appear in the script file. That all makes sense.

Tonight I noticed something a bit strange though. It seems that sometimes we get procedures at the end of a code block, i.e. after the methods.

What does that imply? Could it mean that procedures can be defined within a class definition? I can't see how the compilation process would generate something like that if this was not the case.

What is the benefit of this? Why would they need procedures within a class? Why not make it a method?

Has anyone found byte code for a procedure appearing in a code block that has methods either side of it? If we can find an example of this, it might be stronger proof that procedures could appear within classes.

Offline lskovlun

Re: SCI mysteries
« Reply #21 on: May 04, 2015, 07:21:18 PM »
Tonight I noticed something a bit strange though. It seems that sometimes we get procedures at the end of a code block, i.e. after the methods.

What does that imply? Could it mean that procedures can be defined within a class definition? I can't see how the compilation process would generate something like that if this was not the case.

What is the benefit of this? Why would they need procedures within a class? Why not make it a method?
Well, what we found in the FreeSCI days is that procedures can and do use the self keyword, so they are assumed to execute in the context of some object or other.
I guess we never really looked at what code block those procedures belonged in.
As for the reasons, selector space must have been considered precious. While there was no maximum in SCI0, the selector vocab file was stored in heap memory. Having too many would limit the amount of memory available for other purposes. SCI1.1 had some reserved numbers, starting at 4096 (212).

Offline troflip

Re: SCI mysteries
« Reply #22 on: May 04, 2015, 07:31:48 PM »
In the SCI0 template game, there are three procedures that "belong" to a class:

(procedure (GetCel) of Extra
(procedure (IsSaveDialog) of SRDialog
(procedure (CueClient) of Timer

They could have easily been methods, but as Lars said, they maybe wanted to save on selectors? I don't see any cases where they get re-used between different unrelated classes, so at least code re-use doesn't seem to have been the purpose.

In my decompiled SQ5 source files, there is just one (the Timer one), which I detect by saying "oh hey, this is weird, there are property accessors in a procedure", then I look at all code in the script that calls that procedure, and hopefully (so far at least), it's always called from one class, so I mark the procedure as being "of" that class in the source code (which lets it compile while using self or property accessors).
« Last Edit: May 04, 2015, 07:33:50 PM by troflip »
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline lance.ewing

Re: SCI mysteries
« Reply #23 on: May 05, 2015, 02:36:30 PM »
Well, what we found in the FreeSCI days is that procedures can and do use the self keyword, so they are assumed to execute in the context of some object or other.
I guess we never really looked at what code block those procedures belonged in.

Yeah, I guess the use of the self keyword is pretty much absolute proof, isn't it? I wonder if using self makes sense to any procedure when invoked from within a method of a class, or whether it only makes sense to procedures that are part of the class, i.e. defined within the class, from whose method the procedure call originates. You guys probably know all this already from SCI development experience. Does SCI Studio and SCI Companion have support for procedures with calls to self?

Offline troflip

Re: SCI mysteries
« Reply #24 on: May 05, 2015, 03:21:04 PM »
Yeah, I guess the use of the self keyword is pretty much absolute proof, isn't it? I wonder if using self makes sense to any procedure when invoked from within a method of a class, or whether it only makes sense to procedures that are part of the class, i.e. defined within the class, from whose method the procedure call originates. You guys probably know all this already from SCI development experience. Does SCI Studio and SCI Companion have support for procedures with calls to self?

Clearly it has support for this, since I just outlined three procedures in the template game that do this.

There are a number of opcodes that require a "class context" to be used. Any the of property set/get opcodes, self, super, selfID. The interpreter has a notion of the "current object", and it uses that to process these opcodes (actually, super may not require that, not sure). If a class method calls into a procedure, the "current object" is still that class.

Then, separate from that, is what is needed for compiling source code. The "self" keyword (which corresponds to the "self" opcode) actually doesn't need any context. i.e. to generate the bytecode for "self", I don't need to know what the class context is. So self can appear in any procedure (maybe I should make this an error? I forget if any template game code leverages this or not).

I can't generate bytecode for any of the property opcodes, or "super", without knowing what class this is for. Thus, when used in a procedure, that procedure must be marked as "belonging" to a class (like the 3 examples in the template game) or else it's a compile error.

As for codeblocks (I'm assuming you mean the code sections in the SCI0 script files?), I doubt it matters where things are physically located in the script resource. I certainly never paid any attention to it when writing the SCI Companion compiler. So I think it has no relevance whatsoever to whether or not a procedure is used within an object context. SCI1.1 uses the separate script/heap resources with a significantly changed format, and the notion of "code blocks" doesn't really exist anymore.



« Last Edit: May 05, 2015, 03:26:22 PM by troflip »
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline lance.ewing

Re: SCI mysteries
« Reply #25 on: May 05, 2015, 03:25:45 PM »
In the SCI0 template game, there are three procedures that "belong" to a class:

(procedure (GetCel) of Extra
(procedure (IsSaveDialog) of SRDialog
(procedure (CueClient) of Timer

Yeah, I think Extra might have been one of the examples that I saw where the procedure was at the end of a code block, after methods.

Offline troflip

Re: SCI mysteries
« Reply #26 on: May 05, 2015, 03:28:24 PM »
Yeah, I think Extra might have been one of the examples that I saw where the procedure was at the end of a code block, after methods.

If you compile with SCI Companion, it looks like it's put at the beginning of a code block.
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline lance.ewing

Re: SCI mysteries
« Reply #27 on: May 06, 2015, 06:50:07 PM »
Has anyone found byte code for a procedure appearing in a code block that has methods either side of it?

I've found an example of the above. In script 995 in LSL5, there is a procedure in the middle of a code block, situated between two methods of the same class. The class is Inv.

For the version I'm looking at, the byte code entry addresses for the methods in the Inv class are as follows:

$60d init
$615 ownedBy
$620 showSelf
$6b3 show
$6e9 advance
$75e retreat
(there's a procedure at address $7c0)
$84a doit
$c98 hide
$d3c advanceCurIcon

These methods are all in the same code block.

There are also two procedures in this code block. One quite large one appears at the start of the code block at $01aa. The other procedure appears at $7c0, which slots between the retreat and doit methods. The procedure at $7c0 is called a couple of times by the doit method.

Offline troflip

Re: SCI mysteries
« Reply #28 on: May 06, 2015, 08:01:56 PM »
What's purpose of your investigation? Are you trying to determine what the original syntax might have been for these procedures?

Given the pattern you're seeing in the codeblocks, it's a reasonable assumption that these procedures were defined in a class in the original source code (as opposed to the "procedure blah of fooclass" that Brian used). Basically, they'd be like "private" methods, I guess.

Your version of LSL5 must be a little different than mine. In mine, the procedures are at $1ae and $7c4 (close, but off by a bit). Decompiling script 995 in LSL5, only the $1ae procedure was identified as being "of" the Inv class. $7c4 wasn't because the only class-specific opcode used was "self", which can compile without knowing which class it belongs to (I think I had to do that because there were some procedures in the SCI0 template game that were like that).
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline Collector

Re: SCI mysteries
« Reply #29 on: May 06, 2015, 10:18:17 PM »
All of this brings to mind that I found one of the original developers that still had the original source to Freddy Pharkas. I asked him if it would be possible to see a sample of the code just to get a feel for what the original SCI was like and told him that I understood if he could not, but he quit talking to me all together.
KQII Remake Pic


SMF 2.0.19 | SMF © 2021, Simple Machines
Simple Audio Video Embedder

Page created in 0.034 seconds with 22 queries.