A possible fix for Wishbringer r70

In 1988 someone at Infocom tried to rebuild Wishbringer and the result was the file nj2.zip in development/old/wishbringer.
Zarf renamed it to wishbringer-rX165-s880609.z3, writing “The release number is 32933 (165 with the high bit set). This fails with memory errors in modern interpreters. It may be a compilation failure or an intermediate compilation stage.”
Actually the release number was 70, as can be seen in j2.errors:

Assembling J2.XZAP.1 on Thursday, June 9, 1988 16:10:47
Release(last was 70): 70

From the same file one can see what is wrong:

     0  Inserting J2FREQ.ZAP.4     (554 bytes)
   618  Inserting J2DAT.ZAP.1    (21937 bytes)
 22555  Inserting MISC.ZAP.3      (1626 bytes)

The zip file is missing the 64 bytes header and starts directly with the abbreviations for the frequently used strings.
Moreover it is missing J2PUR.ZAP, which has the “pure” part of the data.

We also have a chart file, whose last 3 entries are:

-date-  -rel-   -size-  -pre-   -obj-   -glo-   -voc-
 5/23     70    139040  22043   253     231     1045
 5/24     70    139040  22043   253     231     1045
 6/09     70    127980  22555   253     231     1045

As you can see, the first two attempts in May produced a zip file bigger than the 128 kB limit for a z3 file. Maybe that’s why on the 3rd attempt the developer decided to remove J2PUR.ZAP and see how much space could be saved.
Then we know that one month later Wishbringer was released as a Solid Gold (z5) game.

Can the broken nj2.zip be fixed ?
Adding a header in front of the data in nj2.zip is trivial.
Optionally one can also insert the missing pure data (e.g. from r69).
Then it is just a matter of fixing a few thousand pointers in the file :wink:

Then one can run the fixed file:

$ frotz wishbringer-r70-s880609.z3 
 ...
 WISHBRINGER
 The Magick Stone of Dreams
 Copyright (C)1985 Infocom, Inc. All rights reserved.
 Wishbringer is a registered trademark of Infocom, Inc.
 Release 70 / Serial Number 880609

Is the game playable to the end ?
Probably not.
We know from j2.errors that there are two undefined symbols:

QUEUED? global undefined:  121906
GVAL global undefined:  120247

A few more if J2PUR.ZAP is not included.
The two undefined symbols are in the code corresponding to MAGICK.ZAP

Depending on how the interpreter is handling calls to the address 0, that may crash the game or just be ignored.

Moreover I noticed that there are 3 places, again in MAGICK.ZAP, where the code is using

PRINTD GAME

which is obviously a mistake, since GAME is a string and not an object.
The rest of the code is correctly using

PRINT GAME.

Anyway my goal was just to obtain a playable version of that broken zip file, without attempting to fix the actual code.

3 Likes

Calls to address 0 are legal according to the standard, and should just return true.

1 Like

They return zero, don’t they?

1 Like

Calling address 0 stores 0. But note that the operands still need to be processed (namely popping from the stack), and not all calls do store.

1 Like

I stand corrected.

Calling address 0 works as if there’s a routine at address 0, which does nothing but return false. Arguments must be processed, and the return value may or may not be stored, depending on the opcode.

(Late, catching up…)

This is neat! Thanks. I’ll update my collection page.

Just to be clear: you did this by

  • compiling the ZIL source in wishbringer-r69
  • removing J2PUR.ZAP from the assembly list
  • running the assembly stage
  • deleting the first 64 bytes.

Is that correct?

1 Like

Unfortunately I don’t have a ZIL compiler setup, but only a ZAP one.
What I did was:

  1. create a set of ZAP files for r69 that when compiled result in a zip file identical to the original one
  2. use that as a starting point for r70, but removing the header and j2pur.zap
  3. compile with zap and compare the result with nj2.zip
  4. modify the zap files, and back to step 2)
  5. rinse and repeat till the two files are identical
    Then I put back the header and j2pur.zap, compiled and the result was the fixed zip file.

When I say identical, there are actually a few remaining differences in the header:

bash-3.2$ ./compare j2.zip nj2.zip
Comparing j2.zip with nj2.zip from 0 to 1f3eb
00000: 65 03 <-- my zap is not putting a 03 there unless it is specified in the header
00012: 32 38 <-- serial number, i.e. compilation date
00013: 36 38
00015: 33 36
00016: 33 30
00017: 30 39
0001c: d6 d7 <-- checksum
0001d: 92 38

Got it. Thanks for the details.

Unfortunately the parser seems very broken:

>get envelope
(This story can't understand the word "envelope" when you use it that way.)

What next?

but “all” is working

>get all
(mysterious envelope)
Taken.

(Your score just went up by 5 points! Your total score is 6 out of 100.)

Mr. Crisp drums his fingers on the service counter impatiently. "Don't just
stand there! The Magick Shoppe closes at five o'clock!"

What next?

:frowning: