29

I am looking at the files included with the 1981 game Wizardry. The particular version I have is from a 1998 re-release, but I do not know if the binary is still the original 1981 release.

My questions are at the bottom. Here is all the information I have gathered.

The binary runs in DOSBox. There are 3 files.

  • WIZ1.COM
  • WIZ1.DSK
  • SAVE1.DSK

Linux file identifies the .COM as 'data', and the .DSK files as 'DOS executable (COM)'.

The first 64 bytes of the .COM are as follows:

00000000: fa8c c88e c08e d88e d0bc 0e08 fbb4 0fcd  ................
00000010: 10a2 dc01 8cc8 8ec0 bbff ffb4 4acd 2181  ............J.!.
00000020: fb00 4173 0cba c403 b409 cd21 b808 4ccd  ..As.......!..L.
00000030: 218c c8ba 1f08 d1ea d1ea d1ea d1ea 01d0  !...............
00000040: a3d2 01ba 6304 b800 3dcd 2173 0cba f103  ....c...=.!s....

The only meaningful ACII strings in the data are:

!Wizardry requires 300K free memory to run.
$The file WIZ1.DSK is missing or damaged.
$The file SAVE1.DSK cannot be created.
$Read error in the Boot Block
$WIZ1.DSK
SAVE1.DSK
Thanks for playing Wizardry!

The .COM file is 1.8K, while the two .DSK files are both 640K. Being that the 'bootstrap' (see below) is well over the 64K limitations of COM executables, I am already perplexed.

Wikipedia says the game was developed using USCD Pascal and implies that it runs p-code and that there was a interpreter for IBM DOS.

USCD Pascal was also used for the IBM versions, but with an x86 version of the interpreter.

The first 64 bytes of WIZ1.DSK would imply that this version was created no earlier than 1987 or that it was recompiled in after 1987.

00000000: eb38 9080 0800 0000 0053 7973 7465 6d20  .8.......System
00000010: 626f 6f74 7374 7261 7020 7632 2e30 2044  bootstrap v2.0 D
00000020: 5344 440d 0a28 4329 2031 3938 3720 5257  SDD..(C) 1987 RW
00000030: 492c 2049 6e63 2e0d 0a00 bb00 7c8c c88e  I, Inc......|...
00000040: d08b e38e c031 c08e d8eb 1f00 3ec5 373e  .....1......>.7>

The following strings from the WIZ1.DSK file seem significant:

No file SYSTEM.INTERP
SYSTEM.PASCAL

There are some strings from the game itself:

$PROVING GROUNDS OF THE MAD OVERLORD!
NO RACE
HUMAN
DWARF
GNOME
HOBBIT
FIGHTER
MAGE.LIBR
PRIEST
THIEF
BISHOP
SAMURAI
LORD
NINJA
AFRAID
ASLEEPIBR
P-LYZE
STONED
DEAD
ASHES
LOST
UNALIGN
GOOD
NEUTRALb
EVIL

There is what looks like PASCAL or BASIC code in the binary:

 PROCEDURE PlotStr;
 VAR S:Str255;
 BEGIN
YTNOM
F=RJ
NAYR
CRAZY YRRAB
ELMER
id:=0; noGold.Hi:=0;
#totGold:=noGold;
#FOR i:=0 TO numInParty-1 DO
&BEGIN
)BigAdd(totGold,Party[i].Gold);
)Party[i].Gold:=noGold
&END;
#Party[N].Gold:=totGold
 END;

There is a around 100 or so occourances of this HLL code strings being found. The SAVE.DSK looks like its a copy of WIZ1.DSK that is modifiable.

None of the strings from the game play are in the files. When the program was compiled, the strings must have been convereted to the routines necessary to draw the characters to the screen?

This is all I know. My goal is to path the game such that the level up function favors positive changes in stats.

  1. How can I positively identify what ABI this program is compiled to?
  2. If it was written in PASCAL, then is there a PASCAL specific debugger/disassembler/decompiler that can make things easier?
  3. Does anyone have any information or tips to help me with this process.

I do know x86 asm for real mode and segmented mode but I have never used that knowledge for reversing a real 16-bit application.

13
  • 5
    It makes sense to ask the question in RE.SE
    – Leo B.
    Commented Feb 10 at 1:58
  • 7
    You're aware that the game is to be re-released? It was a pure PASCAL game on the Apple II and I wouldn't be surprised if those DSK files are images of PASCAL disks. After all, UCSD was a stand alone system. While the file system might be the same, the PC compiler is most likely a later revision, so the p-code may be incompatible to what Apple II tools expect. Opening the COM file with DEBUG might be a good start to see where the interpreter code is loaded from. The code shown is PASCAL.
    – Raffzahn
    Commented Feb 10 at 2:36
  • 7
    Since these are disk images, the code may just be source remains within deleted files. Also, the original game used save disks. (BTW: Back on the Apple and when the game was new, we wrote an editor to change save disks for whatever we needed :)) Was a lot of fun to hack the game. Sorry, no notes nor disks still present).
    – Raffzahn
    Commented Feb 10 at 2:39
  • 1
    @Leo.B I understand, but I disagree. I have serious doubts that RE community cares about software developed in the late 70s.
    – typedeaf
    Commented Feb 10 at 3:54
  • 1
    @typedeaf Radare2 can decompile Java bytecode. Perhaps someone in RE.RC could give you pointers how to proceed developing a Pascal p-code decompiler plugin for it.
    – Leo B.
    Commented Feb 10 at 4:16

7 Answers 7

20

A few hints about how the UCSD system works.

What's often called UCSD-Pascal is in fact a stand alone OS with Pascal as one possible language. Others were BASIC, FORTRAN, Ada or Assembler. The whole idea was rooted in the UCSD having a wide variety of computer systems but no interest in creating lots of different versions of their courses depending on what machines were used in a building or room. So a machine independent OS and development environment (IDE) was designed based on a p-code interpreter.

The system consisted of a machine specific interpreter and (very low) level driver set, and an operating system completely written in p-code (usually using a HLL, but there was also an Assembler). The interpreter was quite compact, just a few KiB, providing a 16-bit stack orientated pseudo CPU. While itself slim, it provided very powerful run-time constructs, resulting in comparable high speed. One may compare it to Forth, just with a more high level compiler.

To port it to a new machine only that interpreter and the low level device routines needed to be rewritten. The low-level routines were really low. Essentially, just addressing of devices as block or character and block devices as contigious numbered, 512 byte blocks. Everything above was already done in p-code.

That way they ported it to everything they had, from DEC to 8080 and HP all the way to IBM /370. And finally as well to the Apple. That way students got the same learning environment, no matter what computer was used.

Pascal as the main language was simply due to the fact that Pascal was seen at the time (mid 70s to mid 80s) as the language of the future - C only became a thing in the second half of the 80s.

The system made no assumptions about how it got booted, on bare-metal, or on top of another OS, as long as those basic access functions were provided. A clean cut that made it easy to run UCSD OS as a guest under any other OS, especially nice with mainframes.

For bare-metal boot each block device reserved the first two blocks (1 KiB) for a machine specific boot loader. Enough to locate and load the interpreter (SYSTEM.INTERP) and the OS (SYSTEM.PASCAL). This was further supported by a simple disk layout. The directory started fixed at block 2 and files were never fractured. All the boot code needed to do was read block two and start scanning for an entry with SYSTEM.INTERP, taking start block and block count from that entry, read those continuous blocks into memory and start the interpreter.

The interpreter in turn initialized its run-time environment and started looking for an OS to start - that is the first file with a name starting with SYSTEM.xxxx. It's content got loaded and started as the first application, as it was already p-code.(*1)

Conclusions for the Project:

  1. The .DSK files may or may not have some x86 code in the first 1024 bytes
  2. At offset 400h a directory structure should start
  3. Usually the directory is 3 KiB
  4. First is a volume entry.
  5. Followed by 77 file entries
  6. Usually the very first is SYSTEM.PASCAL
  7. SYSTEM.INTERP will always come after SYSTEM.PASCAL
  8. Other files may be inbetween.
  9. All files are always continuous, that is, there is no fragmentation.
  10. It should be simple to pick the pointers (block number) to each file.
  11. Pointer times 200h gives the offset within the .DSK file.
  12. Only SYSTEM.INTERP may contain native (x86?) code
  13. All other code is usually p-code.
  14. I was possible to insert machine code as well, but I would not expect any.

And so on ...

Regarding the Files

The fact that file cant identify WIZ1.COM doesn't tell anything. COM files can contain any value, as they are pure code. There is no header or magic number to identify them. file tries to identify COM files by looking at the first byte being 0EBh (after excluding other options), which is a Short Jump, as COM program often starts by jumping around some copyright message.

And that's exactly what happens in the .DSK files. Here an 0EBh 38h is a short jump around the text you already found. At offset 3Ah the code continues with load of BX and move to segment register - quite the usual initialisation.

I wouldn't be surprised if those .DSK are executables and simply starting up the system. Remember the 1 KiB Boot area at the beginning of each UCSD volume?

How To Start?

I'd say disassemble WIZ1.COM first. If no other disassembler available, use DEBUG's U command. I just peeked into a bit, and it looks like a very simple, straight forward loader for WIZ1.DSK. It's not much code, so pen and paper should do the trick.

WIZ1.DSK is also a regular program, but at a different level. Still it should be no big deal to get at least until the interpreter is started. After that you may want to consult the UCSD OS manuals, as the data structures used are quite nifty.

In any case, enjoy your fun project :)


*1 - ProDOS btw inherited part of that logic, except that the kernel does not look for a first SYSTEM.* file but *.SYSTEM to be loaded. Usually BASIC.SYSTEM :)

5
  • This would be more like a userland OS, right? I hate to admit that I know terriible little about the DOS OS, but I am assuming that it still ran the kernel in a different ring level than the user applications and used the interrupts for entering kernel routines? Maybe I need to start by reading about how DOS OS works. Surely when this program exits, it would return to DOS. DOS didnt require protected mode, did it? Would an process in DOS have full access and control to all segment registers and physical memory? So many questions are popping to mind. Off to finding DEBUG!
    – typedeaf
    Commented Feb 10 at 5:30
  • 7
    @typedeaf DOS doesn’t provide any protection (the 8086 didn’t have protected mode anyway). DOS itself probably doesn’t matter for what you’re trying to do, it’s about finding what p-code to patch. Commented Feb 10 at 6:29
  • @typedeaf I seem to remember that UCSD was (infrequently) sold as a standalone alternative to DOS, but I've definitely come across this sort of thing in the past: an interpreter binary to run under DOS plus one or more filesystems each in a DOS file. I remember doing a bit of a hack on the binary to change the way some vectors worked in order to make it compatible with some other TSR. Commented Feb 11 at 8:59
  • LOL file that's a pretty dumb way to identify COM files. In my experience that's more likely to be a disk image than a COM file.
    – Joshua
    Commented Feb 12 at 22:08
  • @Joshua, file won't declare something a COM file until it's excluded every other option. FAT* disk images, for example, have a boot sector signature at 0x1FE and other distinguishing features that a COM file doesn't have.
    – Mark
    Commented Feb 13 at 21:54
18

The background has already been explained, some additional details.

I don't know where to get the version you have, but quick googling found a version with a 320K WIZ1.DSK. This one clearly is a UCSD-formatted disk, with a bootstrap at the beginning:

00000000: eb 38 90 80 08 00 00 00 00 53 79 73 74 65 6d 20  .8.......System 
00000010: 62 6f 6f 74 73 74 72 61 70 20 76 32 2e 30 20 44  bootstrap v2.0 D
00000020: 53 44 44 0d 0a 28 43 29 20 31 39 38 37 20 52 57  SDD..(C) 1987 RW
00000030: 49 2c 20 49 6e 63 2e 0d 0a 00 bb 00 7c 8c c8 8e  I, Inc......|...
...
00000230: 3c 00 75 01 c3 b4 0e 32 ff cd 10 eb ef 57 69 7a  <.u....2.....Wiz
00000240: 61 72 64 72 79 20 66 6f 72 20 74 68 65 20 49 42  ardry for the IB
00000250: 4d 2d 50 43 0d 0a 00 44 69 73 6b 20 52 65 61 64  M-PC...Disk Read
00000260: 20 45 72 72 6f 72 00 4e 6f 20 66 69 6c 65 20 53   Error.No file S
00000270: 59 53 54 45 4d 2e 49 4e 54 45 52 50 00 0d 00 00  YSTEM.INTERP....

This here is the directory of the disk:

00000400: 00 00 06 00 00 00 07 57 49 5a 42 4f 4f 54 f8 04  .......WIZBOOT..
00000410: 0d 00 00 00 07 af 00 00 00 00 06 00 b4 00 02 00  ................
00000420: 0d 53 59 53 54 45 4d 2e 50 41 53 43 41 4c 76 67  .SYSTEM.PASCALvg
00000430: 00 02 59 ae b4 00 ea 00 05 00 09 41 53 43 49 49  ..Y........ASCII
00000440: 2e 4b 52 4e a0 3c 00 00 76 67 00 02 36 ae ea 00  .KRN.<..vg..6...
00000450: 34 01 05 00 0d 53 43 45 4e 41 52 49 4f 2e 44 41  4....SCENARIO.DA
00000460: 54 41 76 67 00 02 87 30 34 01 54 01 05 00 0c 32  TAvg...04.T....2
00000470: 30 30 2e 4d 4f 4e 53 54 45 52 53 00 76 67 00 02  00.MONSTERS.vg..
00000480: f7 ae 54 01 55 01 05 00 09 48 41 53 2e 43 41 43  ..T.U....HAS.CAC
00000490: 48 45 a0 3c 00 00 76 67 00 02 c8 af 55 01 56 01  HE.<..vg....U.V.
000004a0: 05 00 0a 48 41 53 2e 53 54 52 4f 50 53 3c 00 00  ...HAS.STROPS<..
000004b0: 76 67 00 02 c8 af 56 01 58 01 05 00 0b 4b 41 4e  vg....V.X....KAN
000004c0: 41 2e 4b 45 59 4d 41 50 00 00 76 67 00 02 d8 ab  A.KEYMAP..vg....
000004d0: 58 01 62 01 05 00 09 34 30 30 2e 54 49 54 4c 45  X.b....400.TITLE
000004e0: a0 3c 00 00 76 67 00 02 8a ab 62 01 6c 01 05 00  .<..vg....b.l...
000004f0: 09 32 30 30 2e 54 49 54 4c 45 a0 3c 00 00 76 67  .200.TITLE.<..vg
00000500: 00 02 78 ac 6c 01 7c 01 05 00 0b 34 30 30 2e 43  ..x.l.|....400.C
00000510: 48 41 52 53 45 54 00 00 76 67 00 02 78 ac 7c 01  HARSET..vg..x.|.
00000520: 8c 01 05 00 0b 32 30 30 2e 43 48 41 52 53 45 54  .....200.CHARSET
00000530: 00 00 76 67 00 02 78 ac 8c 01 ac 01 05 00 0d 53  ..vg..x........S
00000540: 59 53 54 45 4d 2e 49 4e 54 45 52 50 76 67 00 02  YSTEM.INTERPvg..
00000550: a9 ae ac 01 f8 04 05 00 03 5a 4f 54 e8 ff 00 00  .........ZOT....
00000560: 00 00 a0 3c 00 00 a8 67 00 02 07 af 00 00 00 00  ...<...g........
00000570: 00 00 00 00 a0 3a 00 00 01 00 01 00 00 00 00 00  .....:..........
00000580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000590: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000005a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000005b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000005c0: 00 00 00 00 00 00 03 57 49 5a 4c 4c 00 00 03 57  .......WIZLL...W
000005d0: 49 5a 4c 4c 4f 54 02 23 39 41 4c 4c 4f 54 00 00  IZLLOT.#9ALLOT..
000005e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 23  ...............#
000005f0: 39 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  9...............

SYSTEM.PASCAL and SYSTEM.INTERP are usually system files of the UCSD p-Code system, though SYSTEM.PASCAL may have been re-used for the game. The rest are game files.

To reverse the game, you'd need to extract the files from the image, and disassemble the p-Code. There's plenty of documentation on UCSD p-Code (google), e.g.

Here is a project to read UCSD p-System disks, including a PDF that explains the directory format on pages 33-35:

Here is a collection of cross-compiler tools (with source code) that include a disassembler:

I know you want to do this project yourself for fun, but if you get stuck, Thomas William Ewers already disassembled and reveresed the Apple II version, and the resulting listing is available here:

2
  • The directory is a little off, e.g. the last file ("ZOT") goes from block 0x01ac to 0x04f8, which is past the end of the disk (320KB = 0x0280 blocks). The other files seem coherent though. Could be a copy-protection remnant? FWIW, based on the segment names, I think SYSTEM.PASCAL might be the actual game code.
    – fadden
    Commented Feb 10 at 16:19
  • @fadden It must be, there seems not to be other executable there, only data files. Commented Feb 12 at 19:04
15

What an intriguing piece of archaeology you've stumbled upon!

COM programs, present an interesting quirk. Despite its code segment being confined to a mere 64KB, they allocated all available free RAM within the 640K address space, and it was up to the program/programmer to free it.

Users were tasked with the delicate balance of freeing up memory and retaining only what was necessary for operation. Thus, it's not surprising to find it loading data or machine code overlays that surpass the 64KB limit.

Regarding the DSK files, it's conceivable they harbor disk images housing a runtime of the p-code system, an alternative operating system to MS-DOS, somehow bootstrapped on top of DOS and executed.

However, the downside emerges when we delve into the programming details. It appears that the game is compiled in p-code rather than x86 assembly, which complicates reverse engineering efforts due to the platform's relative obscurity.

Upon downloading the game, it's appears that the DSK file indeed contains a disk(ette) image. Notably, the presence of SYSTEM.INTERP and SYSTEM.PASCAL files aligns with references found in the p-code system introduction manual, specifically on page 1-8 found at http://pascal.hansotten.com/uploads/ucsd/ti/2232396-0001_UCSD_p-System_Introduction_Apr1983.pdf

The fragments of Pascal source seem to have been lost, residing in deleted sectors, and are by no means complete or executable.

I am also finding a thread about it being a Pascal program written in a Apple II. https://comp.sys.apple2.narkive.com/gV6EEodQ/wizardry-re-engineering

The DSK contents and game main routines are not definitively x86 native, they are compiled into p-code opcodes. https://en.wikipedia.org/wiki/P-code_machine

I also disassembled WIZDOS.COM using old venerable sourcer and it loads the WIZ1.DSK in RAM and it setups the environment and jumps to its boot sector as if it were booting it from physical media. https://pastebin.com/3CGYxdCY

In the meanwhile, I found tools for dealing with p-code disks, and managed to compile them for Debian 12 after some source code changes.

The tools are at https://ucsd-p-system-virtual-machine.soft112.com/

The disk seem to be some extended version of the file system, add to use the -e "extended directory listing" option, otherwise was getting an error.

For listing the files:

$ ucsdpsys_svolio -l -e WIZ1.DSK
wizboot:
system.pascal    174  5-Sep-87     6   512 Codefile
ascii.krn         54  3-Jun-87   180   512 Datafile
scenario.data     74  8-Jul-24   234   512 Datafile
200.monsters      32 15-Jul-87   308   512 Datafile
has.cache          1 28-Aug-87   340   512 Datafile
has.strops         1 28-Aug-87   341   512 Datafile
kana.keymap        2 29-Aug-85   342   512 Datafile
400.title         10 24-Oct-85   344   512 Datafile
200.title         10  7-Aug-86   354   512 Datafile
400.charset       16  7-Aug-86   364   512 Datafile
200.charset       16  7-Aug-86   380   512 Datafile
system.interp     32 10-Sep-87   396   512 Datafile
zot              844 16-Jul-87   428   512 Datafile
13 files, 1272 blocks used, 0 unused, 0 in largest

For extrating them to the Linux filesystem:

$ ucsdpsys_svolio --extract-all -e WIZ1.DSK
wizboot:
system.pascal    174  5-Sep-87     6   512 Codefile
ascii.krn         54  3-Jun-87   180   512 Datafile
scenario.data     74  8-Jul-24   234   512 Datafile
200.monsters      32 15-Jul-87   308   512 Datafile
has.cache          1 28-Aug-87   340   512 Datafile
has.strops         1 28-Aug-87   341   512 Datafile
kana.keymap        2 29-Aug-85   342   512 Datafile
400.title         10 24-Oct-85   344   512 Datafile
200.title         10  7-Aug-86   354   512 Datafile
400.charset       16  7-Aug-86   364   512 Datafile
200.charset       16  7-Aug-86   380   512 Datafile
system.interp     32 10-Sep-87   396   512 Datafile
zot              844 16-Jul-87   428   512 Datafile
13 files, 1272 blocks used, 0 unused, 0 in largest

The extracted files with the actual sizes are as follows:

$ ls -l | grep -v WIZ1
total 988
-rw-r--r-- 1 rui rui   8192 Feb 10 22:40 200.charset
-rw-r--r-- 1 rui rui  16384 Feb 10 22:40 200.monsters
-rw-r--r-- 1 rui rui   5120 Feb 10 22:40 200.title
-rw-r--r-- 1 rui rui   8192 Feb 10 22:40 400.charset
-rw-r--r-- 1 rui rui   5120 Feb 10 22:40 400.title
-rw-r--r-- 1 rui rui  27648 Feb 10 22:40 ascii.krn
-rw-r--r-- 1 rui rui    512 Feb 10 22:40 has.cache
-rw-r--r-- 1 rui rui    512 Feb 10 22:40 has.strops
-rw-r--r-- 1 rui rui   1024 Feb 10 22:40 kana.keymap
-rw-r--r-- 1 rui rui  37888 Feb 10 22:40 scenario.data
-rw-r--r-- 1 rui rui  16384 Feb 10 22:40 system.interp
-rw-r--r-- 1 rui rui  89088 Feb 10 22:40 system.pascal
-rw-r--r-- 1 rui rui 432128 Feb 10 22:40 zot

Linux file command identifies system.interp as a x86 16-bit executable (as it should).

t's uncertain whether the system operates solely on pure p-code, as the nature of the modifications made by the game authors remains unclear. system.interp seems to have some modifications for this game. system.interp also seems to be able to recognize some PASCAL-like keywords.

18
  • 2
    I would delete that Quora links (Rabbit hole), as it's total crap. Apple PASCAL is the full UCSD system. After all, that was the whole point of the UCSD system: use of a p code system and write the whole OS in p-code, so it could be ported with adapting only a few KiB of interpreter and a block level disk access. Thus the only adapted part is the 6502 interpreter and use of the 16 sector routines Woz wrote them especial for the Pascal systems to improve speed (With 13 sectors the last block of every track spread into the next, which made it slow. DOS only became 16 sector after that).
    – Raffzahn
    Commented Feb 10 at 2:50
  • Also, SOS only took the 512 byte block structure from PASCAL. SOS file system, like the later ProDOS is not compatible with the UCSD file system.
    – Raffzahn
    Commented Feb 10 at 2:53
  • 1
    Well, it was originally build to run on PDP-11 IIRC. The whole idea was rooted in the UCSD having a wide variety of computer systems but no interesting in creating lots of different versions of their courses. So the p-code system was build, made from a machine specific interpreter and (very low) level driver set, and an operating system completely written in p-code (usually using a HLL, but there was also an assembler). That way they ported it to everything, from S100 to DEC and HP all the way to IBM /370. Students got the same learning environment, no matter what computer was used.
    – Raffzahn
    Commented Feb 10 at 3:37
  • 1
    The disk format is the same as that used on the Apple II, so CiderPress will open the disk and let you examine the files. It'll show you a breakdown of the SYSTEM.PASCAL file into segments, but you'll need a separate program to disassemble the p-code. (CP2 got tripped up by a mis-stated volume size; fixed in next patch.)
    – fadden
    Commented Feb 11 at 15:31
  • 1
    @ssokolow I've done very well with DOSEmu v1 in the past. However it appears that v2 is a very different beast. Commented Feb 12 at 8:06
12

Are you aware that I re-engineered the original executables for Wizardry III and Wizardry I into Pascal code? I posted what and how I did it back around 2012 and 2014 in the AppleII newsgroups. Although those newsgroups are no longer supported you can still search on the following and find the discussion in Google Groups:

"Re-engineered: Wizardry III, Legacy of Llylgamyn" and "Wizardry re-engineering" -- for Wizardry I, Proving Grounds.

I uploaded the "source" code to the Asimov website back then.

9

One additional piece not mentioned in the other answers...

The notes on the UCSD Pascal filesystem here have links to Apple II Pascal reference material, notably this monster. You can, for example, see the filesystem documentation on page IV-15 (page 804 in the PDF). The following pages in that reference provide information on the UCSD Pascal file formats, summarized here.

While most of the files on the disk image are data files, the file SYSTEM.PASCAL on the Wizardry disk is a code file with 16 segments:

WIZARDRY
COMBAT
CASTAPSE
SWINGASW
CINIT
CUTIL
KANJIREA
UTILITIE
SHOPS
SPECIALS
CASTLE
ROLLER
CAMP
REWARDS
RUNNER
GAMEUTIL

All segments claim to be p-code (LSB first).

The CiderPress utility will open the disk and display the Pascal codefile broken into segments. It doesn't include a p-code disassembler however, so it just shows hex dumps. (CP2 doesn't handle this disk well; fixed soon.)

The file "ZOT" is a 421KB file at the end of a 360KB disk image, so only the first 100KB or so would be valid (if it's valid at all).

3

Just want to point out that while UCSD P-System was indeed intended to be a portable runtime, that, in the end, the binaries were not necessarily completely portable.

Notable bit are that the Apple system had some extensions built into the runtime (notably things like graphics access). Also, things like the binary endian status of binary encodings can differ across platforms.

Other details of the host system could leak through as well. In the end, it was very good at source code portability, and while not impossible, it was imperfect at binary compatibility.

I am sure the Wizardry folks took advantage of everything Apple Pascal and the Apple had to offer for their game.

1

Your listing is the actual program image. For COM files, nominally speaking, the data at the addresses 0000-00ff (hexadecimal) are provided by the operating system and has the form of a Program Segment Prefix (PSP). The program image listed in the COM file is placed at 0100 (hexadecimal) and beyond, when the program is loaded and run. The program can access the PSP area and look at what the operating system supplied to it.

Your first 64 bytes, as a program image (in hexadecimal), are therefore actually addressed as:

    0100: fa 8c c8 8e c0 8e d8 8e d0 bc 0e 08 fb b4 0f cd
    0110: 10 a2 dc 01 8c c8 8e c0 bb ff ff b4 4a cd 21 81
    0120: fb 00 41 73 0c ba c4 03 b4 09 cd 21 b8 08 4c cd
    0130: 21 8c c8 ba 1f 08 d1 ea d1 ea d1 ea d1 ea 01 d0
    0140: a3 d2 01 ba 63 04 b8 00 3d cd 21 73 0c ba f1 03

80x86 opcodes are naturally formatted in octal, except for the conditional jumps. There was a tendency to stray away from this after the Pentium, when the older legacy was forgotten.

The data is listed in hexadecimal. Two byte data, e.g. 080e is sequenced in memory as (0e, 08). Thus, for instance, the instruction mov SP, _080e corresponds to \274 080e, or the byte sequence bc 0e 08, in hexadecimal.

    _0100:
    ;;      Critical Section: align ES, DS and SS with CS, move SP to _080e.
    ;;      This is a method for jail-breaking out of the 64k limit for *.COM files.
    ;;      It has a rare race condition that will disrupt the stack, if an interrupt is pending when "cli" is executed.
            cli                     ;; \372
            mov AX, CS              ;; \214\310
            mov ES, AX              ;; \216\300
            mov DS, AX              ;; \216\330
            mov SS, AX              ;; \216\320
            mov SP, _080e           ;; \274 080e
            sti                     ;; \373
    ;;      _01dc = Current Video Mode.
            mov AH, 0x0f            ;; \264 0f
            int 0x10                ;; \315 10
            mov [_01dc], AL         ;; \242 01dc
    ;;      Resize the memory block at CS to maximum size 0xffff.
            mov AX, CS              ;; \214\310
            mov ES, AX              ;; \216\300
            mov BX, 0xffff          ;; \273 ffff
            mov AH, 0x4a            ;; \264 4a
            int 0x21                ;; \315 21
    ;;      BX is the new size. Ignore the error flag CF and error code AX.
    ;;      if (BX < 0x4100) {
            cmp BX, 0x4100          ;; \201\373 4100
            jnb _0131               ;; 73 0c
    ;;              Write the $-suffixed string _03c4 (excluding the ending '$') to standard output.
            mov DX, _03c4           ;; \272 03c4
            mov AH, 0x09            ;; \264 09
            int 0x21                ;; \315 21
    ;;              Exit with return code 8 (i.e. exit(8)).
            mov AX, 0x4c08          ;; \270 4c08
            int 0x21                ;; \315 21
    ;;      }
    _0131:
    ;;      _01d2 = CS + (0x081f >> 4);
            mov AX, CS              ;; \214\310
            mov DX, 0x081f          ;; \272 081f
            shr DX, 1               ;; \321\352
            shr DX, 1               ;; \321\352
            shr DX, 1               ;; \321\352
            shr DX, 1               ;; \321\352
            add AX, DX              ;; \001\320
            mov [_01d2], AX         ;; \243 01d2
    ;;      Open file _0463, access mode 0 (read?).
            mov DX, _0463           ;; \272 0463
            mov AX, 0x3d00          ;; \270 3d00
            int 0x21                ;; \315 21
    ;;      CF means "Not OK", AX is the error code, if not OK.
    ;;      if (!CF) goto _0159;
            jnc _0159               ;; 73 0c
    ;;      DX = _03f1;
            mov DX, _03f1           ;; \272 03f1
    _0150:
    ;;      Probably:
    ;;      mov AH, 0x09            ;; \264 09
    ;;      int 0x21                ;; \315 21
    ⋯
    _0159:
    ⋯
    _01d2:  dw      <Relocated Code Segment>
    ⋯
    _01dc:  db      <Current Video Mode>
    ⋯
    _03c2:
    ;;      Probable, since '!' (= 0x21) was cited in the query:
            int 0x21                ;; \315 21
    _03c4:  db      "Wizardry requires 300K free memory to run.\r\n",'$'
    _03f1:  db      "The file WIZ1.DSK is missing or damaged.\r\n",'$'
    _041c:  db      "The file SAVE1.DSK cannot be created.\r\n", '$'
    _0444:  db      "Read error in the Boot Block.\r\n", '$'
    _0463:  db      "WIZ1.DSK",0
    _046c:  db      "SAVE1.DSK",0
    _0476:  db      "Thank you for playing Wizardry!\r\n", '$'
    ⋯
    _080e:  ;; Relocated stack top.

To reconstruct this in its entirety, it would be necessary to see the remaining part of the program image on your *.COM file. I listed what I can infer, based on your additional remarks.

Edit (added discussion of WIZ1.DSK):
WIZ1.DSK is also a code image, also with a few jump-over data areas. I can't say what the intended address is without the added context of the WIZ1.COM file, so I will set it at 0000.

    0000: eb 38 90 80 08 00 00 00 00 53 79 73 74 65 6d 20 │ ∙∙∙∙∙∙∙∙∙System  │
    0010: 62 6f 6f 74 73 74 72 61 70 20 76 32 2e 30 20 44 │ bootstrap v2.0 D │
    0020: 53 44 44 0d 0a 28 43 29 20 31 39 38 37 20 52 57 │ SDD∙∙(C) 1987 RW │
    0030: 49 2c 20 49 6e 63 2e 0d 0a 00 bb 00 7c 8c c8 8e │ I, Inc.∙∙∙∙∙∙∙∙∙ │
    0040: d0 8b e3 8e c0 31 c0 8e d8 eb 1f 00 3e c5 37 3e │ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │

This is what the listing says. I'm not entirely sure about this, because its code is redundant.

    _0000:
            jmp _003a       ;; \353 38
    _0002:  db 90,80,08,00,00,00,00
    _0009:  db "System bootstrap v2.0 DSDD\r\n"
    _0025:  db "(C) 1987 RWI, Inc.\r\n",00
    _003a:
    ;;      SS:SP = ES:7c00;
            mov BX, 0x7c00  ;; \273 7c00
            mov AX, ES      ;; \214\310
            mov SS, AX      ;; \216\320
            mov SP, BX      ;; \213\343
    ;;      ES = ES;
            mov ES, AX      ;; \216\300
    ;;      DS = AX = 0;
            xor AX, AX      ;; \061\300
            mov DS, AX      ;; \216\330
            jmp _006a       ;; \353 1f
    _004b:  db 00           ;; Alignment padding.
    _004c:
            DS: lds SI,[BX] ;; \076\305\067 ;; Probably data "db 3e,c5,37".
            DS: ⋯           ;; \076⋯        ;; Probably data "db 3e,⋯".
            ⋯
    _006a:
            ⋯
4
  • 2
    It's not necessary to see the rest of the COM file, because we already know it contains a p-Code interpreter. The interesting part is the WIZ1.DSK file, but as the other answers say, that has already been reverse-engineered by at least two different people (which of course doesn't mean the OP can't reverse engineer it a third time, for his own pleasure).
    – dirkt
    Commented Sep 24 at 2:40
  • I have the rest of the COM file now. It is small and its only purpose is to bootstrap the DSK file, and (as I noted in the comments in my reconstruction) to break out of the limitations imposed by COM files. That's the "jail-break". The DSK file is much larger. It could go from three to four, if I take an interest in it. A similar situation happens with other older DOS programs. A notable example is a version of DEBUG, which is self-extracting, self-relocating and self-loading, and the Vinyl Goddess From Mars, which uses PKLITE to extract, relocate and load itself. Commented Sep 29 at 19:52
  • 1
    I somehow get the impression that you have not read the other answers. If you indeed have not, I recommend to read them.
    – dirkt
    Commented Sep 30 at 5:42
  • The files that I retrieved came from the links cited in the other replies. As I said, the number of reconstructions could go from 3 to 4, time permitting, and assuming the original query'er (who would be #3) is taking an interest in studying the game up close and personal like this, too. Commented Oct 5 at 20:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .