Skip to content

Fixes to build and play on OpenVMS x86#9

Open
jhamby wants to merge 7 commits intotesneddon:masterfrom
jhamby:master
Open

Fixes to build and play on OpenVMS x86#9
jhamby wants to merge 7 commits intotesneddon:masterfrom
jhamby:master

Conversation

@jhamby
Copy link

@jhamby jhamby commented Nov 5, 2023

I ran into a few tricky issues getting this code to compile and run correctly on x86. I've resolved them in this PR.

  1. Lacking a BLISS compiler, I rewrote the wrapper code that converts the $message and $message_indent calls to pass the arguments as a list to the Pascal implementations. On non-VAX, the compiler has to make a fake argument block to pass to the callee since the first 6 arguments are passed in registers. I figured out what the original MACRO-32 code must've looked like and wrote my own version to use in place of the BLISS version, which was itself rewritten from MACRO-32. It looks like the game code uses up to 9 params for $message calls and up to 7 params for $message_indent calls, but I set MAX_ARGS to 10 for both wrappers to be on the safe side.

  2. Hacked zk/zklink_time.pas to never print a negative number for version, which caused a build failure for me. I haven't looked yet to see why it calculated -48 for the version.

  3. The bug that caused me the most grief was messages like the sign in the first room not printing. I saw "The sign reads:" and then nothing. My first commit was to remove pairs of "0, 0" params in the $message lines that had those, which caused the sign to start printing, but I realized those "0, 0" pairs were supposed to print a blank line. It turns out the VSI Pascal compiler is generated bad code when you use the optional parameters feature ("truncate"). The shortest fix was to modify the one call to put_scroll_dx with no parameters (the one to print a blank line that was failing) to pass all three parameters, with an empty descriptor.

With these changes, now I can play ZK.

Add a MACRO-32 version of the variable-argument-list wrapper that was
originally written in MACRO-32 and then converted to BLISS, presumably
for portability. Unfortunately, the x86 version of the BLISS compiler
isn't ready yet, and it's just as efficient to have MACRO-32 generate
the argument list from the register params, especially since there can
be so many of them (up to 9 for ifc$message or 7 for ifc$message_indent).

Besides this change, there was a bug in reading objects, like the sign
in the first room, or the ASCII table in the second room, because the
call to ifc$message() had some extra "0, 0" parameters for some reason.
This caused it to print "The sign reads:" but then nothing after that.

With these diffs, the game should now build and play on OpenVMS V9.2-1.
My workaround to get messages printing by removing pairs of 0, 0 params
wasn't correct. The code is supposed to print a blank line when it sees those.
The reason it's failing on x86 is due to a VSI Pascal compiler bug with
default parameters causing bad behavior at the default optimization level.

I'm going to try to work around the bug by modifying function put_scroll_dx
to not use "[truncate]".
The VSI Pascal compiler on x86 is generating bad code when default params
are used. This was causing some game messages not to print because of
embedded blank lines (a pair of 0 params in the ifc$message call) causing
put_scroll_dx to be called with no arguments, which was stopping the
rest of the message from being printed.

I reproduced the bad behavior with a standalone Pascal test program that
checks the presence of its parameters and prints them if present. It
behaves correctly when compiled with "/NoOpt" but crashes with the
default optimization level. I've reported this issue on the VSI Forum.

As a workaround, commented out the "[truncate]" modifier on all three
parameters, and passed default params in the one location where it was
being called with no arguments (the case that was failing). This fixes
the game text.
For the arg pointer wrappers now in ifc/ifcrtl_macro.mar, we need to
copy up to 9 args for ifc$message (read_start_record in zk/zkinit.pas),
and up to 7 args for ifc$message_indent (zk$print_ast in zk/zkast.pas).

Save a few clock cycles and memory copies by reducing MAX_ARG from 10.
Initialize the card_ptr field in the context record so that the game
can save its state without getting an ACCVIO in write_context_record.
The no-longer-documented MTH$RANDOM returns its result in VAX FP format.
The game gives array index exceptions because it's expecting IEEE values
(on non-VAX).

Changed to use Pascal's RANDOM function, which returns the same range.
Use Pascal RANDOM and not MTH$RANDOM.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant