Author Topic: Original AGI Interpreter  (Read 9661 times)

0 Members and 1 Guest are viewing this topic.

Offline lance.ewing

Re: Original AGI Interpreter
« Reply #30 on: June 20, 2024, 11:57:28 AM »
It is interesting nonetheless. If it really came from King's Quest it would have to be the GAL version, since by the time of AGI, Sierra was all about generic code. We have established that GAL is not simply an early kind of AGI. And yet, the file wasn't rewritten from scratch.

Yes, very interesting, in fact it isn't the only reference to a specific game. I'd like to explore that a bit more in a later post. I recall seeing a KQ II reference as well.

I noticed another macro-related thing. They use 'enter' as an assembly macro, but 'enter' is an opcode on 80186 and later processors. So it seems their assembler didn't complain about this.

I've tried MASM 4.0 with every one of the ASM files now, using my implementations of the missing macros. Most of the files are producing .OBJ files without error. Obviously not tested though, so there could very well be errors in my macro implementations. I won't really be able to test them properly until I've fully linked it together. I have successfully compiled all the C source using the MWC compiler (version 4 for that one as well). Its going to be some time before the missing bits are ready though, as I'll have to reconstruct each of those. I've done it already for a couple of files, one of which I haven't yet pushed to the repo.

MASM had no problems with the "enter" macro. It does have problems with a few things though. I think I have three separate issues at the moment, or maybe its four if I'm being picky.

1. The TYPE keyword as understood by MASM is clashing with a "type" symbol in one of the source files. I think there might be an option to support using keywords for symbols. Haven't tried it yet though.
2. The "return" macro is clashing with the RETURN constant that is defined in one of the source files.
3. Some of the "pcall" macro calls are using a & char in front of a string parameter, presumably to get the address of the string. MASM doesn't seem to like this. It outputs a warning and uses a value of 0, which doesn't sound good.
4. Some of the "pcall" macro calls are using a # char in front of either a number (e.g. #15) or a numeric constant (e.g. #TEXTRGHT"). This is presumably meant to indicate an immediate value but MASM doesn't like this either. It doesn't seem to recognise the # char being used in this way, in fact the macro calls would probably work without the #, so not sure why they are needed.

I've searched online a bit, and read through bits of a few MASM books online, but can't see anywhere where # or & are used in this way. It suggests that something else other than MASM was looking at these.

Any ideas?


Offline lance.ewing

Re: Original AGI Interpreter
« Reply #31 on: June 21, 2024, 02:16:06 AM »
1. The TYPE keyword as understood by MASM is clashing with a "type" symbol in one of the source files. I think there might be an option to support using keywords for symbols. Haven't tried it yet though.
2. The "return" macro is clashing with the RETURN constant that is defined in one of the source files.

Actually, rather than there being an option to support using keyword names as symbol names (I thought I saw one but can't spot it now in the MASM 4 command line options), there is instead an /ML option that allows symbols to retain their case. Using that option allows, for example, "type" to avoid clashing with TYPE.

I don't think the RETURN constant was clashing with the return macro btw. I misinterpreted the error. It's another example of the 4th issue. This is in the SCROUT.ASM file:

Code: [Select]
pcall PutChar,#RETURN

where RETURN is defined as follows:

Code: [Select]
RETURN               equ     13

Offline lance.ewing

Re: Original AGI Interpreter
« Reply #32 on: June 21, 2024, 09:48:56 AM »
So, yeah, I think it is mainly the "pcall" macro uses below that are causing issues:

Code: [Select]
DOTEST.ASM:     pcall   Error,#15,ax    ;bad test number
EQUIPCHK.ASM:   pcall   _SetTextAtr,#WHITE,#BLACK
EQUIPCHK.ASM:   pcall   open,&fontFile,#INPUT0
EQUIPCHK.ASM:   pcall   printf,&noFontMsg
EQUIPCHK.ASM:   pcall   read,ax,heapBase,#FONTFILESIZE
EQUIPCHK.ASM:   pcall   printf,&noMemMsg
INTRPT.ASM:     pcall   WindowNoWait,&badStackMsg
SCROUT.ASM:     pcall   PutChar,#RETURN ;out of window -- recurse on
SCROUT.ASM:     pcall   ClearRect,topline,#TEXTLEFT,bottomline,#TEXTRGHT,attribute

i.e. any usage that uses # or &.

The following are working fine:

Code: [Select]
DOTEST.ASM:     pcall   TraceTest,ax,savedTestPtr
DOTEST.ASM:     pcall   CompareStrings,ax,bx
EQUIPCHK.ASM:   pcall   close,ax
EQUIPCHK.ASM:   pcall   ErrBeep
SCROUT.ASM:     pcall   ClrLines, theLine, theLine, clrAtr

There must be a way to translate the # and & into a form that MASM understands. For example, if & could be translated into "OFFSET " then maybe that might work (?). Maybe there is a way to define/override what these chars do. The & char is a tricky one though, as that is by default used for substitution, which I'm making heavy use of in the macro definitions.

Offline lance.ewing

Re: Original AGI Interpreter
« Reply #33 on: June 21, 2024, 12:27:13 PM »
I think the logic for this is all inside the missing macro. The # and & is indicating to the macro what type of parameter it is, and then the macro must be somehow detecting that and behaving differently. If I compare some pcall usages with the disassembly of the same code, then these are some examples of what gets generated:

#15

becomes:

mov   [bp+var_2], 15
push   [bp+var_2]

and:

&noMemMsg

becomes:

push   ax
lea   ax, noMemMsg
mov   [bp+var_2], ax
pop   ax
push   [bp+var_2]

where the [bp+var_2] is a local variable (var_2 is negative).

And then there is the normal case where it pushes the macro parameter as is:

ax

becomes:

push   ax

Three different behaviours, based on whether the first char is #, & or neither.

Now I need to read up more on macros to see how this kind of determination logic and be implemented.

Offline mnicolella

Re: Original AGI Interpreter
« Reply #34 on: June 21, 2024, 12:59:04 PM »
In the MASM manual there is talk of a "TYPE" operator that can be applied to an expression to see what it is. It says it returns "a number" but I don't see what the possible numbers are. I would make a macro that takes a parameter and print out the TYPE of the parameter, and then I bet you could use that with some IF directives to select the code to emit based on the type of thing (register / word / pointer?) passed to the macro

Offline mnicolella

Re: Original AGI Interpreter
« Reply #35 on: June 21, 2024, 01:54:06 PM »
I did this test in the latest masm:


.data
stuff db 54
extrn   other_foo:near

.code
foo proc
   push TYPE stuff
   push TYPE other_foo
   push TYPE rax
foo endp

end


Results in:


  0000000000000000: 6A 01              push        1
  0000000000000002: 68 08 FF 00 00     push        0FF08h
  0000000000000007: 6A 08              push        8

Offline mnicolella

Re: Original AGI Interpreter
« Reply #36 on: June 21, 2024, 01:56:33 PM »
(it also gives me a syntax error if I try to write &other_foo so I'm not entirely sure what that's about)

Offline lance.ewing

Re: Original AGI Interpreter
« Reply #37 on: June 21, 2024, 06:23:03 PM »
Version 5.1 of MASM has some new features apparently not in MASM 5.0 or 4 that look like they could be useful, but MASM 5.1 wasn't released until 1988, whereas the code is dated the 7th October 1987. I'm trying to use 4 since this is likely what they used at the time.

Offline Collector

Re: Original AGI Interpreter
« Reply #38 on: June 22, 2024, 09:17:29 AM »
Have you seen anything that indicates what version interpreter the source is from?
KQII Remake Pic

Offline lance.ewing

Re: Original AGI Interpreter
« Reply #39 on: June 22, 2024, 12:34:53 PM »
Have you seen anything that indicates what version interpreter the source is from?

AGKorson answered that question earlier in this thread:

The files appear to match the memory map in size and position, and also match version 2.903 except for a few places where there is code matching 2.440.

The source code appears to date to a few weeks before the first game using 2.903 was released. The memory map file is dated the 7th October 1987. Version 2.903 was used for an early Police Quest release. I don't have that disk image, so I can't check myself what the timestamp is for the AGI and AGIDATA.OVL files on that disk. I found a date of 23rd October 1987 mentioned online though.

AGKorson has done a detailed analysis of the sizes of the various parts of the AGI.MAP memory map file and deduced that it predates 2.903, but is mostly a match for 2.903, with, as he mentioned in the quote above, a few bits still matching what was in 2.440.

Offline Collector

Re: Original AGI Interpreter
« Reply #40 on: June 22, 2024, 05:16:32 PM »
Yeah, the only PQ1 I have is v2, the same used for the 4 Most Wanted.
KQII Remake Pic

Offline lance.ewing

Re: Original AGI Interpreter
« Reply #41 on: June 22, 2024, 06:42:44 PM »
In the MASM manual there is talk of a "TYPE" operator that can be applied to an expression to see what it is. It says it returns "a number" but I don't see what the possible numbers are. I would make a macro that takes a parameter and print out the TYPE of the parameter, and then I bet you could use that with some IF directives to select the code to emit based on the type of thing (register / word / pointer?) passed to the macro

I couldn't see how this would work with the values starting with # and &. I think TYPE must be for determining the type of data. The documentation talks about the size being returned for simple types like byte, word, etc. The problem with these values that are prefixed with & and # is that they aren't valid symbols. They don't actually refer to anything as such. Without the & and #, then do refer to something. I think that when these values, e.g. &noMemMsg or #TEXTLEFT, are passed into the macro, they must look like string values at that point, rather than a symbol that references data, since # and & do not have the meaning within MASM that these pcall usages appear to convey. If the macro uses them as-is with an asm instruction, then it wouldn't be valid. When I try to do that, I get the message "error 101: Missing data; zero assumed". It treats it as a warning, which is quite strange actually, as it clearly isn't correct for it to assume a zero value.

I'm stumped to be honest. I've skimmed through the MASM 4 manuals a few times and can't see anything that would be able to do what needs to be done here. It needs two different mechanisms: One is to recognise the &, #, or neither of those based on the first character, and the other mechanism is to get the substring from the second character to the end, which would give the actual symbol name in the case of & or # being present. Later versions of MASM do support INSTR and SUBSTR, which would be useful, because they could presumably be used to detect the # and & characters, and then to get the substring after that character. I looked at the strings in versions 5.0 and 5.1 of the MASM.EXE. Version 5.0 has no mention of INSTR and SUBSTR but version 5.1 does. I feel like it would be cheating though to write something that targets MASM 5.1, since that version wasn't yet available (the two 5.1 versions are dated 31st Jan 1988 and 1st Feb 1988). I may end up having to target version 5.1 though, as I can't see how it can be done in MASM 4.

I did wonder whether maybe they used more than one assembler. As was mentioned earlier in this thread, one of the files, SCROUT.ASM, mentions MASM by name in one of the comments. SCROUT.ASM also happens to be one of the files that uses these strange pcall macro calls, so it is difficult to suggest that a different assembler was used for that file when MASM is mentioned within the file. Of course, it could be the case that the comment is old and that they were using a different assembler at this time and hadn't bothered to remove that comment. It is worth considering. I'm not sure what other assemblers would have been around that might have handled this type of syntax. Or is it possible that some kind of preprocessor was used on the .ASM file before MASM was used?

One thing I'm trying not to think too much about is that the SQ2 disk itself was prepared in mid-March 1988, i.e. that is when the AGI interpreter and game files for SQ2 were copied onto the master disk. So it is theoretically possible that the AGI interpreter source is more recent than the October 1987 date. The problem with this though is that AGKorson's analysis of AGI versions, i.e. the evolution of the different sizes of the various internal data and code parts within the interpreter, places the source code around that 2.903 version, which can't be any later than early Nov 1987, since the 2.911/2.912/2.915 are from Nov 1987, and 2.917 is early Dec 1987. The point to make though is that MASM 5.1 was available prior to March 1988 when the SQ2 disk was prepared, thus the reason why it being theoretically possible that the AGI interpreter source is more recent is of relevance, as it would then bring MASM 5.1 into the picture. I feel like that is stretching the evidence a bit though.

Offline lance.ewing

Re: Original AGI Interpreter
« Reply #42 on: June 22, 2024, 07:54:09 PM »
I may have finally found something available in MASM 4 that should do the trick. It's the IRPC directive. It loops over the characters in a string. So it should be possible to use that to check the first char and split off the rest. There is an example of doing something similar to that in the MIXED.INC macro file provided with MASM 5.0.

Code: [Select]
; Split argment into argNameCur and typeNameCur

fetType macro arg
    cbType=0
    fColon=0
    argNameCur equ < >
    typeNameCur equ < >
    .xcref fColon, argNameCur

    irpc aChar,arg
        if fColon
            conCat typeNameCur, %typeNameCur, aChar
        else
            ifidni <aChar>,<:>
                fColon=1
            else
                conCat argNameCur,%argNameCur,aChar
            endif
        endif
    endm
    adjustType %typeNameCur
endm

This example is splitting strings like the following:

rectype:byte

It looks for the colon in the middle to switch between concatenating to the arg name vs the arg type name.

The cool thing is that the macro code it is using should also work in MASM 4. I'll give this approach a go tomorrow.

Offline AGKorson

Re: Original AGI Interpreter
« Reply #43 on: June 22, 2024, 11:19:47 PM »
I managed to download a copy of the Mark Williams compiler owner's manual (it was called "Let's C").
According to the manual, (Version 4, published in 1987 [I don't know the exact date though]) it included an assembler (called 'as'). According to the documentation, you could compile C source files and assembly files at the same time as part of a single project. Maybe that's the assembler they used, instead of MASM.

I haven't read the documentation on as to see if it handles the prefix problem you are seeing. It does say that it support macros.
« Last Edit: June 23, 2024, 12:42:18 AM by AGKorson »

Offline AGKorson

Re: Original AGI Interpreter
« Reply #44 on: June 22, 2024, 11:41:11 PM »
After more reading, it looks like 'Let's C' will use their internal assembler if the source file ends in '.s' and it will use MASM if the source file ends in '.asm'. Since all the assembly source files end in '.asm', it looks like Sierra wasn't using the MWC built in assembler. So I guess that theory is debunked.


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

Page created in 0.076 seconds with 22 queries.