Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Wizardry re-engineering

4,058 views
Skip to first unread message

Didier VALLET

unread,
Mar 26, 2014, 2:00:07 AM3/26/14
to

Hello, i've read a part of Tommy's big work on Wizardry III and i'm interested in looking on the older ones like Wizardry I (also called Sorcellerie in French)

"
Le mardi 10 avril 2012 09:53:17 UTC+2, TommyGoog a écrit :
> Recently I completed a rather interesting project that I'd like to
> share with the Apple][ community. I re-engineered the two main
> executable files, WIZARDRY.CODE and WIZUTIL.CODE, for "Wizardry III,
> Legacy of Llylgamyn" into Pascal code.
"

I saw that there are tools to do it like his Wiz4 or Hyde.
Does anybody know where are tools to work on p-code or can help me to start.
Thanks a lot. Didier

TommyGoog

unread,
Mar 26, 2014, 10:14:45 PM3/26/14
to
On Wednesday, March 26, 2014 1:00:07 AM UTC-5, Didier VALLET wrote:
> Hello, i've read a part of Tommy's big work on Wizardry III and i'm interested in looking on the older ones like Wizardry I (also called Sorcellerie in French)
>
>
>
> I saw that there are tools to do it like his Wiz4 or Hyde.
>
> Does anybody know where are tools to work on p-code or can help me to start.
>
> Thanks a lot. Didier

Hi Didier,

I am still alive. (Last year I suffered a heart attack.)

I have the Wiz4 program that I wrote. It was written in Applesoft Basic. I have it in a ".dsk" image that I used with AppleWin. I also have the source code text of Wiz4 "printed" to a file (".txt").

If you would like the ".dsk" image (or the text file listing), what is the best way to get it (them) to you?

Tommy

TommyGoog

unread,
Mar 29, 2014, 10:27:56 PM3/29/14
to
On Wednesday, March 26, 2014 1:00:07 AM UTC-5, Didier VALLET wrote:
I've replied to an email from Didier and sent him a copy of WIZ4. If anyone else would like a copy of WIZ4 let me know.

I'm now tempted to re-engineer Wizardry I (Proving Grounds). Would anyone besides Didier be interested if I did? I ask this because there didn't seem to be a lot of interest after I re-engineered Wizardry III (see my post 2 years ago: Re-engineered: Wizardry III, Legacy of Llylgamyn).

Tommy



Tommy

Vladimir Ivanov

unread,
Mar 31, 2014, 6:57:25 AM3/31/14
to


On Sat, 29 Mar 2014, TommyGoog wrote:

> I've replied to an email from Didier and sent him a copy of WIZ4. If
> anyone else would like a copy of WIZ4 let me know.

I'd suggest you upload your works and documentation to Asimov.

> I'm now tempted to re-engineer Wizardry I (Proving Grounds). Would
> anyone besides Didier be interested if I did? I ask this because there
> didn't seem to be a lot of interest after I re-engineered Wizardry III
> (see my post 2 years ago: Re-engineered: Wizardry III, Legacy of
> Llylgamyn).

I followed you previous work, which then led me to discovering Hyde's
book. I suppose there are other people like me that don't have interest in
the Wizardry games themselves, but rather in the reverse-engineering
process.

Good luck!

Rob Craig

unread,
Apr 1, 2014, 5:11:33 PM4/1/14
to
Hi Tommy,
Im very interested in you work. Can you send me the things you have discovered. Especially Wizardry 4. A true masterpiece.

I run www.wizardryarchives.com

Cheers,
Rob

sicklittlemonkey

unread,
Apr 1, 2014, 8:14:58 PM4/1/14
to
On Sunday, 30 March 2014 15:27:56 UTC+13, TommyGoog wrote:
> I'm now tempted to re-engineer Wizardry I (Proving Grounds). Would anyone besides Didier be interested if I did? I ask this because there didn't seem to be a lot of interest after I re-engineered Wizardry III (see my post 2 years ago: Re-engineered: Wizardry III, Legacy of Llylgamyn).

<takes off hat>
Wow. You have completed an Epic Hack, Sir. Larger and longer than the games themselves!

Original discussion (which I missed) is here:
https://groups.google.com/d/topic/comp.sys.apple2/2oDJTbQaJWU/discussion

If you did Wizardy I (Proving Grounds) I'd definitely read your report with great interest. I don't know how many people are likely to actually use the source code, but that's not why you did it, is it? ; - ) At least you've overcome the first _decidedly_ non-trivial hurdle should someone else want to port it to another platform. (There are Pascal to JavaScript compilers ...)

Also, serious academic research is being done into gaming history, and some future researcher will likely use what you've done - if it's preserved. I don't know about you, but even being being a footnote in a published paper would make me happy enough.

I'm thinking of places like this:
http://www.icheg.org/research

They have Wizardry in their collection (this is the PC version though):
http://www.thestrong.org/online-collections/nmop/22/52/110.10828

Cheers,
Nick.

Steve Nickolas

unread,
Apr 1, 2014, 11:42:13 PM4/1/14
to
This makes me wonder: if Wizardry is a 48K Pascal program, would it be
possible to modify the 48K Pascal VM it uses to run on top of ProDOS and
use the ProDOS filesystem?

-uso.

TommyGoog

unread,
Apr 2, 2014, 9:14:01 PM4/2/14
to
On Wednesday, March 26, 2014 1:00:07 AM UTC-5, Didier VALLET wrote:
Re-Engineering Wizardry I Proving Grounds. The adventure begins....

In the coming months I (Tommy) will hopefully be re-engineering Wizardry I Proving Grounds. Instead of making the journey alone, I will frequently update this thread with my progress. I encourage anyone with questions to chime in. There will likely be hints and information regarding re-engineering that were not in the thread where I re-engineered Wizardry III (Legacy of Llylgamyn, LOL or LofL).

Review LofL thread.
Get reading materials (Apple Pascal OS 1.1, Apple Pascal Language Ref + Addendum, etc.)
Set up directory (Wizardry1) and files on my WindowsXP pc:
01 EDIT.DSK
SYSTEM.APPLE
SYSTEM.PASCAL
SYSTEM.MISCINFO
SYSTEM.FILER
SYSTEM.EDITOR
SYSTEM.COMPILER
SYSTEM.SWAPDISK
SYSTEM.LIBRARY
02 COMPILE.DSK
SYSTEM.APPLE
SYSTEM.PASCAL
SYSTEM.MISCINFO
SYSTEM.COMPILER
SYSTEM.LINKER
SYSTEM.ASSMBLER
6500.OPCODES
6500.ERRORS
04 APPLE3.1.1.DSK
FORMATTER.CODE
LIBRARY.CODE
05 DECOMPILE.DSK
HELLO
WIZ4
06 WIZ1A.DSK
07 WIZ1B.DSK
08 WIZ1C.DSK
09 WIZ1D.DSK (For 605 ASM code)
10 WIZ1E.DSK (for SYSTEM.STARTUP)
11 MASTER.DSK (DOS Master Disk)
12 PASCAL BLANK.DSK (Init'd using FORMATTER in PASCAL)
13 MAKELIB.DSK (Used when altering SYSTEM.LIBRARY)
14 UnalteredAPPLE1.1.1.DSK
SYSTEM.LIBRARY

Shortcut to my 4-disk enabled AppleWin.exe (Don't even think about using a 2-disk drive system for this.)
pCodeFrenchProvGrndBoot.txt (Using WIZ4)
pCodeProvGrndBoot.txt (Using WIZ4)
Printer.txt (Output from AppleWin.exe execution)
PROVGRNDBOOT.DSK
PROVGRNDSCN.DSK
Shortcut to WinDiff.exe
Wiz1Design.xls (I generally use Excel to record my progress.)

Verified my version of Wizardry 1 from my "box" set of Wizardry I, II, III is same as one at ASIMOV.

From ASIMOV/Sorcellerie:
Ran WIZ4 for Sorcellerie and did a quick eyeball comparison to English version.
Most of code will be identical I think, except for the language differences.

A lot of the code for Wizardry I will be the same as for Wizardry III.

One thought for developing the Wiz1 Pascal code is to first start with Wiz3 and remove the code that is vastly different, then start building up the resulting code.

Copied LofL source code disks to WIZ1A, WIZ1B, WIZ1C, WIZ1D.
Copied SYSTEM.LIBRARY from LofL to EDIT.dsk and COMPILE.dsk.
Modified source code to refer to new volumne name (WIZ1A:, WIZ1B:, WIZ1C:, etc.) on the include statements.

Compiled the code.
Remembered just how tight the space is on the disks. Need to delete WIZARDRY.CODE first, and then make sure output goes to disk with about 200 free blocks.
Made sure that SYSTEM.LIBRARY contained the 6502 code for Wizardry.
Made sure SWAPFILE was present.
Turned on S(WAP option on PASCAL main menu (to edit large files).
Remembered "($S+)" swapping option.

Where to begin?

(We rest after the first hard day of our journey.)

TommyGoog

unread,
Apr 4, 2014, 1:20:16 PM4/4/14
to
....The journey continues....

Let's start by looking at the directory listings for Wizardry I:

WBV2.1:
1 WIZARDRY.CODE
2 RTSTRP.APPLE
3 SYSTEM.PASCAL
4 SYSTEM.LIBRARY
5 SYSTEM.MISCINFO
6 WT
7 SYSTEM.STARTUP


Compare with LOL:

LOLBOOT:
1 WIZARDRY.CODE
2 SYSTEM.CHARSET
3 SYSTEM.STARTUP
4 PICTURE.BITS
5 WIZUTIL.CODE
6 SYSTEM.LIBRARY
7 RTSTRP.APPLE
8 SYSTEM.PASCAL
9 SYSTEM.MISCINFO

Read materials for Apple Pascal OS (EDIT, COMPILE, LINK, SYSTEM.LIBRARY, etc.)
Play with Pascal Editor a bit.
S(et E(nvironment
A(uto indent TRUE
F(illing FALSE
T(oken def FALSE

Note, use AppleWin in APPLE IIe mode for 80 columns.

DeCompiled Wizardry1 (both English and French versions.

I noticed the DeCompiler (Wiz4) generated a few "AN UNKNOWN STANDARD PROCEDURE ?!?!" messages for Wizardry1. This means that Wizardry1 calls an external procedure that I did not encounter in LOL.

I noticed WizUtil from LOL also had 1 "AN UNKNOWN" message. Turns out that one was MEMAVAIL, but I never updated Wiz4.

Note the SEGMENT names in both main programs (WIZARDRY.CODE) are the same:
WIZARDRY
UTILITIE
SHOPS
SPECIALS
COMBAT
CINIT
CUTIL
MELEE
CASTASPE
SWINGASW
CASTLE
ROLLER
CAMP
REWARDS
RUNNER

In LOL, SYSTEM.STARTUP is mostly the "picture" splash screens.
WT is a data file. Perhaps it is the picture bits for Wizardry1.
LOL moved code from Wiz1 SYSTEM.STARTUP to WIZUTIL.CODE, and Wiz1 does not have a WIZUTIL.CODE file.

Let's look at the file SYSTEM.LIBRARY using the LIBMAP utility:

LIBRARY MAP FOR #11:SYSTEM.LIBRARY
$1F Segment #31:
System version = 3.0, code type is P-Code (least sig. 1st)
PASCALIO library unit (LINKED INTRINSIC)
TYPE DECMAX = INTEGER[36];
STUNT = RECORD CASE INTEGER OF
2:(W2:INTEGER[4]);
3:(W3:INTEGER[8]);
4:(W4:INTEGER[12]);
5:(W5:INTEGER[16]);
6:(W6:INTEGER[20]);
7:(W7:INTEGER[24]);
8:(W8:INTEGER[28]);
9:(W9:INTEGER[32]);
10:(W10:INTEGER[36])
END;
PROCEDURE FSEEK(VAR F: FIB; RECNUM: INTEGER);
PROCEDURE FREADREAL(VAR F: FIB; VAR X: REAL);
PROCEDURE FWRITEREAL(VAR F: FIB; X: REAL; W, D: INTEGER);
PROCEDURE FREADDEC(VAR F: FIB; VAR D: STUNT; L: INTEGER);
PROCEDURE FWRITEDEC(VAR F: FIB; D: DECMAX; RLENG: INTEGER);
FUNCTION SUPER_MOD(A,B : INTEGER) : INTEGER;
FUNCTION SUPER_DIV(A,B : INTEGER) : INTEGER;
----------------------------------------------------------------------
$1E Segment #30:
System version = 3.0, code type is 6502
LONGINTI library unit (LINKED INTRINSIC)
TYPE DECMAX = INTEGER[36];
STUNT = RECORD CASE INTEGER OF
2:(W2:INTEGER[4]);
3:(W3:INTEGER[8]);
4:(W4:INTEGER[12]);
5:(W5:INTEGER[16]);
6:(W6:INTEGER[20]);
7:(W7:INTEGER[24]);
8:(W8:INTEGER[28]);
9:(W9:INTEGER[32]);
10:(W10:INTEGER[36])
END;
PROCEDURE FREADDEC(VAR F: FIB; VAR D: STUNT; L: INTEGER);
PROCEDURE FWRITEDEC(VAR F: FIB; D: DECMAX; RLENG: INTEGER);
----------------------------------------------------------------------
$1C Segment #28:
System version = 3.0, code type is P-Code (least sig. 1st)
CHAINSTU library unit (LINKED INTRINSIC)
PROCEDURE SETCHAIN(TYTLE:STRING);
PROCEDURE SETCVAL(VAL:STRING);
PROCEDURE GETCVAL(VAR VAL:STRING);
PROCEDURE SWAPON;
PROCEDURE SWAPOFF;
----------------------------------------------------------------------
$1D Segment #29:
System version = 3.0, code type is P-Code (least sig. 1st)
TRANSCEN library unit (LINKED INTRINSIC)
FUNCTION SIN(X:REAL):REAL;
FUNCTION COS(X:REAL):REAL;
FUNCTION EXP(X:REAL):REAL;
FUNCTION ATAN(X:REAL):REAL;
FUNCTION LN(X:REAL):REAL;
FUNCTION LOG(X:REAL):REAL;
FUNCTION SQRT(X:REAL):REAL;
----------------------------------------------------------------------
$14 Segment #20:
System version = II.1, code type is 6502
TURTLEGR library unit (LINKED INTRINSIC)
TYPE
SCREENCOLOR=(none,white,black,reverse,radar,
black1,green,violet,white1,black2,orange,blue,white2);
PROCEDURE INITTURTLE;
PROCEDURE TURN(ANGLE: INTEGER);
PROCEDURE TURNTO(ANGLE: INTEGER);
PROCEDURE MOVE(DIST: INTEGER);
PROCEDURE MOVETO(X,Y: INTEGER);
PROCEDURE PENCOLOR(PENMODE: SCREENCOLOR);
PROCEDURE TEXTMODE;
PROCEDURE GRAFMODE;
PROCEDURE FILLSCREEN(FILLCOLOR: SCREENCOLOR);
PROCEDURE VIEWPORT(LEFT,RIGHT,BOTTOM,TOP: INTEGER);
FUNCTION TURTLEX: INTEGER;
FUNCTION TURTLEY: INTEGER;
FUNCTION TURTLEANG: INTEGER;
FUNCTION SCREENBIT(X,Y: INTEGER): BOOLEAN;
PROCEDURE DRAWBLOCK(VAR SOURCE; ROWSIZE,XSKIP,YSKIP,WIDTH,HEIGHT,
XSCREEN,YSCREEN,MODE: INTEGER);
PROCEDURE WCHAR(CH: CHAR);
PROCEDURE WSTRING(S: STRING);
PROCEDURE CHARTYPE(MODE: INTEGER);
----------------------------------------------------------------------
$15 Segment #21:
System version = II.1, code type is P-Code (least sig. 1st)
TURTLEGR data segment
----------------------------------------------------------------------
$16 Segment #22:
System version = 3.0, code type is 6502
APPLESTU library unit (LINKED INTRINSIC)
FUNCTION PADDLE(SELECT: INTEGER): INTEGER;
FUNCTION BUTTON(SELECT: INTEGER): BOOLEAN;
PROCEDURE TTLOUT(SELECT: INTEGER; DATA: BOOLEAN);
FUNCTION KEYPRESS: BOOLEAN;
FUNCTION RANDOM: INTEGER;
PROCEDURE RANDOMIZE;
PROCEDURE NOTE(PITCH,DURATION: INTEGER);
----------------------------------------------------------------------


The first program executed on a "turnkey" Pascal system is SYSTEM.STARTUP. I will start by DeCompiling SYSTEM.STARTUP and then later turn my attention to WIZARDRY.CODE.

SYSTEM.STARTUP

SEGMENT: Procedures:
0 WIZBOOT 5
1 UTILS 36
2 TITLELOA 8
3 OPTIONS 1

WIZBOOT lex Start Exit Order Hierarchy
1 0 50CC 50FF 2 7.0.1
2 6502 code 511A 52EA 3
3 6502 code 52F0 54B6 4
4 1 5000 50BA 1 7.0.4
5 6502 code 54BC 5642 5

Every Pascal procedure on a diskette can be identified by a series of 3 numbers (File, Segment, Procedure). This is the information that Wiz4 solicits and is the way that I first name the procedures in the code when I am creating the Pascal code. For example, SYSTEM.STARTUP is file 7 on the disk. Segment 0 is the first segment, and procedure 1 is the main line. I might refer to this as P070001. (File 07, Segment 00, Procedure 01).

Here is the output from Wiz4 (DeCompiler) for P070001 (SYSTEM.STARTUP, SEGMENT 0, Procedure 01):

FILE: 7 SEG: 0 PROC: 1

JTAB FOR SUBROUTINE 1:
DATA SIZE: 12
PARAM SIZE: 4
EXIT AT: 50FF
ENTER AT: 50CC
PROC NUMBER: 1
LEXICAL LEVEL: 0
50CC B9 36 UJP. JUMP TO 5104
50CE CD 1C 01 CXP. CALL EXTERNAL PROCEDURE: 01 IN SEGMENT: 1C
50D1 CE 04 CLP. CALL CHILD PROCEDURE: 04
50D3 CD 08 01 CXP. CALL EXTERNAL PROCEDURE: 01 IN SEGMENT: 08
50D6 CD 09 01 CXP. CALL EXTERNAL PROCEDURE: 01 IN SEGMENT: 09
50D9 EA SLDO. PUSH BASE.03
50DA B9 12 UJP. JUMP TO 50EE
50DC CE 04 CLP. CALL CHILD PROCEDURE: 04
50DE 01 SLDC. PUSH #0001
50DF 01 SLDC. PUSH #0001
50E0 9E 04 EXIT. EXIT FROM PROCEDURE. (TOS)=PROC# (TOS-1)=SEG#
50E2 B9 18 UJP. JUMP TO 50FC
50E4 CD 07 01 CXP. CALL EXTERNAL PROCEDURE: 01 IN SEGMENT: 07
50E7 B9 13 UJP. JUMP TO 50FC
50E9 CD 08 01 CXP. CALL EXTERNAL PROCEDURE: 01 IN SEGMENT: 08
50EC B9 0E UJP. JUMP TO 50FC
50EE AC (00)53 00 55 00 B9 06 TABLE: 1A 00 0F 00 16 00
XJP. W1,W2,W3,<TABLE>
50FC 00 SLDC. PUSH #0000
50FD A1 F6 UJP. IF NOT (TOS) THEN JUMP TO 50D6
50FF 1C SLDC. PUSH #001C
5100 9E 16 DUSE. DEC USE CNT FOR SEG #(TOS)
5102 B9 05 UJP. JUMP TO 5109
5104 1C SLDC. PUSH #001C
5105 9E 15 RSEG. READ SEGMENT #(TOS) FROM ACTIVE SEG TABLE
5107 B9 F4 UJP. JUMP TO 50CE
5109 C1 00 RBP. RETURN FROM BASE PROCEDURE.
510B 00 SLDC. PUSH #0000
510C 3E SLDC. PUSH #003E
510D 00 SLDC. PUSH #0000
510E 38 SLDC. PUSH #0038
510F 00 SLDC. PUSH #0000

What is the following? What is #001C? And Procedure 01?
50CC B9 36 UJP. JUMP TO 5104
50CE CD 1C 01 CXP. CALL EXTERNAL PROCEDURE: 01 IN SEGMENT: 1C

5104 1C SLDC. PUSH #001C
5105 9E 15 RSEG. READ SEGMENT #(TOS) FROM ACTIVE SEG TABLE

Ok, LOL has the same construct. Oh yeah! INTRINSICS.

See Apple Pascal Language, p. 78, "The Initialization Part of a UNIT":
"The resulting code runs automatically when the host program is executed, before the program is run."

In Language Reference Addendum is a discussion about SEGMENT NUMBERS and their assignment:
"The segment number of an Intrinsic UNIT segment....can be found by examining the segment dictionary of the SYSTEM.LIBRARY file with the LIBMAP utility program."

Looking back a the LIBMAP output earlier in this post we see the following:

Segment #28:
System version = 3.0, code type is P-Code (least sig. 1st)
CHAINSTU library unit (LINKED INTRINSIC)
PROCEDURE SETCHAIN(TYTLE:STRING);

Cool! Another mystery solved! (28 = $1C). WIZBOOT therefore uses CHAINSTU (and the procedure SETCHAIN).

Lets look at more p-code:

50D3 CD 08 01 CXP. CALL EXTERNAL PROCEDURE: 01 IN SEGMENT: 08
50D6 CD 09 01 CXP. CALL EXTERNAL PROCEDURE: 01 IN SEGMENT: 09

Segment 8? Segment 9? I'm lost. There are only 4 segments in SYSTEM.STARTUP.

Time to learn more about Segments....

Apple Pascal Language, p 76-77 has a discussion about File segment numbers compared to the Execution segment numbers.
0 System
1 Program's mainline
2-6 System
7 First declared SEGMENT from program
8 Second declared SEGMENT from program
... Up to 16 (?) of these.

Ok, now we are getting somewhere.
7 = UTILS
8 = TITLELOA
9 = OPTIONS

Hmmm, I see there is 6502 code in SYSTEM.STARTUP. How do we get that code so we can examine it and "de-compile" (disassemble) it into our re-engineered code?

Did I mention this was going to be a long journey?

TommyGoog

unread,
Apr 7, 2014, 3:28:10 PM4/7/14
to
On Friday, April 4, 2014 12:20:16 PM UTC-5, TommyGoog wrote:
> ....The journey continues....

>
> Hmmm, I see there is 6502 code in SYSTEM.STARTUP. How do we get that code so we can examine it and "de-compile" (disassemble) it into our re-engineered code?
>
>
>
> Did I mention this was going to be a long journey?

I use the DeCompiler (Wiz4) to get the procedures that were written in assembly language by the authors of Wizardry. There are other ways to get the code, but this works for me!

----------

PROCESS ALL? N
FILES: 7

1 WIZARDRY.CODE
2 RTSTRP.APPLE
3 SYSTEM.PASCAL
4 SYSTEM.LIBRARY
5 SYSTEM.MISCINFO
6 WT
7 SYSTEM.STARTUP

TYPE A FILE NUMBER (OR -1) 7

SEGMENT T/S = 32/2 --- PASCAL T/S
SEGMENT T/S = 32/13 --- DOS 3.3 T/S

0 WIZBOOT
1 UTILS
2 TITLELOA
3 OPTIONS

TYPE A SEGMENT NUMBER (OR -1)

T/S FOR SEGMENT 34/8 --- PASCAL
T/S FOR SEGMENT 34/7 --- DOS

SEGMENT'S START ADDR($5000):

THERE ARE 5 PROCEDURES.


ENTER PROCEDURE # (OR -1) 2


JTAB FOR SUBROUTINE 2:
DATA SIZE: 72
PARAM SIZE: 8
EXIT AT: 52EA
ENTER AT: 511A
PROC NUMBER: 0
6502 CODE

ENTER PROCEDURE # (OR -1) -1

SEGMENT T/S = 32/2 --- PASCAL T/S
SEGMENT T/S = 32/13 --- DOS 3.3 T/S

0 WIZBOOT
1 UTILS
2 TITLELOA
3 OPTIONS

TYPE A SEGMENT NUMBER (OR -1) -1



TYPE A FILE NUMBER (OR -1) -1


]CALL-151

*511AL

511A- 68 PLA
511B- AA TAX
511C- 68 PLA
511D- A8 TAY
511E- 68 PLA
511F- 85 00 STA $00
5121- 68 PLA
5122- 85 01 STA $01
5124- 68 PLA
5125- 85 02 STA $02
5127- 68 PLA
5128- 85 03 STA $03
512A- 98 TYA
512B- 48 PHA
512C- 8A TXA
512D- 48 PHA
512E- 18 CLC
512F- A5 02 LDA $02
5131- 65 00 ADC $00
5133- 85 02 STA $02
*

----------

The DeCompiler always loads the segment at $5000 (even if you specify a different address). The values in the JTAB displayed for a procedure tells you where that procedure was loaded into memory. Then I simply use the Apple's disassembler to display the information. Since my HELLO program turned on the printer, the text can be found in PRINTER.TXT on my pc thanks to AppleWin.

I compared the code from Wiz1 to my previous 6502 code in LOL. Those routines were:
P050002 COPYPROT
P010024 PRPICCH
P010025 DRAWSCR
P010026 DRAWLINE
P010027 RANDOM
P010028 CHKKEYBD
P010030 SCRNDATA

The code at P070002 ($511A) looks much different from the code in LOL.
The code at P070003 ($52F0) looks like disk handling and might be like COPYPROT.
The code at P070005 ($54BC) is similar to a screen table in LOL at L11E2 in SCRNDATA.

Before working on WIZBOOT (SYSTEM.STARTUP, SEGMENT 0), lets take a peek at Segment UTILS.

I noticed the UTILS segment for Wizardry1 has 36 procedures. Using output from the DeCompiler, I made the following table:

ProvGrnds LofL
7.1.1 5.1.1 UTILS main No "Update" in LOL
7.1.2 5.1.2 GETREC identical
7.1.3 5.1.3 PUTREC identical
7.1.4 5.1.4 GETKEY some variable diffs
7.1.5 5.1.5 FINDFILE identical
7.1.6 5.1.6 GETCR identical
7.1.7 5.1.7 EXITUTIL SYSTEM.PASCAL vs SYSTEM.CHARSET
7.1.8 5.1.8 RDSCNTC2 identical
7.1.9 5.1.9 RDSCNTOC identical
7.1.A 5.1.A GETPASS identical
7.1.B 5.1.B RDCHARAC identical
7.1.C 5.1.C WRCHARAC identical
7.1.D 5.1.D WRICACHE variable stores seem off by 1
7.1.E 5.1.E PRESSRET identical
7.1.F 5.1.F TITLESCR identical
7.1.10 5.1.10 RTNESC identical
7.1.11 5.1.11 CHGNAMES identical
7.1.12 5.1.12 GETNAME identical
7.1.13 5.1.13 BACKUP identical
7.1.14 5.1.14 FRBACKUP identical
7.1.15 5.1.15 TOBACKUP identical
7.1.16 5.1.16 RECOVER identical
7.1.17 5.1.17 TRANSFER "MOVE CHARS BETWEEN SCENARIOS" vs
"MOVE CHARS FROM A SCENARIO"
"TO LEGACY OF LLYLGAMYN ONLY!"
and other differences
7.1.18 5.1.18 REMOVCHR mostly identical, but lots more code at
end in Wiz1
7.1.19 "** CHAR HAS NON-XFERRABLE ITEMS"
7.1.1A 5.1.19 TRANBAD lots of differences in messages/conditions
7.1.1B 5.1.1A TRANGOOD differences in code. More in LOL.

The following procedures are in Wiz1, but don't exist in LOL.

7.1.1C "MAKE NEW SCENARIO DISKETTE"
7.1.1D "ERROR MAKING SCENARIO"
7.1.1E call 1D
7.1.1F "NOT SCENARIO DISK"
7.1.20 "STEP 2 - UPDATE SCENARIO SIDE"
7.1.21 "ERROR DURING UPDATE"
7.1.22 "UPDATING"
7.1.23 Read / Write Volume
7.1.24 "UPDATE DISK"

All of the procedures from 7.1.1C to 7.1.24 are in the MAKESCEN segment for LOL. Since they don't exist in Wiz1, I removed them from the code (recall that I first copied all the LOL code to the disks and I'm removing code that is not in Wiz1.) I also removed the call to MAKESCEN.

I next tried to enter some place holder "dummy" procedures so that UTILS segment would have 36 procedures.

PROCEDURE P07011B;
PROCEDURE P07011C;
PROCEDURE P07011D;
BEGIN
END;
BEGIN
END;

...and so forth.

When I compiled this code I got the message:

ERROR 399

So I looked up that error in the manual:

399: Implementation restriction

That's it! No other information about the error!

After awhile I realized I had placed the "dummy" procedures before some Segment procedures. After I moved the code it compiled cleanly.

Some random notes....

Source files are so large that they must be split so that the editor can load them. This makes it very difficult to do simple things like find and replace text throughout the code. Note also that "included" files cannot be nested.

When working with the DeCompiler, sometimes it helps to transfer the "file.CODE" by itself to a single diskette, and then run the DeCompiler and answer "Y" for all. You can do this for the original Wiz1 file and the re-engineered Wiz1 file and then easily compare the listings using Windiff.

When working with Apple Pascal, I never use the "work" files called SYSTEM.WRK.TEXT or SYSTEM.WRK.CODE. The source files for Wizardry are so large that they need to be on volumes (diskettes) by themselves.

Because of the file size problems, I had to refrain from putting comments in the re-engineered code.

I also use identifier names in the Pascal code that are only 8 characters or fewer. This helps with the file size problem, and also avoids a peculiar scoping problem that can occur in Pascal with variables having the first 8 characters the same.

I make frequent use of the "drag and drop" file to insert a diskette into the AppleWin floppy drive.

I make use of "Scroll Lock" to maximize the speed of AppleWin.

Ok, back to some more coding....

I added SEGMENT TITLELOA(), and also inserted into WIZUTIL the include (*I WIZ1E:TITLELOA *)

I now have the following:

SYSTEM.STARTUP
WIZBOOT 4 procedures
UTILS 36 procedures
TITLELOA 1 procedure
OPTIONS 1 procedure

Note I changed the name from WIZUTIL to SYSTEM.STARTUP to match Wiz1. For compiling I need "#5:SYSTEM.STARTUP." (with the period at end), and for the destination "#5:STARTUP.CODE".

Eventually I changed that to just STARTUP.TEXT and STARTUP.CODE and will make a change at the very end to SYSTEM.STARTUP. It was very confusing using the Pascal system with those other names.

In my next post, I will examine SYSTEM.STARTUP and begin re-engineering starting with the WIZBOOT main line.

Are we there yet?

TommyGoog

unread,
Apr 7, 2014, 7:13:24 PM4/7/14
to
On Monday, April 7, 2014 2:28:10 PM UTC-5, TommyGoog wrote:
> On Friday, April 4, 2014 12:20:16 PM UTC-5, TommyGoog wrote:
>
> > ....The journey continues....

> In my next post, I will examine SYSTEM.STARTUP and begin re-engineering starting with the WIZBOOT main line.

> Are we there yet?

SYSTEM.STARTUP
Segment Procedures
0 WIZBOOT 5
1 UTILS 36
2 TITLELOA 8
3 OPTIONS 1

0 WIZBOOT
proc lex start end order-in-file hierarchy
1 0 7.0.1 50CC 50FF 2 7.0.1
2 6502 7.0.2 511A 52EA 3
3 6502 7.0.3 52F0 54B6 4
4 1 7.0.4 5000 50BA 1 7.0.4
5 6502 7.0.5 54BC 5642 5

I copied SYSTEM.STARTUP from the original Wizardry1 to a blank diskette and ran the DeCompiler and saved the output. I did the same for my STARTUP.CODE that is under construction. I compared the two using Windiff and noticed a lot of the code was the same, but most of the addresses on the left of each line were different. Therefore Windiff reported differences for most almost every line.

This is probably a good place to show a good use for the DeCompiler prompt:

SEGMENT'S START ADDR($5000):

It can be used to help make the output code for the "under construction" version to match more closely with the original. The reason that addresses are different at this point is because I don't have all the code written for the "under construction" version so the addresses relative to the segment load address are smaller than they will be when I have completed the "under construction" version. For example,

Original version:

FILE: 1 SEG: 1 PROC: 1

JTAB FOR SUBROUTINE 1:
DATA SIZE: 1538
PARAM SIZE: 0
EXIT AT: 6B77
ENTER AT: 6A32
PROC NUMBER: 1
LEXICAL LEVEL: 1
6A32 D7 NOP. NOP
6A33 A6 12 57 49 5A 41 52 44 52 59 20 55 54 49 4C 49 54 49 45 53
WIZARDRY UTILITIES
LSA. PUSH #(PC+1) POINTER TO THE STRING
6A47 CE 0F CLP. CALL CHILD PROCEDURE: 0F

Under Construction version:
FILE: 1 SEG: 1 PROC: 1

JTAB FOR SUBROUTINE 1:
DATA SIZE: 1536
PARAM SIZE: 0
EXIT AT: 63DB
ENTER AT: 62A2
PROC NUMBER: 1
LEXICAL LEVEL: 1
62A2 D7 NOP. NOP
62A3 A6 12 57 49 5A 41 52 44 52 59 20 55 54 49 4C 49 54 49 45 53
WIZARDRY UTILITIES
LSA. PUSH #(PC+1) POINTER TO THE STRING
62B7 CE 0F CLP. CALL CHILD PROCEDURE: 0F

The code matches at 6A32 in the original version with that at 62A3. Note the difference is $6A32 - $62A2 = $790. So now when the DeCompiler prompts for "SEGMENT'S START ADDR($5000):" we answer that with "5790" and can see the addresses are the same:

SEGMENT'S START ADDR($5000): 5790

THERE ARE 36 PROCEDURES.


ENTER PROCEDURE # (OR -1) 1


JTAB FOR SUBROUTINE 1:
DATA SIZE: 1536
PARAM SIZE: 0
EXIT AT: 6B6B
ENTER AT: 6A32
PROC NUMBER: 1
LEXICAL LEVEL: 1
6A32 D7 NOP. NOP
6A33 A6 12 57 49 5A 41 52 44 52 59 20 55 54 49 4C 49 54 49 45 53
WIZARDRY UTILITIES
LSA. PUSH #(PC+1) POINTER TO THE STRING
6A47 CE 0F CLP. CALL CHILD PROCEDURE: 0F


By the way, if you don't have something like Windiff, I've found that using Notepad can be used to detect differences in two text files under comparison. You open each ".txt" file in a separate Notepad and maximize both of them. Then you quickly use ALT-TAB to toggle between the two text files and use your eyes to detect any differences. This works great when most of the text is already identical but there might be a few differences. Use the "Page Down" key to advance each one and repeat. Sometimes one will have an extra line in it, so you just adjust that notepad window one line. Rinse and repeat.

A couple more side notes...

My EDIT.DSK can be used to edit or compile code, but not to link or assemble it. The disk COMPILE.DSK can be used to link or assemble code but not to edit.

The "(*$L PRINTER: *)" switch in the source code sends print to the printer when the code is compiled.

In looking at the code for P070001 (WIZBOOT mainline), it becomes clear that the code is something like the following:

STARTUP.TEXT
PROGRAM WIZBOOT;
SEGMENT PROCEDURE UTILS;
SEGMENT PROCEDURE TITLELOA;
SEGMENT PROCEDURE OPTIONS;

PROCEDURE P070002; (* 6502 code *)
PROCEDURE P070003; (* 6502 code *)
PROCEDURE P070004;

BEGIN (* WIZBOOT *)
CALL CHILD 4
CALL PROC 01 SEG 08
REPEAT
CALL PROC 01 SEG 09
50D9
CASE statement
CALL CHILD 4
EXIT PROCEDURE
CALL PROC 01 SEG 07
CALL PROC 01 SEG 08
50EE
UNTIL FALSE;
END.

Let's compare that to the LOL WIZUTIL code:

1230 1 1:0 0 BEGIN (* WIZUTIL *)
1231 1 1:1 0 WRITE( CHR( ESC) );
1232 1 1:1 13 WRITE( CHR( 21) );
1233 1 1:1 21 IF NOT CHKCOPY THEN
1234 1 1:2 28 BEGIN
1235 1 1:3 28 IF NOT CHKCOPY THEN
1236 1 1:4 35 REPEAT UNTIL FALSE
1237 1 1:2 35 END;
1238 1 1:1 38 SVSERIAL;
1239 1 1:1 40 REPEAT
1240 1 1:2 40 OPTIONS;
1241 1 1:2 43 CASE INCHAR OF
1242 1 1:2 46 'S': BEGIN
1243 1 1:4 46 SETCHAIN( 'WIZARDRY');
1244 1 1:4 60 EXIT( WIZBOOT);
1245 1 1:3 64 END;
1246 1 1:3 66
1247 1 1:2 66 'U': BEGIN
1248 1 1:4 66 REPEAT
1249 1 1:5 66 UTILS;
1250 1 1:5 69 IF BASE04 > 0 THEN
1251 1 1:6 74 MAKESCEN
1252 1 1:4 74 UNTIL BASE04 = 0
1253 1 1:3 78 END;
1254 1 1:2 84 END;
1255 1 1:1 98 UNTIL FALSE
1256 1 1:0 98 END.

I will note that in Wizardry1, the range from $53 to $55 on the case statement denotes options "S", "T", and "U".

Wizardry1, P010201 has a SETCHAIN("WIZARDRY"), and is entered by "CALL PROC 01 SEG 08" as shown in the DeCompiler listing.

"CHILD 4" looks like it might be something like "CHKCOPY".

"GLOBAL PROCEDURE: 03" might be "COPYPROT", because the code at 52F0 is definitely accessing the disk drive

5308- A2 60 LDX #$60
530A- BD 8A C0 LDA $C08A,X
530D- BD 89 C0 LDA $C089,X
5310- BD 8E C0 LDA $C08E,X
5313- BD 8C C0 LDA $C08C,X

And now let's just review how Wizardry I actually starts before getting to re-engineering the code.

When booting:

PREPARE YOURSELF
FOR THE ULTIMATE
IN FANTASY GAMES

Then,

Caldron, pipe player, smoke animation, and WIZARDRY logo with sword through it.

At some point there is a check for keypress, so press a key and:

COPYRIGHT @1981...
more legal stuff...
...
VERSION 2.1 of 22-JAN-82 SER: ??????
S)TART GAME U)TILITIES T)ITLE PAGE

[Note, since "SER: ??????" is displayed, clearly not all of my Wizardry disk matches the one at ASIMOV.]

So let's just take a quick stab at the code and see how we do:

CHKCOPY; (* as a PROCEDURE and not as a FUNCTION *)
TITLELOA; (* Load title *)
REPEAT
OPTIONS; (* Get a key *)
CASE INCHAR OF
'S': BEGIN
CHKCOPY; (* CHKCOPY might be bad name as it
does SETCHAIN('WIZARDRY') *)
EXIT( WIZBOOT)
END;
'U': BEGIN
UTILS
END;
'T': BEGIN
TITLELOA
END;
END
UNTIL FALSE


This actually turned out pretty good when I ran the Compiler and then the DeCompiler.
I noticed the DATA SIZE: was 14 instead of 12 (I think BASE04 needs to disappear.)
And I noticed the child procedure displayed by the DeCompiler was 03 and not 04, therefore I need to insert another 6502 External procedure.

Ok, I'm happy with WIZBOOT main line code.

I will tackle CHKCOPY in the next post.


TommyGoog

unread,
Apr 11, 2014, 2:12:32 PM4/11/14
to
> > >I will tackle CHKCOPY in the next post.

Maybe CHKCOPY from LOL will look similar to CHKCOPY for Wiz1.

CHKCOPY from LOL:

BEGIN
UNITREAD( DRIVE1, BUFFER, SIZEOF( BUFFER), SERIALBL, 0);
MOVELEFT( BUFFER, SERIAL, 7);
CHKCOPY := TRUE;
UNITREAD( DRIVE1, BUFFER, SIZEOF( BUFFER), 278, 0);
IF NOT COPYPROT THEN
BEGIN
CHKCOPY := COPYPROT
END
END;

The first part of LOL CHKCOPY is this:

5000 04 SLDC. PUSH #0004
5001 C6 03 LLA. PUSH #MP.03
5003 00 SLDC. PUSH #0000
5004 C7 00 02 LDCI. PUSH #0200
5007 05 SLDC. PUSH #0005
5008 00 SLDC. PUSH #0000
5009 9E 05 READ FROM VOL#

The first part of CHKCOPY( P050003) from Wiz1:

5000 04 SLDC. PUSH #0004
5001 C6 0A LLA. PUSH #MP.0A
5003 00 SLDC. PUSH #0000
5004 C7 00 02 LDCI. PUSH #0200
5007 05 SLDC. PUSH #0005
5008 00 SLDC. PUSH #0000
5009 9E 05 READ FROM VOL#

Clearly this code is generated by a UNITREAD and is similar to LOL. In Wiz1, the buffer is #MP.0A (not #MP.01). This means we need more variables declared before BUFFER in Wiz1. SERIALBL (#0005) is the block on the disk being read. Normally that block is part of a normal PASCAL directory, but for Wizardry it holds the Wizardry "SER: xxxxxx" identifier.

Since SVSERIAL code does not seem to be used, I will remove it for Wiz1.

I insert MP01, MP02, ..., MP05 as INTEGERs into CHKCOPY, and MP06 as ARRAY[ 0..3] OF INTEGER.

The first instruction is decompiled as:

UNITREAD( DRIVE1, BUFFER, SIZEOF( BUFFER), SERIALBL, 0);

The next pcode is:

500B C6 0A LLA. PUSH #MP.0A
500D 00 SLDC. PUSH #0000
500E A5 05 LA0. PUSH #BASE.05
5010 00 SLDC. PUSH #0000
5011 07 SLDC. PUSH #0007
5012 9E 02 MVL. MOVELEFT
5014 1F SLDC. PUSH #001F
5015 CC 04 STL. MP.04 := (TOS)

This converts to:

MOVELEFT( BUFFER, SERIAL, 7);
MP04 := 31;

The next piece of code is a FOR construct:

5017 0A SLDC. PUSH #000A
5018 CC 03 STL. MP.03 := (TOS)
501A 0D SLDC. PUSH #000D
501B CC 81 0A STL. MP.010A := (TOS)
501E DA SLDL. PUSH MP.03
501F CA 81 0A LDL. PUSH MP.010A
5022 C8 LEQI. PUSH ((TOS-1) <= (TOS))
5023 A1 27 UJP. IF NOT (TOS) THEN JUMP TO 504C

5045 DA SLDL. PUSH MP.03
5046 01 SLDC. PUSH #0001
5047 82 ADI. PUSH ((TOS) + (TOS-1))
5048 CC 03 STL. MP.03 := (TOS)
504A B9 F6 UJP. JUMP TO 501E

So let's put it in:

FOR MP03 := 10 to 13 DO
BEGIN
END;

Note the variable MP.010A is automatically generated by the compiler as the FOR loop termination variable. You will see MP.010A re-used later in the code for another FOR loop following this one.

The first instruction in the FOR loop is a MOVELEFT instruction:

5025 C6 0A LLA. PUSH #MP.0A
5027 DB SLDL. PUSH MP.04
5028 C6 06 LLA. PUSH #MP.06
502A DA SLDL. PUSH MP.03
502B 0A SLDC. PUSH #000A
502C 95 SBI. PUSH ((TOS-1) - (TOS))
502D A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
502F 00 SLDC. PUSH #0000
5030 02 SLDC. PUSH #0002
5031 9E 02 MVL. MOVELEFT

Decompiled it is:

MOVELEFT( MP0A[MP04], MP06[MP03-10], 2);

Note, MP0A is a PACKED ARRAY of CHAR. The pcode had me confused at first into thinking there were 4 parameters passed to MOVELEFT, but this is the correct PASCAL code to generate the pcode.

The next sequence of pcode looks intimidating at first. Here it is:

5033 DB SLDL. PUSH MP.04
5034 02 SLDC. PUSH #0002
5035 C6 06 LLA. PUSH #MP.06
5037 DA SLDL. PUSH MP.03
5038 0A SLDC. PUSH #000A
5039 95 SBI. PUSH ((TOS-1) - (TOS))
503A A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
503C F8 SIND. PUSH (TOS)^.0
503D 0D SLDC. PUSH #000D
503E 8E MODI. PUSH ((TOS-1) MOD (TOS))
503F 8F MPI. PUSH ((TOS-1) * (TOS))
5040 82 ADI. PUSH ((TOS) + (TOS-1))
5041 05 SLDC. PUSH #0005
5042 82 ADI. PUSH ((TOS) + (TOS-1))
5043 CC 04 STL. MP.04 := (TOS)

De-Compiled it is:

MP04 := MP04 + 2 * ((MP06[MP03 - 10]) MOD 13) + 5;

This instruction is also within the FOR loop.

This is what the code looks like so far, and I will often compile a PROCEDURE or FUNCTION before it is complete to make sure I am on the right track:


966 1 2:D 3 FUNCTION COPYPROT : BOOLEAN; EXTERNAL; (* P050002 *)
967 1 2:D 3
968 1 2:D 3
969 1 3:D 1 PROCEDURE CHKCOPY; (* P050003 *)
970 1 3:D 1
971 1 3:D 1 VAR
972 1 3:D 1 MP01 : INTEGER;
973 1 3:D 2 MP02 : INTEGER;
974 1 3:D 3 MP03 : INTEGER;
975 1 3:D 4 MP04 : INTEGER;
976 1 3:D 5 MP05 : INTEGER;
977 1 3:D 6 MP06 : ARRAY[0..3] OF INTEGER;
978 1 3:D 10 BUFFER : PACKED ARRAY[ TBLOCKRG] OF CHAR;
979 1 3:D 266
980 1 3:0 0 BEGIN
981 1 3:1 0 UNITREAD( DRIVE1, BUFFER, SIZEOF( BUFFER), SERIALBL, 0);
982 1 3:1 11 MOVELEFT( BUFFER, SERIAL, 7);
983 1 3:1 20 MP04 := 31;
984 1 3:1 23 FOR MP03 := 10 TO 13 DO
985 1 3:2 37 BEGIN
986 1 3:3 37 MOVELEFT( BUFFER[ MP04], MP06[ MP03 - 10], 2);
987 1 3:3 51 MP04 := MP04 + 2 * ((MP06[MP03 - 10]) MOD 13) + 5;
988 1 3:2 69 END;


After the entire routine is completed (and maybe a lot later) I will clean up the variables to something meaningful.

Here is the pcode for the rest of CHKCOPY:

504C 01 SLDC. PUSH #0001
504D CC 02 STL. MP.02 := (TOS)
504F 05 SLDC. PUSH #0005
5050 CC 81 0A STL. MP.010A := (TOS)
5053 D9 SLDL. PUSH MP.02
5054 CA 81 0A LDL. PUSH MP.010A
5057 C8 LEQI. PUSH ((TOS-1) <= (TOS))
5058 A1 5E UJP. IF NOT (TOS) THEN JUMP TO 50B8
505A 01 SLDC. PUSH #0001
505B CC 05 STL. MP.05 := (TOS)
505D 0A SLDC. PUSH #000A
505E CC 03 STL. MP.03 := (TOS)
5060 0D SLDC. PUSH #000D
5061 CC 81 0B STL. MP.010B := (TOS)
5064 DA SLDL. PUSH MP.03
5065 CA 81 0B LDL. PUSH MP.010B
5068 C8 LEQI. PUSH ((TOS-1) <= (TOS))
5069 A1 3F UJP. IF NOT (TOS) THEN JUMP TO 50AA
506B 04 SLDC. PUSH #0004
506C C6 0A LLA. PUSH #MP.0A
506E 00 SLDC. PUSH #0000
506F C7 00 02 LDCI. PUSH #0200
5072 08 SLDC. PUSH #0008
5073 DA SLDL. PUSH MP.03
5074 8F MPI. PUSH ((TOS-1) * (TOS))
5075 00 SLDC. PUSH #0000
5076 9E 05 READ FROM VOL#
5078 C6 04 LLA. PUSH #MP.04
507A CF 03 CGP. CALL GLOBAL PROCEDURE: 03
507C DA SLDL. PUSH MP.03
507D 0A SLDC. PUSH #000A
507E C3 EQUI. PUSH ((TOS-1) = (TOS))
507F A1 0C UJP. IF NOT (TOS) THEN JUMP TO 508D
5081 DB SLDL. PUSH MP.04
5082 C6 06 LLA. PUSH #MP.06
5084 0A SLDC. PUSH #000A
5085 0A SLDC. PUSH #000A
5086 95 SBI. PUSH ((TOS-1) - (TOS))
5087 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
5089 F8 SIND. PUSH (TOS)^.0
508A 95 SBI. PUSH ((TOS-1) - (TOS))
508B CC 01 STL. MP.01 := (TOS)
508D DB SLDL. PUSH MP.04
508E D8 SLDL. PUSH MP.01
508F 95 SBI. PUSH ((TOS-1) - (TOS))
5090 CC 04 STL. MP.04 := (TOS)
5092 DC SLDL. PUSH MP.05
5093 DB SLDL. PUSH MP.04
5094 C6 06 LLA. PUSH #MP.06
5096 DA SLDL. PUSH MP.03
5097 0A SLDC. PUSH #000A
5098 95 SBI. PUSH ((TOS-1) - (TOS))
5099 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
509B F8 SIND. PUSH (TOS)^.0
509C 95 SBI. PUSH ((TOS-1) - (TOS))
509D 80 ABI. PUSH ABS( (TOS) ) )
509E 23 SLDC. PUSH #0023
509F C9 LESI. PUSH ((TOS-1) < (TOS))
50A0 84 LAND. PUSH ((TOS-1) AND (TOS))
50A1 CC 05 STL. MP.05 := (TOS)
50A3 DA SLDL. PUSH MP.03
50A4 01 SLDC. PUSH #0001
50A5 82 ADI. PUSH ((TOS) + (TOS-1))
50A6 CC 03 STL. MP.03 := (TOS)
50A8 B9 F4 UJP. JUMP TO 5064
50AA DC SLDL. PUSH MP.05
50AB A1 04 UJP. IF NOT (TOS) THEN JUMP TO 50B1
50AD 01 SLDC. PUSH #0001
50AE 04 SLDC. PUSH #0004
50AF 9E 04 EXIT. EXIT FROM PROCEDURE. (TOS)=PROC# (TOS-1)=SEG#
50B1 D9 SLDL. PUSH MP.02
50B2 01 SLDC. PUSH #0001
50B3 82 ADI. PUSH ((TOS) + (TOS-1))
50B4 CC 02 STL. MP.02 := (TOS)
50B6 B9 F2 UJP. JUMP TO 5053
50B8 9E 27 AN UNKNOWN STANDARD PROCEDURE ?!?!
50BA AD 00 RNP. RETURN FROM NON-BASE PROCEDURE.

Here is the entire decompiled listing:

PROCEDURE CHKCOPY; (* P070004 *)

VAR
MP01 : INTEGER;
MP02 : INTEGER;
MP03 : INTEGER;
MP04 : INTEGER;
MP05 : BOOLEAN;
MP06 : ARRAY[0..3] OF INTEGER;
BUFFER : PACKED ARRAY[ TBLOCKRG] OF CHAR;

BEGIN
UNITREAD( DRIVE1, BUFFER, SIZEOF( BUFFER), SERIALBL, 0);
MOVELEFT( BUFFER, SERIAL, 7);
MP04 := 31;
FOR MP03 := 10 TO 13 DO
BEGIN
MOVELEFT( BUFFER[ MP04], MP06[ MP03 - 10], 2);
MP04 := MP04 + 2 * ((MP06[MP03 - 10]) MOD 13) + 5;
END;
FOR MP02 := 1 TO 5 DO
BEGIN
MP05 := TRUE;
FOR MP03 := 10 TO 13 DO
BEGIN
UNITREAD( DRIVE1, BUFFER, SIZEOF( BUFFER), 8 * MP03, 0);
P070003( MP04); (* CALL GLOBAL PROCEDURE: 03 *)
IF MP03 = 10 THEN
BEGIN
MP01 := MP04 - MP06[ 10 - 10];
END;
MP04 := MP04 - MP01;
MP05 :=MP05 AND (ABS((MP04 - MP06[ MP03 - 10])) < 35);
END;
IF MP05 THEN
BEGIN
EXIT( CHKCOPY);
END;
END;
HALT;
END;


Nothing too remarkable in the rest of that code conversion. You must determine that "CALL GLOBAL PROCEDURE: 03" refers to P070003 and passes MP04.

Also note the sequence of pcode at 5084:

5084 0A SLDC. PUSH #000A
5085 0A SLDC. PUSH #000A
5086 95 SBI. PUSH ((TOS-1) - (TOS))

It looks a bit odd, and the decompiled code I wrote does generate that pcode:

MP01 := MP04 - MP06[ 10 - 10];

Certainly the Wizardry programmers did not write something quite like that ("10 - 10"). I seem to remember sequences like this when doing LOL, and I *think* it has something to do with SCALAR defined constants or subranges, or perhaps something about the "ORD()" function.

I now inserted:

PROCEDURE P070005; EXTERNAL;

following P070004 (CHKCOPY). It needs to be placed there to have the correct number assigned to it by the compiler.

At first I inserted P07003 as this:

PROCEDURE P07003( MP01: INTEGER); EXTERNAL:

It generated the following pcode:

5078 DB SLDL. PUSH MP.04
5079 CF 03 CGP. CALL GLOBAL PROCEDURE: 03

But we really wanted:

5078 C6 04 LLA. PUSH #MP.04
507A CF 03 CGP. CALL GLOBAL PROCEDURE: 03

Therefor the parameter needs to be passed by REFERENCE and not by VALUE. (Put "VAR" before MP01 in declaration.)

I found that the "UNKNOWN" for "9E 27" is the PASCAL "HALT" instruction.

A lot of this code is really confusing to try to understand. I think I looked at it 2.5 years ago. To understand it you need to see at least the sector with the serial number, so here it is (using COPY][+):

00- 06 33 39 31 30 39 30 00 F391090@
08- 00 00 00 01 88 00 00 00 @@@A.@@@
10- 00 00 00 00 00 00 00 00 @@@@@@@@
18- 00 00 00 00 00 00 00 16 @@@@@@@V
20- 12 00 00 00 F0 0C D4 0F R@@@pLTO
28- C7 09 64 16 47 09 47 05 GI$VGIGE
30- 64 16 47 05 F3 06 ED 07 $VGEsFmG
38- 0F 06 12 15 12 31 12 00 OFRUR1R@
40- E5 02 B9 08 12 4B 12 79 eB9HRKR9
48- C6 05 31 13 12 78 17 1B FE1SR8W[
50- 12 06 AB 08 EA 05 12 12 RF+HjERR
58- EE 02 EC 0C 00 00 1C 13 nBlL@@\S
60- 00 12 BE 05 1C 13 E8 05 @R>E\ShE
68- B5 05 00 00 16 09 00 00 5E@@VI@@
70- 00 00 00 00 00 00 00 00 @@@@@@@@
78- 00 00 00 00 00 00 00 00 @@@@@@@@
80- 00 00 00 00 00 00 00 00 @@@@@@@@
88- 00 00 00 00 00 00 00 00 @@@@@@@@
90- 00 00 00 00 00 00 00 00 @@@@@@@@
98- 00 00 00 00 00 00 00 00 @@@@@@@@
A0- 00 00 00 00 00 00 00 00 @@@@@@@@
A8- 00 00 00 00 00 00 00 00 @@@@@@@@
B0- 00 00 00 00 00 00 00 00 @@@@@@@@
B8- 00 00 00 00 00 00 00 00 @@@@@@@@
C0- 00 00 00 00 00 00 00 00 @@@@@@@@
C8- 00 00 00 00 00 00 00 00 @@@@@@@@
D0- 00 00 00 00 00 00 00 00 @@@@@@@@
D8- 00 00 00 00 00 00 00 00 @@@@@@@@
E0- 00 00 00 00 00 00 00 00 @@@@@@@@
E8- 00 00 00 00 00 00 00 00 @@@@@@@@
F0- 00 00 00 00 00 00 00 00 @@@@@@@@
F8- 00 00 00 00 00 00 00 00 @@@@@@@@

Note that MP04 := 31 is looking at $1F. Also note the serial number at the beginning of this sector. This came from my "box" set of Wizardry. The Serial# is: 391090.

One other thing I feel I must mention is the "EXIT" instruction. This is used here (and in LOL) and I think it is generally a bad idea to use this construct. In this routine, EXIT is the "normal" way to return to the caller. YUCK!

Next up is the procedure P070003 which is 6502 assembly code. I need to relearn a bunch more stuff before tackling that.

TommyGoog

unread,
Apr 12, 2014, 4:58:27 PM4/12/14
to

> Next up is the procedure P070003 which is 6502 assembly code. I need to relearn a bunch more stuff before tackling that.

SEGMENT: Procedures:
0 WIZBOOT 5
1 UTILS 36
2 TITLELOA 8
3 OPTIONS 1

WIZBOOT lex Start Exit Order Hierarchy
1 0 50CC 50FF 2 7.0.1
2 6502 code 511A 52EA 3
3 6502 code 52F0 54B6 4
4 1 5000 50BA 1 7.0.4
5 6502 code 54BC 5642 5

There are 3 PROCEDUREs/FUNCTIONs in SEGMENT WIZBOOT that are 6502 code (written in assembler).

I mentioned in an earlier post how to get an Apple "monitor" disassembly for Pascal 6502 procedures.

P070003
52F0- 68 PLA
52F1- 85 00 STA $00
52F3- 68 PLA
52F4- 85 01 STA $01
52F6- 68 PLA
52F7- 85 02 STA $02
52F9- 68 PLA
52FA- 85 03 STA $03
52FC- A5 01 LDA $01
52FE- 48 PHA
52FF- A5 00 LDA $00
5301- 48 PHA
5302- A9 00 LDA #$00
5304- 85 0D STA $0D
5306- 85 0E STA $0E
5308- A2 60 LDX #$60
530A- BD 8A C0 LDA $C08A,X
530D- BD 89 C0 LDA $C089,X
5310- BD 8E C0 LDA $C08E,X
5313- BD 8C C0 LDA $C08C,X
5316- 10 FB BPL $5313
5318- C9 FF CMP #$FF
531A- D0 F7 BNE $5313
531C- BD 8C C0 LDA $C08C,X
531F- 10 FB BPL $531C
5321- C9 FF CMP #$FF
5323- D0 EE BNE $5313
5325- BD 8C C0 LDA $C08C,X
5328- 10 FB BPL $5325
532A- C9 FF CMP #$FF
532C- D0 03 BNE $5331
532E- 4C 35 00 JMP $0035
5331- BD 8C C0 LDA $C08C,X
5334- 10 FB BPL $5331
5336- C9 D5 CMP #$D5
5338- D0 F7 BNE $5331
533A- BD 8C C0 LDA $C08C,X
533D- 10 FB BPL $533A
533F- C9 AA CMP #$AA
5341- D0 EE BNE $5331
5343- BD 8C C0 LDA $C08C,X
5346- 10 FB BPL $5343
5348- C9 96 CMP #$96
534A- D0 E5 BNE $5331
534C- BD 8C C0 LDA $C08C,X
534F- 10 FB BPL $534C
5351- EA NOP
5352- EA NOP
5353- EA NOP
5354- EA NOP
5355- EA NOP
5356- BD 8C C0 LDA $C08C,X
5359- 10 FB BPL $5356
535B- EA NOP
535C- EA NOP
535D- EA NOP
535E- EA NOP
535F- EA NOP
5360- BD 8C C0 LDA $C08C,X
5363- 10 FB BPL $5360
5365- EA NOP
5366- EA NOP
5367- EA NOP
5368- EA NOP
5369- EA NOP
536A- BD 8C C0 LDA $C08C,X
536D- 10 FB BPL $536A
536F- EA NOP
5370- EA NOP
5371- EA NOP
5372- EA NOP
5373- EA NOP
5374- BD 8C C0 LDA $C08C,X
5377- 10 FB BPL $5374
5379- A8 TAY
537A- EA NOP
537B- EA NOP
537C- EA NOP
537D- EA NOP
537E- EA NOP
537F- BD 8C C0 LDA $C08C,X
5382- 10 FB BPL $537F
5384- 85 04 STA $04
5386- 98 TYA
5387- 38 SEC
5388- 2A ROL
5389- 25 04 AND $04
538B- C9 00 CMP #$00
538D- D0 84 BNE $5313
538F- 20 1B 01 JSR $011B
5392- BD 8C C0 LDA $C08C,X
5395- 10 FB BPL $5392
5397- C9 D5 CMP #$D5
5399- F0 09 BEQ $53A4
539B- E6 0D INC $0D
539D- D0 F3 BNE $5392
539F- E6 0E INC $0E
53A1- 4C A2 00 JMP $00A2
53A4- BD 8C C0 LDA $C08C,X
53A7- 10 FB BPL $53A4
53A9- C9 AA CMP #$AA
53AB- D0 E5 BNE $5392
53AD- BD 8C C0 LDA $C08C,X
53B0- 10 FB BPL $53AD
53B2- C9 96 CMP #$96
53B4- D0 DC BNE $5392
53B6- BD 8C C0 LDA $C08C,X
53B9- 10 FB BPL $53B6
53BB- EA NOP
53BC- EA NOP
53BD- EA NOP
53BE- EA NOP
53BF- EA NOP
53C0- BD 8C C0 LDA $C08C,X
53C3- 10 FB BPL $53C0
53C5- EA NOP
53C6- EA NOP
53C7- EA NOP
53C8- EA NOP
53C9- EA NOP
53CA- BD 8C C0 LDA $C08C,X
53CD- 10 FB BPL $53CA
53CF- EA NOP
53D0- EA NOP
53D1- EA NOP
53D2- EA NOP
53D3- EA NOP
53D4- BD 8C C0 LDA $C08C,X
53D7- 10 FB BPL $53D4
53D9- EA NOP
53DA- EA NOP
53DB- EA NOP
53DC- EA NOP
53DD- EA NOP
53DE- BD 8C C0 LDA $C08C,X
53E1- 10 FB BPL $53DE
53E3- A8 TAY
53E4- EA NOP
53E5- EA NOP
53E6- EA NOP
53E7- EA NOP
53E8- EA NOP
53E9- BD 8C C0 LDA $C08C,X
53EC- 10 FB BPL $53E9
53EE- 85 04 STA $04
53F0- 98 TYA
53F1- 38 SEC
53F2- 2A ROL
53F3- 25 04 AND $04
53F5- C9 00 CMP #$00
53F7- F0 03 BEQ $53FC
53F9- 4C A2 00 JMP $00A2
53FC- A0 00 LDY #$00
53FE- A5 0D LDA $0D
5400- 91 02 STA ($02),Y
5402- C8 INY
5403- A5 0E LDA $0E
5405- 91 02 STA ($02),Y
5407- BD 88 C0 LDA $C088,X
540A- 60 RTS

540B- 86 06 STX $06
540D- A0 0C LDY #$0C
540F- 84 07 STY $07
5411- 88 DEY
5412- 88 DEY
5413- 84 08 STY $08
5415- A9 EF LDA #$EF
5417- 85 0B STA $0B
5419- A9 D8 LDA #$D8
541B- 85 0C STA $0C
541D- A9 00 LDA #$00
541F- 85 09 STA $09
5421- A5 08 LDA $08
5423- 85 0A STA $0A
5425- 38 SEC
5426- E5 07 SBC $07
5428- F0 31 BEQ $545B
542A- B0 06 BCS $5432
542C- 49 FF EOR #$FF
542E- E6 08 INC $08
5430- 90 04 BCC $5436
5432- 69 FE ADC #$FE
5434- C6 08 DEC $08
5436- C5 09 CMP $09
5438- 90 02 BCC $543C
543A- A5 09 LDA $09
543C- C9 0C CMP #$0C
543E- B0 01 BCS $5441
5440- A8 TAY
5441- 38 SEC
5442- 20 6F 01 JSR $016F
5445- B9 91 01 LDA $0191,Y
5448- 20 80 01 JSR $0180
544B- A5 0A LDA $0A
544D- 18 CLC
544E- 20 71 01 JSR $0171
5451- B9 9D 01 LDA $019D,Y
5454- 20 80 01 JSR $0180
5457- E6 09 INC $09
5459- D0 C6 BNE $5421
545B- 20 80 01 JSR $0180
545E- 18 CLC
545F- A5 08 LDA $08
5461- 29 03 AND #$03
5463- 2A ROL
5464- 05 06 ORA $06
5466- AA TAX
5467- BD 80 C0 LDA $C080,X
546A- A6 06 LDX $06
546C- 60 RTS

546D- AA TAX
546E- A0 A0 LDY #$A0
5470- A2 11 LDX #$11
5472- CA DEX
5473- D0 FD BNE $5472
5475- E6 0B INC $0B
5477- D0 02 BNE $547B
5479- E6 0C INC $0C
547B- 38 SEC
547C- E9 01 SBC #$01
547E- D0 F0 BNE $5470
5480- 60 RTS

5481- 01 30 ORA ($30,X)
5483- 28 PLP
5484- 20 20 1E JSR $1E20
5487- 1D 1C 1C ORA $1C1C,X
548A- 1C ???
548B- 1C ???
548C- 1C ???
548D- 70 2C BVS $54BB
548F- 26 22 ROL $22
5491- 1F ???
5492- 1E 1D 1C ASL $1C1D,X
5495- 1C ???
5496- 1C ???
5497- 1C ???
5498- 1C ???
5499- 00 BRK
549A- 00 BRK
549B- 00 BRK
549C- 6D 01 0E ADC $0E01
549F- 01 FE ORA ($FE,X)
54A1- 00 BRK
54A2- A8 TAY
54A3- 00 BRK
54A4- 61 00 ADC ($00,X)
54A6- 60 RTS
54A7- 00 BRK
54A8- 5F ???
54A9- 00 BRK
54AA- 5B ???
54AB- 00 BRK
54AC- 5A ???
54AD- 00 BRK
54AE- 59 00 54 EOR $5400,Y
54B1- 00 BRK
54B2- 0B ???
54B3- 00 BRK
54B4- 00 BRK
54B5- 00 BRK
54B6- 00 BRK
54B7- 00 BRK
54B8- C8 INY
54B9- 01 00 ORA ($00,X)
54BB- 00 BRK

This code as loaded at $511A is the code from the Wizardry1 diskette. Note though that it is not yet ready for execution. The Assembler, Linker, and runtime Segment Loader need to coordinate a few things. The Segment Loader can load the segment at different locations in memory. One time it might load it at $5000, and another time at $5502. Therefore a JMP instruction cannot have the same destination address in both places if the JMP is to a location somewhere else in this code.

The Assembler updates the JTAB "Optional Jump Table" for this procedure. (See Apple Pascal Operating System, Operation of P-Machine, P 253). When the Segment Loader loads the segment, it goes through this Jump Table and alters the JMP (and JSR) instructions.

Let's look at an example from the code above for P070003:

545B- 20 80 01 JSR $0180

The JTAB begins at 54BB and is "upside down" as described in the manual.

Also, 2 consecutive addresses are generally grouped in pairs forming a 16 bit value. The lower address of the pair is considered the address of that table entry, and the lower address contains the least significant bits of the 16 bit value ($54B8 is the address with a value of $01C8).

54BB 0
54BA 0 JTAB
54B9 1
54B8 C8 Enter IC
54B7 0
54B6 0
54B5 0
54B4 0
54B3 0
54B2 0B Number of JMP entries in table
54B1 0
54B0 54
54AF 0
54AE 59

Before I get too far, a word about those pointers. They are self-relative pointers. You take the value that is stored there, and subtract it from its address to get the ABSOLUTE address. For example, the Enter IC is at $54B8 and it has the value $01C8. When this segment is loaded at $5000, this is therefore referring to $52F0 ($54B8 - $01C8).

Another example, $54B0 - $0054 = $545C, and we find a JSR instruction there:

545B- 20 80 01 JSR $0180

Ok, so now we see $0180 as the destination. That is a relative pointer using the beginning of the procedure. $5470 ($52F0 + $0180).

For starters we can call the label "L0180, and have JSR L0180.

If there is a data table in the procedure, then the references to it will also need to be ABSOLUTIZED (resolved is probably the proper term to use).

5445- B9 91 01 LDA $0191,Y

$52F0 + $0191 = $5481

Therefore this is " LDA L0191,Y" and the table at $5481 has the label L0191.

Ok, so now we can convert this to source code, but we note that Apple Pascal does have a few differences:

All number must begin with 0 through 9, so "$C08C" must be written as "0C08C".

Some instructions need the operand. ROL must be written as "ROL A".

STA ($02),Y becomes STA @02,Y

I had some problems during my first attempts at Assembling the code, that I thought I'd share with you so that you do not make the same mistakes.

A(ssemble
Assemble what text? #11:P070003
To what codefile? #11:P070003
Output file for assembled listing: #11:P070003.OUT
"bad title, illegal file name"

Don't give the file for output an extension.
And if you try P070003 with no extension you will not be happy. It will overwrite your source file!!

Output file for assembled listing: #11:P07OUT
"no room, insufficient space on disk"

But this is my current disk usage:

#4: 194 unused
#5: 38 unused
#11: 194 unused
#12: 160 unused

Ok, let's try putting the output listing on a different disk:

Output file for assembled listing: #12:POUT
...
Assembly complete: 38 lines
0 Errors flagged on this Assembly

Ok, that worked.

Here is an alternate way of fixing the problem:
Put "size" for Code file:

To what codefile? #11:p070003.CODE[10]
Output file for assembled listing: #11:pout
...
Assembly complete: 38 lines
0 Errors flagged on this Assembly

Now its time to Link P070003.CODE into STARTUP.CODE

L(inking
Host file? #12:STARTUP
Libfile? #11:P070003.CODE
Reading WIZBOOT
Reading P070003
Output file? #11:STARTUP.CODE

Linking UTILS #7
Linking TITLELOA #8
Linking OPTIONS #9
Linking WIZBOOT #1
Proc P070005 undefined
Func COPYPROT undefined

Since there were errors, no .CODE was produced. Therefore, make a dummy P070005 and dummy COPYPROT.

Host file? #12:STARTUP
Libfile?
#11:P070003.CODE
#11:P070005.CODE
#11:COPYPROT.CODE
Output file? #11:STARTUP

In looking at the DeCompiled code for this STARTUP.CODE, I noticed that PROCEDURE 03 started at a smaller address than $52F0, therefore I need to put more data in PROCEDURE 02. Also worth noting is that the order you enter Lib Files is important.

Libfile?
#11:COPYPROT.CODE
#11:P070003.CODE
#11:P070005.CODE

Here is the completed rough draft for P070003

0000| .PROC P070003,1 ; 1 PARAMETER
Current memory available: 8644
0000| 68 PLA
0001| 85 00 STA 00
0003| 68 PLA
0004| 85 01 STA 01
0006| 68 PLA
0007| 85 02 STA 02
0009| 68 PLA
000A| 85 03 STA 03
000C| A5 01 LDA 01
000E| 48 PHA
000F| A5 00 LDA 00
0011| 48 PHA
0012| A9 00 LDA #0
0014| 85 0D STA 0D
0016| 85 0E STA 0E
0018| A2 60 LDX #060
001A| BD 8AC0 LDA 0C08A,X
001D| BD 89C0 LDA 0C089,X
0020| BD 8EC0 LDA 0C08E,X
0023| L5313
0023| BD 8CC0 LDA 0C08C,X
0026| 10FB BPL L5313
0028| C9 FF CMP #0FF
002A| D0F7 BNE L5313
002C| L531C
002C| BD 8CC0 LDA 0C08C,X
002F| 10FB BPL L531C
0031| C9 FF CMP #0FF
0033| D0EE BNE L5313
0035| L0035
0035| BD 8CC0 LDA 0C08C,X
0038| 10FB BPL L0035
003A| C9 FF CMP #0FF
003C| D0** BNE L5331
003E| 4C 3500 JMP L0035
003C* 03
0041| L5331
0041| BD 8CC0 LDA 0C08C,X
0044| 10FB BPL L5331
0046| C9 D5 CMP#0D5
0048| D0F7 BNE L5331
004A| L533A
004A| BD 8CC0 LDA 0C08C,X
004D| 10FB BPL L533A
004F| C9 AA CMP #0AA
0051| D0EE BNE L5331
0053| L5343
0053| BD 8CC0 LDA 0C08C,X
0056| 10FB BPL L5343
0058| C9 96 CMP #096
005A| D0E5 BNE L5331
005C| L534C
005C| BD 8CC0 LDA 0C08C,X
PAGE - 2 P070003 FILE:


005F| 10FB BPL L534C
0061| EA NOP
0062| EA NOP
0063| EA NOP
0064| EA NOP
0065| EA NOP
0066| L5356
0066| BD 8CC0 LDA 0C08C,X
0069| 10FB BPL L5356
006B| EA NOP
006C| EA NOP
006D| EA NOP
006E| EA NOP
006F| EA NOP
0070| L5360
0070| BD 8CC0 LDA 0C08C,X
0073| 10FB BPL L5360
0075| EA NOP
0076| EA NOP
0077| EA NOP
0078| EA NOP
0079| EA NOP
007A| L536A
007A| BD 8CC0 LDA 0C08C,X
007D| 10FB BPL L536A
007F| EA NOP
0080| EA NOP
0081| EA NOP
0082| EA NOP
0083| EA NOP
0084| L5374
0084| BD 8CC0 LDA 0C08C,X
0087| 10FB BPL L5374
0089| A8 TAY
008A| EA NOP
008B| EA NOP
008C| EA NOP
008D| EA NOP
008E| EA NOP
008F| L537F
008F| BD 8CC0 LDA 0C08C,X
0092| 10FB BPL L537F
0094| 85 04 STA 04
0096| 98 TYA
0097| 38 SEC
0098| 2A ROL A
0099| 25 04 AND 04
009B| C9 00 CMP #00
009D| D084 BNE L5313
009F| 20 **** JSR L011B
00A2| L00A2
00A2| L5392
00A2| BD 8CC0 LDA 0C08C,X
00A5| 10FB BPL L5392
00A7| C9 D5 CMP #0D5
PAGE - 3 P070003 FILE:


00A9| F0** BEQ L53A4
00AB| E6 0D INC 0D
00AD| D0F3 BNE L5392
00AF| E6 0E INC 0E
00B1| 4C A200 JMP L00A2
00A9* 09
00B4| L53A4
00B4| BD 8CC0 LDA 0C08C,X
00B7| 10FB BPL L53A4
00B9| C9 AA CMP #0AA
00BB| D0E5 BNE L5392
00BD| L53AD
00BD| BD 8CC0 LDA 0C08C,X
00C0| 10FB BPL L53AD
00C2| C9 96 CMP #096
00C4| D0DC BNE L5392
00C6| L53B6
00C6| BD 8CC0 LDA 0C08C,X
00C9| 10FB BPL L53B6
00CB| EA NOP
00CC| EA NOP
00CD| EA NOP
00CE| EA NOP
00CF| EA NOP
00D0| L53C0
00D0| BD 8CC0 LDA 0C08C,X
00D3| 10FB BPL L53C0
00D5| EA NOP
00D6| EA NOP
00D7| EA NOP
00D8| EA NOP
00D9| EA NOP
00DA| L53CA
00DA| BD 8CC0 LDA 0C08C,X
00DD| 10FB BPL L53CA
00DF| EA NOP
00E0| EA NOP
00E1| EA NOP
00E2| EA NOP
00E3| EA NOP
00E4| L53D4
00E4| BD 8CC0 LDA 0C08C,X
00E7| 10FB BPL L53D4
00E9| EA NOP
00EA| EA NOP
00EB| EA NOP
00EC| EA NOP
00ED| EA NOP
00EE| L53DE
00EE| BD 8CC0 LDA 0C08C,X
00F1| 10FB BPL L53DE
00F3| A8 TAY
00F4| EA NOP
00F5| EA NOP
00F6| EA NOP
PAGE - 4 P070003 FILE:


00F7| EA NOP
00F8| EA NOP
00F9| L53E9
00F9| BD 8CC0 LDA 0C08C,X
00FC| 10FB BPL L53E9
00FE| 85 04 STA 04
0100| 98 TYA
0101| 38 SEC
0102| 2A ROL A
0103| 25 04 AND 04
0105| C9 00 CMP #0
0107| F0** BEQ L53FC
0109| 4C A200 JMP L00A2
0107* 03
010C| L53FC
010C| A0 00 LDY #0
010E| A5 0D LDA 0D
0110| 91 02 STA @02,Y
0112| C8 INY
0113| A5 0E LDA 0E
0115| 91 02 STA @02,Y
0117| BD 88C0 LDA 0C088,X
011A| 60 RTS
011B| ;
00A0* 1B01
011B| L011B
011B| 86 06 STX 06
011D| A0 0C LDY #0C
011F| 84 07 STY 07
0121| 88 DEY
0122| 88 DEY
0123| 84 08 STY 08
0125| A9 EF LDA #0EF
0127| 85 0B STA 0B
0129| A9 D8 LDA #0D8
012B| 85 0C STA 0C
012D| A9 00 LDA #0
012F| 85 09 STA 09
0131| L5421
0131| A5 08 LDA 08
0133| 85 0A STA 0A
0135| 38 SEC
0136| E5 07 SBC 07
0138| F0** BEQ L545B
013A| B0** BCS L5432
013C| 49 FF EOR #0FF
013E| E6 08 INC 08
0140| 90** BCC L5436
013A* 06
0142| L5432
0142| 69 FE ADC #0FE
0144| C6 08 DEC 08
0140* 04
0146| L5436
0146| C5 09 CMP 09
PAGE - 5 P070003 FILE:


0148| 90** BCC L543C
014A| A5 09 LDA 09
0148* 02
014C| L543C
014C| C9 0C CMP #0C
014E| B0** BCS L5441
0150| A8 TAY
014E* 01
0151| L5441
0151| 38 SEC
0152| 20 **** JSR L016F
0155| B9 **** LDA L0191,Y
0158| 20 **** JSR L0180
015B| A5 0A LDA 0A
015D| 18 CLC
015E| 20 **** JSR L0171 ; NOT RESOLVED
0161| B9 **** LDA L019D,Y ; NOT RESOLVED
0164| 20 **** JSR L0180 ; NOT RESOLVED
0167| E6 09 INC 09
0169| D0C6 BNE L5421
0138* 31
016B| L545B
016B| 20 **** JSR L0180 ; NOT RESOLVED
016E| 18 CLC
0153* 6F01
016F| L016F
016F| A5 08 LDA 08
015F* 7101
0171| L0171
0171| 29 03 AND #03
0173| 2A ROL A
0174| 05 06 ORA 06
0176| AA TAX
0177| BD 80C0 LDA 0C080,X
017A| A6 06 LDX 06
017C| 60 RTS
017D| ;
017D| AA TAX
017E| A0 A0 LDY #0A0
016C* 8001
0165* 8001
0159* 8001
0180| L0180
0180| L5470
0180| A2 11 LDX #011
0182| L5472
0182| CA DEX
0183| D0FD BNE L5472
0185| E6 0B INC 0B
0187| D0** BNE L547B
0189| E6 0C INC 0C
0187* 02
018B| L547B
018B| 38 SEC
018C| E9 01 SBC #01
PAGE - 6 P070003 FILE:


018E| D0F0 BNE L5470
0190| 60 RTS
0156* 9101
0191| 01 30 28 20 20 1E 1D L0191 .BYTE 001,030,028,020,020,01E,01D,01C,01C,01C,01C,01C
0198| 1C 1C 1C 1C 1C
0162* 9D01
019D| 70 2C 26 22 1F 1E 1D L019D .BYTE 070,02C,026,022,01F,01E,01D,01C,01C,01C,01C,01C
01A4| 1C 1C 1C 1C 1C
01A9| 00 .BYTE 000
01AA| .END
PAGE - 7 P070003 FILE: SYMBOLTABLE DUMP


AB - Absolute LB - Label UD - Undefined MC - Macro
RF - Ref DF - Def PR - Proc FC - Func
PB - Public PV - Private CS - Consts


L0035 LB 0035| L00A2 LB 00A2| L011B LB 011B| L016F LB 016F| L0171 LB 0171| L0180 LB 0180| L0191 LB 0191
L019D LB 019D| L5313 LB 0023| L531C LB 002C| L5331 LB 0041| L533A LB 004A| L5343 LB 0053| L534C LB 005C
L5356 LB 0066| L5360 LB 0070| L536A LB 007A| L5374 LB 0084| L537F LB 008F| L5392 LB 00A2| L53A4 LB 00B4
L53AD LB 00BD| L53B6 LB 00C6| L53C0 LB 00D0| L53CA LB 00DA| L53D4 LB 00E4| L53DE LB 00EE| L53E9 LB 00F9
L53FC LB 010C| L5421 LB 0131| L5432 LB 0142| L5436 LB 0146| L543C LB 014C| L5441 LB 0151| L545B LB 016B
L5470 LB 0180| L5472 LB 0182| L547B LB 018B| P070003 PR ----|
PAGE - 8 P070003 FILE:


Current minimum space is 8305 words

Assembly complete: 267 lines
0 Errors flagged on this Assembly

I just noticed something a bit unusual in the code. Either I made a mistake or the original coders left some "dead code" in there:

546D- AA TAX
546E- A0 A0 LDY #$A0


Next up is P070002 (COPYPROT)






TommyGoog

unread,
Apr 14, 2014, 10:35:15 PM4/14/14
to

> Next up is P070002 (COPYPROT)

P070002 (COPYPROT)

Right now COPYPROT is just a placeholder routine with " .BLOCK 1C8,2".

I'm not sure what COPYPROT does, so for now I'll rename it to P070002.

Here is how I currently build STARTUP.CODE:

Host file?
#12:STARTUP
Libfile?
#5:P070002.CODE
#5:P070003.CODE
#5:P070005.CODE
Output file?
#5:STARTUP

From the DeCompiler we see:

Start
P070002 $511A
P070003 $52F0

Note, the DeCompiler has a bug if P070002 is not already LINKED into the executable. It displays lots of garbage.

We do the trick with the DeCompiler to get P070002 (from Wiz1 Boot disk) into memory and use Apples monitor to display the code:

]CALL-151

*511ALLLLLLLLLL

511A- 68 PLA
511B- AA TAX
511C- 68 PLA
511D- A8 TAY
511E- 68 PLA
511F- 85 00 STA $00
5121- 68 PLA
5122- 85 01 STA $01
5124- 68 PLA
5125- 85 02 STA $02
5127- 68 PLA
5128- 85 03 STA $03
512A- 98 TYA
512B- 48 PHA
512C- 8A TXA
512D- 48 PHA
512E- 18 CLC
512F- A5 02 LDA $02
5131- 65 00 ADC $00
5133- 85 02 STA $02
5135- A5 03 LDA $03
5137- 65 01 ADC $01
5139- 85 03 STA $03
513B- A2 00 LDX #$00
513D- A9 03 LDA #$03
513F- 0D 1C BF ORA $BF1C
5142- 8D 1C BF STA $BF1C
5145- A1 02 LDA ($02,X)
5147- C9 C0 CMP #$C0
5149- 90 36 BCC $5181
514B- C9 FD CMP #$FD
514D- 90 03 BCC $5152
514F- 4C 32 01 JMP $0132
5152- 38 SEC
5153- E9 C0 SBC #$C0
5155- 85 07 STA $07
5157- A0 02 LDY #$02
5159- B1 02 LDA ($02),Y
515B- 85 06 STA $06
515D- 88 DEY
515E- B1 02 LDA ($02),Y
5160- A8 TAY
5161- B9 BC 04 LDA $04BC,Y
5164- 85 04 STA $04
5166- B9 7C 05 LDA $057C,Y
5169- 85 05 STA $05
516B- A4 07 LDY $07
516D- A5 06 LDA $06
516F- 91 04 STA ($04),Y
5171- 18 CLC
5172- A5 02 LDA $02
5174- 69 03 ADC #$03
5176- 85 02 STA $02
5178- A9 00 LDA #$00
517A- 65 03 ADC $03
517C- 85 03 STA $03
517E- 4C 2B 00 JMP $002B
5181- A8 TAY
5182- B9 BC 04 LDA $04BC,Y
5185- 85 04 STA $04
5187- B9 7C 05 LDA $057C,Y
518A- 85 05 STA $05
518C- A0 01 LDY #$01
518E- B1 02 LDA ($02),Y
5190- 85 06 STA $06
5192- C8 INY
5193- B1 02 LDA ($02),Y
5195- 85 07 STA $07
5197- C8 INY
5198- B1 02 LDA ($02),Y
519A- 85 08 STA $08
519C- C8 INY
519D- B1 02 LDA ($02),Y
519F- 85 09 STA $09
51A1- C8 INY
51A2- B1 02 LDA ($02),Y
51A4- 85 0A STA $0A
51A6- 18 CLC
51A7- A5 02 LDA $02
51A9- 69 06 ADC #$06
51AB- 85 02 STA $02
51AD- A5 03 LDA $03
51AF- 69 00 ADC #$00
51B1- 85 03 STA $03
51B3- A0 00 LDY #$00
51B5- A5 06 LDA $06
51B7- 20 B7 00 JSR $00B7
51BA- A5 07 LDA $07
51BC- 20 B7 00 JSR $00B7
51BF- A5 08 LDA $08
51C1- 20 B7 00 JSR $00B7
51C4- A5 09 LDA $09
51C6- 20 B7 00 JSR $00B7
51C9- A5 0A LDA $0A
51CB- 20 B7 00 JSR $00B7
51CE- 4C 2B 00 JMP $002B
51D1- 85 00 STA $00
51D3- 46 00 LSR $00
51D5- 90 0A BCC $51E1
51D7- A1 02 LDA ($02,X)
51D9- 91 04 STA ($04),Y
51DB- E6 02 INC $02
51DD- D0 02 BNE $51E1
51DF- E6 03 INC $03
51E1- C8 INY
51E2- 46 00 LSR $00
51E4- 90 0A BCC $51F0
51E6- A1 02 LDA ($02,X)
51E8- 91 04 STA ($04),Y
51EA- E6 02 INC $02
51EC- D0 02 BNE $51F0
51EE- E6 03 INC $03
51F0- C8 INY
51F1- 46 00 LSR $00
51F3- 90 0A BCC $51FF
51F5- A1 02 LDA ($02,X)
51F7- 91 04 STA ($04),Y
51F9- E6 02 INC $02
51FB- D0 02 BNE $51FF
51FD- E6 03 INC $03
51FF- C8 INY
5200- 46 00 LSR $00
5202- 90 0A BCC $520E
5204- A1 02 LDA ($02,X)
5206- 91 04 STA ($04),Y
5208- E6 02 INC $02
520A- D0 02 BNE $520E
520C- E6 03 INC $03
520E- C8 INY
520F- 46 00 LSR $00
5211- 90 0A BCC $521D
5213- A1 02 LDA ($02,X)
5215- 91 04 STA ($04),Y
5217- E6 02 INC $02
5219- D0 02 BNE $521D
521B- E6 03 INC $03
521D- C8 INY
521E- 46 00 LSR $00
5220- 90 0A BCC $522C
5222- A1 02 LDA ($02,X)
5224- 91 04 STA ($04),Y
5226- E6 02 INC $02
5228- D0 02 BNE $522C
522A- E6 03 INC $03
522C- C8 INY
522D- 46 00 LSR $00
522F- 90 0A BCC $523B
5231- A1 02 LDA ($02,X)
5233- 91 04 STA ($04),Y
5235- E6 02 INC $02
5237- D0 02 BNE $523B
5239- E6 03 INC $03
523B- C8 INY
523C- 46 00 LSR $00
523E- 90 0A BCC $524A
5240- A1 02 LDA ($02,X)
5242- 91 04 STA ($04),Y
5244- E6 02 INC $02
5246- D0 02 BNE $524A
5248- E6 03 INC $03
524A- C8 INY
524B- 60 RTS
524C- C9 FE CMP #$FE
524E- F0 05 BEQ $5255
5250- C9 FD CMP #$FD
5252- F0 10 BEQ $5264
5254- 60 RTS
5255- A9 30 LDA #$30
5257- 85 09 STA $09
5259- 20 77 01 JSR $0177
525C- C6 09 DEC $09
525E- D0 F9 BNE $5259
5260- 20 77 01 JSR $0177
5263- 60 RTS
5264- A9 30 LDA #$30
5266- 85 09 STA $09
5268- 20 59 01 JSR $0159
526B- C6 09 DEC $09
526D- D0 F9 BNE $5268
526F- 20 59 01 JSR $0159
5272- 60 RTS
5273- A4 09 LDY $09
5275- B9 BC 04 LDA $04BC,Y
5278- 85 04 STA $04
527A- B9 7C 05 LDA $057C,Y
527D- 85 05 STA $05
527F- A0 27 LDY #$27
5281- B1 04 LDA ($04),Y
5283- 49 80 EOR #$80
5285- 91 04 STA ($04),Y
5287- 88 DEY
5288- D0 F7 BNE $5281
528A- B1 04 LDA ($04),Y
528C- 49 80 EOR #$80
528E- 91 04 STA ($04),Y
5290- 60 RTS
5291- 18 CLC
5292- A4 09 LDY $09
5294- B9 BC 04 LDA $04BC,Y
5297- 85 04 STA $04
5299- 69 01 ADC #$01
529B- 85 06 STA $06
529D- B9 7C 05 LDA $057C,Y
52A0- 85 05 STA $05
52A2- 69 00 ADC #$00
52A4- 85 07 STA $07
52A6- A0 00 LDY #$00
52A8- B1 04 LDA ($04),Y
52AA- 85 08 STA $08
52AC- A2 27 LDX #$27
52AE- B1 06 LDA ($06),Y
52B0- 91 04 STA ($04),Y
52B2- C8 INY
52B3- CA DEX
52B4- D0 F8 BNE $52AE
52B6- A5 08 LDA $08
52B8- 91 04 STA ($04),Y
52BA- 60 RTS
52BB- 00 BRK
52BC- 00 BRK
52BD- 00 BRK
52BE- 6E 01 41 ROR $4101
52C1- 01 0A ORA ($0A,X)
52C3- 01 07 ORA ($07,X)
52C5- 01 04 ORA ($04,X)
52C7- 01 01 ORA ($01,X)
52C9- 01 FE ORA ($FE,X)
52CB- 00 BRK
52CC- FD 00 74 SBC $7400,X
52CF- 00 BRK
52D0- 6F ???
52D1- 00 BRK
52D2- 69 00 ADC #$00
52D4- 64 ???
52D5- 00 BRK
52D6- 0C ???
52D7- 00 BRK
52D8- 76 01 ROR $01,X
52DA- 73 ???
52DB- 01 59 ORA ($59,X)
52DD- 01 56 ORA ($56,X)
52DF- 01 6A ORA ($6A,X)
52E1- 00 BRK
52E2- 67 ???
52E3- 00 BRK
52E4- 4F ???
52E5- 00 BRK
52E6- 48 PHA
52E7- 00 BRK
52E8- 08 PHP
52E9- 00 BRK
52EA- 00 BRK
52EB- 00 BRK
52EC- D2 ???
52ED- 01 00 ORA ($00,X)
52EF- 00 BRK

The JTAB begins at the bottom, and we see the self-referencing pointer $01D2 to the start of the code.

This routine has a mystery to solve. Look at:

513F- 0D 1C BF ORA $BF1C

$BF1C? Isn't that part of the Pascal operating system? (Yes!)

Using Google and the internet, I found these references:

Apple II Pascal ATTACH.pdf at ASIMOV (SPCHAR at location BF1C)
Apple II Computer Technical Information
ATTACH-BIOS Documentation for Apple II Pascal 1.1
by Barry Haynes, Apple Computer Inc. -- January 12, 1980

Somewhere in those documents you will find:

BF1C
00 Means do all special character checking
01 Means don't check for Apple screen stuff
02 Means don't check for other screen stuff

3 types of characters:
A. ctrl-A, Z, W, E, K
B. ctrl-S, F
C. ctrl-C, DLE, CR

SPCHAR bit 0 set to 1 === don't look for type A chars
SPCHAR bit 1 set to 1 === don't look for type B chars
When set, special char checking is turned OFF until reboot.

Ok, looks like we will need the following:

SPCHAR .EQU 0BF1C;

On to the next problem:

5161- B9 BC 04 LDA $04BC,Y

Using the Segment load address of $5000 to ABSOLUTIZE this address puts it at $54BC, which isn't in this procedure!

Looking back at my WIZBOOT chart, I think we have our answer:

WIZBOOT
lex Start End Order-in-File
1 0 7.0.1 50CC 50FF 2
2 6502 7.0.2 511A 52EA 3
3 6502 7.0.3 52F0 54B6 4
4 1 7.0.4 5000 50BA 1
5 6502 7.0.5 54BC 5642 5

$54BC is the start of the "code" for P070005.
Earlier I made this observation, and it seems to be true:

"The code at P070005 ($54BC) is similar to a screen table in LOL at L11E2 in SCRNDATA."

To access data in another 6502 procedure, you use the ".REF" instruction:

.REF L04BC, L057C

The JMP and JSR addresses and labels are determined in the same manner as was done with P070003.

I now Assembled and Linked P070005 and got the following errors:

Global L04BC undefined
Global L057c undefined

P070005 will define those 2 labels. P070005 is entirely data.

This is P070005 (Note the ".DEF" instructions to "externalize" those labels.):

.PROC P070005 ; P070003 USES THESE TABLES
;
.DEF L04BC, L057C
;
L54BC
L04BC
.BYTE 000,000,000,000,000,000,000,000
.BYTE 080,080,080,080,080,080,080,080
.BYTE 000,000,000,000,000,000,000,000
.BYTE 080,080,080,080,080,080,080,080
.BYTE 000,000,000,000,000,000,000,000
.BYTE 080,080,080,080,080,080,080,080
.BYTE 000,000,000,000,000,000,000,000
.BYTE 080,080,080,080,080,080,080,080
L54FC
.BYTE 028,028,028,028,028,028,028,028
.BYTE 0A8,0A8,0A8,0A8,0A8,0A8,0A8,0A8
.BYTE 028,028,028,028,028,028,028,028
.BYTE 0A8,0A8,0A8,0A8,0A8,0A8,0A8,0A8
.BYTE 028,028,028,028,028,028,028,028
.BYTE 0A8,0A8,0A8,0A8,0A8,0A8,0A8,0A8
.BYTE 028,028,028,028,028,028,028,028
.BYTE 0A8,0A8,0A8,0A8,0A8,0A8,0A8,0A8
L553C
.BYTE 050,050,050,050,050,050,050,050
.BYTE 0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0
.BYTE 050,050,050,050,050,050,050,050
.BYTE 0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0
.BYTE 050,050,050,050,050,050,050,050
.BYTE 0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0
.BYTE 050,050,050,050,050,050,050,050
.BYTE 0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0
L557C
L057C
.BYTE 020,024,028,02C,030,034,038,03C
.BYTE 020,024,028,02C,030,034,038,03C
.BYTE 021,025,029,02D,031,035,039,03D
.BYTE 021,025,029,02D,031,035,039,03D
.BYTE 022,026,02A,02E,032,036,03A,03E
.BYTE 022,026,02A,02E,032,036,03A,03E
.BYTE 023,027,02B,02F,033,037,03B,03F
.BYTE 023,027,02B,02F,033,037,03B,03F
L55BC
.BYTE 020,024,028,02C,030,034,038,03C
.BYTE 020,024,028,02C,030,034,038,03C
.BYTE 021,025,029,02D,031,035,039,03D
.BYTE 021,025,029,02D,031,035,039,03D
.BYTE 022,026,02A,02E,032,036,03A,03E
.BYTE 022,026,02A,02E,032,036,03A,03E
.BYTE 023,027,02B,02F,033,037,03B,03F
.BYTE 023,027,02B,02F,033,037,03B,03F
L55FC
.BYTE 020,024,028,02C,030,034,038,03C
.BYTE 020,024,028,02C,030,034,038,03C
.BYTE 021,025,029,02D,031,035,039,03D
.BYTE 021,025,029,02D,031,035,039,03D
.BYTE 022,026,02A,02E,032,036,03A,03E
.BYTE 022,026,02A,02E,032,036,03A,03E
.BYTE 023,027,02B,02F,033,037,03B,03F
.BYTE 023,027,02B,02F,033,037,03B,03F
;
.END

Recall also that hex numbers must begin with 0 - 9. To get them lined up I made each of them 3 digits.

Here is the final rough draft for P070002:

.PROC P070002,2 ; WITH 2 PARAMETERS PASSED INTO (FORMERLY COPYPROT)
;
.REF L04BC, L057C
;
SPCHAR .EQU 0BF1C ; SEE APPLE II COMPUTER TECHNICAL INFORMATION
;
PLA
TAX
PLA
TAY
PLA
STA 00
PLA
STA 01
PLA
STA 02
PLA
STA 03
TYA
PHA
TXA
PHA
CLC
LDA 02
ADC 00
STA 02
LDA 03
ADC 01
STA 03
LDX #00
LDA #03
ORA SPCHAR ;0BF1C ...HMMM....PART OF PASCAL SYSTEM TABLES???
STA SPCHAR ;0BF1C
L5145
L002B
LDA @02,X
CMP #0C0
BCC L5181
CMP #0FD
BCC L5152
JMP L0132 ; L524C
L5152
SEC
SBC #0C0
STA 07
LDY #02
LDA @02,Y
STA 06
DEY
LDA @02,Y
TAY
LDA L04BC,Y ; LOOKS UNRESOLVED ??? MAYBE P070005 STARTS AT $54BC
STA 04
LDA L057C,Y
STA 05
LDY 07
LDA 06
STA @04,Y
CLC
LDA 02
ADC #03
STA 02
LDA #00
ADC 03
STA 03
JMP L002B ; UNRESOLVED L5145 L51D1
L5181
TAY
LDA L04BC,Y ; ???
STA 04
LDA L057C,Y
STA 05
LDY #01
LDA @02,Y
STA 06
INY
LDA @02,Y
STA 07
INY
LDA @02,Y
STA 08
INY
LDA @02,Y
STA 09
INY
LDA @02,Y
STA 0A
CLC
LDA 02
ADC #06
STA 02
LDA 03
ADC #00
STA 03
LDY #00
LDA 06
JSR L00B7 ; UNRESOLVED L51D1
LDA 07
JSR L00B7
LDA 08
JSR L00B7
LDA 09
JSR L00B7
LDA 0A
JSR L00B7
JMP L002B ; UNRESOLVED L5145
L51D1
L00B7
STA 00
LSR 00
BCC L51E1
LDA @02,X
STA @04,Y
INC 02
BNE L51E1
INC 03
L51E1
INY
LSR 00
BCC L51F0
LDA @02,X
STA @04,Y
INC 02
BNE L51F0
INC 03
L51F0
INY
LSR 00
BCC L51FF
LDA @02,X
STA @04,Y
INC 02
BNE L51FF
INC 03
L51FF
INY
LSR 00
BCC L520E
LDA @02,X
STA @04,Y
INC 02
BNE L520E
INC 03
L520E
INY
LSR 00
BCC L521D
LDA @02,X
STA @04,Y
INC 02
BNE L521D
INC 03
L521D
INY
LSR 00
BCC L522C
LDA @02,X
STA @04,Y
INC 02
BNE L522C
INC 03
L522C
INY
LSR 00
BCC L523B
LDA @02,X
STA @04,Y
INC 02
BNE L523B
INC 03
L523B
INY
LSR 00
BCC L524A
LDA @02,X
STA @04,Y
INC 02
BNE L524A
INC 03
L524A
INY
RTS
L524C
L0132
CMP #0FE
BEQ L5255
CMP #0FD
BEQ L5264
RTS
L5255
LDA #030
STA 09
L5259
JSR L0177 ; UNRESOLVED L5291
DEC 09
BNE L5259
JSR L0177 ; UNRESOLVED
RTS
L5264
LDA #030
STA 09
L5268
JSR L0159 ; UNRESOLVED L5273
DEC 09
BNE L5268
JSR L0159 ; UNRESOLVED
RTS
L5273
L0159
LDY 09
LDA L04BC,Y ; ???
STA 04
LDA L057C,Y ; ???
STA 05
LDY #027
L5281
LDA @04,Y
EOR #080
STA @04,Y
DEY
BNE L5281
LDA @04,Y
EOR #080
STA @04,Y
RTS
L5291
L0177
CLC
LDY 09
LDA L04BC,Y ; ???
STA 04
ADC #01
STA 06
LDA L057C,Y ; ???
STA 05
ADC #00
STA 07
LDY #00
LDA @04,Y
STA 08
LDX #027
L52AE
LDA @06,Y
STA @04,Y
INY
DEX
BNE L52AE
LDA 08
STA @04,Y
RTS
;
L52BB ;
;
.END
RTS
.END

I was now able to Compile and Link all of WIZBOOT segment in STARTUP.CODE.

STARTUP.TEXT
Mainline (P070001)
CHKCOPY (P070004)
P070002.TEXT (Check keyboard (?). Accesses BF1C SPCHAR)
P070003.TEXT (Disk I/O, and uses P070005 Screen Data ptrs)
P070005.TEXT (Screen Data ptrs)

Using the Call -151 trick after running DeCompiler, I compared my new WIZBOOT segment with the original and found them to be identical. ($5000 to $
564B).

YAY! I've successfully re-enginneered the first Segment for STARTUP.CODE (SYSTEM.STARTUP)!

(Ok, there's still lots of work to do to clean up variable names, etc.)

Up next is TITLELOA, which is executed from SYSTEM.STARTUP mainline right after CHKCOPY is first called.

TommyGoog

unread,
Apr 15, 2014, 6:50:32 PM4/15/14
to

> Up next is TITLELOA, which is executed from SYSTEM.STARTUP mainline right after CHKCOPY is first called.

TITLELOA FILE: 7 SEG: 2 PROC: 1

lex start end order hierarchy
1 1 7.2.1 531E 5378 8 7.2.1
2 2 7.2.2 5000 500C 1 7.2.2
3 2 7.2.3 5018 504F 2 7.2.3
4 2 7.2.4 50D8 52BD 6 7.2.4
5 3 7.2.5 505C 5077 3 7.2.5
6 3 7.2.6 5086 50A2 4 7.2.6
7 3 7.2.7 50AE 50CC 5 7.2.7
8 2 7.2.8 52DE 530C 7 7.2.8

STARTUP.TEXT
$I WIZUTILB
$I WIZUTILC
$I TITLELOA
$I OPTIONS

Using DeCompiler on Wiz1 Boot diskette:

JTAB FOR SUBROUTINE 1:
DATA SIZE: 9222
PARAM SIZE: 0
EXIT AT: 5378
ENTER AT: 531E
PROC NUMBER: 1
LEXICAL LEVEL: 1
531E D7 NOP. NOP
531F A6 08 57 49 5A 41 52 44 52 59
WIZARDRY
LSA. PUSH #(PC+1) POINTER TO THE STRING
5329 CD 1C 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 1C
532C CE 08 CLP. CALL CHILD PROCEDURE: 08
532E C6 02 LLA. PUSH #MP.02
5330 9E 20 MRK. MARK HEAP. (TOS)^ := NP
5332 C7 00 40 LDCI. PUSH #4000
5335 CC 92 03 STL. MP.1203 := (TOS)
5338 C6 92 03 LLA. PUSH #MP.1203
533B 9E 21 RLS. RELEASE HEAP. NP := (TOS)^
533D C7 FD 00 LDCI. PUSH #00FD
5340 CC 01 STL. MP.01 := (TOS)
5342 CE 04 CLP. CALL CHILD PROCEDURE: 04
5344 D8 SLDL. PUSH MP.01
5345 C7 FD 00 LDCI. PUSH #00FD
5348 C3 EQUI. PUSH ((TOS-1) = (TOS))
5349 A1 07 UJP. IF NOT (TOS) THEN JUMP TO 5352
534B C7 FE 00 LDCI. PUSH #00FE
534E CC 01 STL. MP.01 := (TOS)
5350 B9 05 UJP. JUMP TO 5357
5352 C7 FD 00 LDCI. PUSH #00FD
5355 CC 01 STL. MP.01 := (TOS)
5357 C7 AC 3F LDCI. PUSH #3FAC
535A 91 NGI. PUSH -(TOS) (2'S COMP)
535B CE 02 CLP. CALL CHILD PROCEDURE: 02
535D C7 AF 3F LDCI. PUSH #3FAF
5360 91 NGI. PUSH -(TOS) (2'S COMP)
5361 CE 02 CLP. CALL CHILD PROCEDURE: 02
5363 00 SLDC. PUSH #0000
5364 00 SLDC. PUSH #0000
5365 CE 03 CLP. CALL CHILD PROCEDURE: 03
5367 A1 F6 UJP. IF NOT (TOS) THEN JUMP TO 5342
5369 B6 02 03 LOD. PUSH ACTREC(-02).03
536C 20 SLDC. PUSH #0020
536D 00 SLDC. PUSH #0000
536E CD 00 11 CXP. CALL EXTERNAL PROCEDURE: 11 IN SEGMENT: 00
5371 01 SLDC. PUSH #0001
5372 9E 26 CHECK VOL#
5374 C6 02 LLA. PUSH #MP.02
5376 9E 21 RLS. RELEASE HEAP. NP := (TOS)^
5378 AD 00 RNP. RETURN FROM NON-BASE PROCEDURE.
537A 38 SLDC. PUSH #0038
537B 00 SLDC. PUSH #0000


The first pcode is:

531F A6 08 57 49 5A 41 52 44 52 59
WIZARDRY
LSA. PUSH #(PC+1) POINTER TO THE STRING
5329 CD 1C 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 1C

Recall that "SEGMENT: 1C" is SETCHAIN in the SYSTEM.LIBRARY.

So this converts to:

SETCHAIN( 'WIZARDRY');

Next code is:

532C CE 08 CLP. CALL CHILD PROCEDURE: 08

This converts to:
P070208;

Oh yeah, lets set up dummy procedures for TITLELOA in the hierarchy that I have in the table earlier.

Next I will compile this little bit to make sure we are on the right path. I will then look at it with the DeCompiler.

Do I need to Link in the 6502 code? Can I put those 6502 procedures in SYSTEM.LIBRARY and then always use SYSTEM.LIBRARY instead of knowing the names and order to Link files in? At this time, the 6502 procedures don't seem to be needed for what I am looking at.

Next up:

532E C6 02 LLA. PUSH #MP.02
5330 9E 20 MRK. MARK HEAP. (TOS)^ := NP
5332 C7 00 40 LDCI. PUSH #4000
5335 CC 92 03 STL. MP.1203 := (TOS)
5338 C6 92 03 LLA. PUSH #MP.1203
533B 9E 21 RLS. RELEASE HEAP. NP := (TOS)^

$4000 is the start of Hi-Res page 2, just above page 1. I think this code is protecting Hi-res Page 1 from being used for heap space. I will have a lot more to say about memory management and the heap when looking at the Wizardry main code.

The Pascal code is:

MARK( MP02);
MP1203 := 16384; (* $4000 *)
RELEASE( MP1203);

MP1203 indicates this routine has a lot of memory used for VARiables.

For now I'll try this:

MP01 : INTEGER
MP02 : ^INTEGER;
MP03 : ARRAY[ 1..3000] OF INTEGER;
MP1203 : ^INTEGER;

That failed because MP02 is used as 2 different variable TYPEs: INTEGER and POINTER.

Oh yeah! Time to relearn VARIANT RECORDs.

BYTE = PACKED ARRAY [0..1] OF 0..255;
MAGIC = RECORD CASE BOOLEAN OF
FALSE : (I : INTEGER);
TRUE : (P : ^BYTE);
END;

Here is the completed rough draft:

SEGMENT PROCEDURE TITLELOA;
TYPE

BYTE = PACKED ARRAY [ 0..1] OF 0..255;

MAGIC = RECORD CASE BOOLEAN OF
FALSE : (I : INTEGER);
TRUE : (P : ^BYTE);
END;

VAR

MP01 : INTEGER;
MP02 : ^INTEGER;
MP03 : ARRAY[ 1..4608] OF INTEGER;
MP1203 : MAGIC;

PROCEDURE P070202( MP01 : INTEGER);
BEGIN
END;

FUNCTION P070203 : BOOLEAN;
BEGIN
END;

PROCEDURE P070204;

PROCEDURE P070205;
BEGIN
END;

PROCEDURE P070206;
BEGIN
END;

PROCEDURE P070207;
BEGIN
END;

BEGIN (* P070204 *)
END;

PROCEDURE P070208;
BEGIN
END;

BEGIN (* P070201 MAINLINE *)

SETCHAIN( 'WIZARDRY');
P070208;
MARK( MP02);
MP1203.I := 16384;
RELEASE( MP1203.P);
MP01 := 253;
REPEAT

P070204;
IF MP01 = 253 THEN
BEGIN
MP01 := 254
END
ELSE
BEGIN
MP01 := 253
END;
P070202( -16300);
P070202( -16303);

UNTIL P070203;
WRITE( CHR( 32));
UNITCLEAR( 1);
RELEASE( MP02);
END;

-16300 and -16303
These are soft switches on the Apple II.
-16300 is $C054 and displays primary page 1.
-16303 is $C051 and displays TEXT mode.

How do I know UNITCLEAR( 1) is generates " CHECK VOL#"?

I have a table that I've created to help me with "SEGMENT: 00" and other system calls. I created this table by looking at examples of other Pascal code and using the DeCompiler.

READ() Procedure: 10
EOLN() Procedure: 0B
WRITE() Procedure: 11 WRITE( CHR( 13))
WRITE() Procedure: 13 WRITE( Astr : 20);
WRITELN() Procedure: 13 and 16
WRITELN Procedure: 16
Write() Procedure: 0D WRITE( Anum : 2);
GOTOXY() Procedure: 1D
COPY() Procedure: 19
CONCAT Procedure: 17
RESET() Procedure: 05

VAR x : FILE; Procedure: 03 Declaring the file generates 2 calls.
"03" at the start of the procedure.
The parameter passed to 03 is the
file "type" (REAL, INTEGER, untyped, ...)
VAR x : FILE; Precedure: 06 "06" at the end of the procedure.

UNITREAD() READ FROM VOL# (* DEVICE, BUFF, CNT, BLOCK #, MODE *)
UNITWRITE() WRITE VOL #
UNITCLEAR( 1) CHECK VOL#

USE CHAINSTUFF Procedure: 01 in Segment: 1C
SETCHAIN() Procedure: 02 in Segment: 1C

Note, this is not a completed table yet. As I encounter more "UNKNOWNs" I will need to update it.

UNITCLEAR( 1) flushes the typeahead buffer for CONSOLE: and resets horizontal scrolling to full left.

Before every FUNCTION() call in Pascal, the pcode generates PUSH #0 and PUSH #0.



P070201 is next:

FILE: 7 SEG: 2 PROC: 2

JTAB FOR SUBROUTINE 2:
DATA SIZE: 0
PARAM SIZE: 2
EXIT AT: 500C
ENTER AT: 5000
PROC NUMBER: 2
LEXICAL LEVEL: 2
5000 D8 SLDL. PUSH MP.01
5001 B8 01 92 03 STR. ACTREC(-01).1203 := TOS
5005 B6 01 92 03 LOD. PUSH ACTREC(-01).1203
5009 00 SLDC. PUSH #0000
500A 00 SLDC. PUSH #0000
500B BF STB. (TOS-2)^.(TOS-1) := TOS BYTE
500C AD 00 RNP. RETURN FROM NON-BASE PROCEDURE.

"PARAM SIZE: 2" means the parameter occupies 2 bytes. This could be an INTEGER variable.

When looking at the DeCompiled code, when no parameters are passed, then the first variable declared is referred to as MP.01. When there are parameters, this changes. Now the first parameter is named MP.01 and the declared variables follow that one.

The LEXICAL LEVEL is 2, so this is "nested" beneath TITLELOA.

The ACTREC(-01) refers to the most recent activation record before this procedure is called. ACTREC(-01).1203 therefore refers to a declared variable in TITLELOA.

It is a PROCEDURE an not a FUNCTION, because RNP ($AD) has 00 as its parameter.

PROCEDURE P070202( MP01 : INTEGER);
BEGIN
MP1203 := MP01;
MP1203^ hey MP1203 is an INTEGER, not a pointer!
END;

Hmmm, MP1203 cannot be an INTEGER and a POINTER.
Look at the definition for MP1203. It is a variant record.
Let's try the following:

SEGMENT PROCEDURE TITLELOA;
VAR
MP1203 : MAGIC;

PROCEDURE P070202( MP01 : INTEGER);
BEGIN
MP1203.I := MP01;
MP1203.P^[ 0] := 0
END;

Side rant:

Whomever invented "E" for "EDIT" and "E" for "EXTENDED DIR" should be shot. How many times have I entered the EDITOR when I wanted an EXTENDED DIR? Maybe I should start using "L" for "DIR".

But Nooooo! "L" is for "LINKER"

Continue with P070203 in TITLELOA.

FILE: 7 SEG: 2 PROC: 3

JTAB FOR SUBROUTINE 3:
DATA SIZE: 0
PARAM SIZE: 4
EXIT AT: 504F
ENTER AT: 5018
PROC NUMBER: 3
LEXICAL LEVEL: 2
5018 01 SLDC. PUSH #0001
5019 CC 01 STL. MP.01 := (TOS)
501B C7 00 40 LDCI. PUSH #4000
501E 91 NGI. PUSH -(TOS) (2'S COMP)
501F B8 01 92 03 STR. ACTREC(-01).1203 := TOS
5023 B6 01 92 03 LOD. PUSH ACTREC(-01).1203
5027 00 SLDC. PUSH #0000
5028 BE LDB. PUSH #00, PUSH (TOS-1)^.TOS BYTE
5029 7F SLDC. PUSH #007F
502A C5 GRTI. PUSH ((TOS-1) > (TOS))
502B A1 04 UJP. IF NOT (TOS) THEN JUMP TO 5031
502D 08 SLDC. PUSH #0008
502E 03 SLDC. PUSH #0003
502F 9E 04 EXIT. EXIT FROM PROCEDURE. (TOS)=PROC# (TOS-1)=SEG#
5031 C7 E8 40 LDCI. PUSH #40E8
5034 91 NGI. PUSH -(TOS) (2'S COMP)
5035 B8 01 92 03 STR. ACTREC(-01).1203 := TOS
5039 B6 01 92 03 LOD. PUSH ACTREC(-01).1203
503D 00 SLDC. PUSH #0000
503E BE LDB. PUSH #00, PUSH (TOS-1)^.TOS BYTE
503F B6 01 92 03 LOD. PUSH ACTREC(-01).1203
5043 01 SLDC. PUSH #0001
5044 BE LDB. PUSH #00, PUSH (TOS-1)^.TOS BYTE
5045 CB NEQI. PUSH ((TOS-1) <> (TOS))
5046 A1 04 UJP. IF NOT (TOS) THEN JUMP TO 504C
5048 08 SLDC. PUSH #0008
5049 03 SLDC. PUSH #0003
504A 9E 04 EXIT. EXIT FROM PROCEDURE. (TOS)=PROC# (TOS-1)=SEG#
504C 00 SLDC. PUSH #0000
504D CC 01 STL. MP.01 := (TOS)
504F AD 01 RNP. RETURN FROM NON-BASE PROCEDURE.
5051 00 SLDC. PUSH #0000

PARAM SIZE indicates 2 parameters.
RNP with AD 01 means this is a FUNCTION
MP.01 is value of function returned.
lex level is 2, so same level as P070202.
I already have this returning BOOLEAN. Why? Because of P070201 Mainline with "UNTIL P070203; 0 = FALSE and 1 = TRUE I think.
DATA SIZE 0 means no VARs here.
$4000 is 16384
IF MP1203.P^[0] > #$7F THEN #$7F === 127
EXIT ( SEG 8, PROC 3); SEG 8 PROC 3 === P070203
MP1203.i := -16616 #$40E8 === 16616

I'm not sure, but I think the code is like the following:
IF MP1203.P^[ 0] <> MP1203.P^[ 1] THEN
EXIT (P070203);
P070203 := FALSE;

Well let's throw it into the editor and try to compile it.

941 8 3:D 3 FUNCTION P070203 : BOOLEAN;
942 8 3:0 0 BEGIN
943 8 3:1 0 P070203 := TRUE;
944 8 3:1 3 MP1203.I := -16384; (* -$4000 *)
945 8 3:1 11 IF MP1203.P^[0] > 127 THEN
946 8 3:2 21 EXIT( P070203);
947 8 3:1 25 MP1203.I := -16616;
948 8 3:1 33 IF MP1203.P^[ 0] <> MP1203.P^[ 1] THEN
949 8 3:2 48 EXIT( P070203);
950 8 3:1 52 P070203 := FALSE
951 8 3:0 52 END;

Wow! That actually compiled. I wasn't really sure if the syntax was correct, but apparently it is.

Double Wow! The DeCompiler says it produced the proper code!

Something about a million monkeys and Shakespeare comes to mind.

I have no idea what this code is doing.
$4000 is secondary hi-res screen location.
$40E8 is also on that screen.

Lol (laughing!) -16384 is $C000 (-$4000), so it is the Keyboard Data Latch.

-$4000 -16384 $C000 Keyboard Data
-$40E8 -16616 $BF18 Pascal System stuff (?) SYSCOM (?)
-16368 $C010 Clear Keyboard Strobe

$BF18 (See ATTACH.PDF)

"1. The type ahead buffer is located at $03B1 hex and is $4E hex in length. It is implemented with a read pointer (RPTR at BF18 hex) and a write pointer WPTR at $BF19 hex). At CONSOLE: init time, these should both be set to 0. When a character is detected by CONCK, the WPTR is incremented then compared with $4E. If it is equal to $4E, it is set to $0 (this is a circular buffer). Then the WPTR is compared with RPTR and if they are equal the buffer is full. If the buffer is not full, the character is stored at $03B1+the value in WPTR.

"When removing a character from the type ahead buffer, use the following sequence. Compare the RPTR with WPTR and if they are equal, the buffer is empty and you must wait until a character is available from the keyboard. If they are not equal, increment the RPTR and compair it to $4E. If it equals $4E, set it to $0. Now get the character from location $03B1+the value in RPTR."

(Note the interesting spelling of "compair".)

This routine, P070203 is checking to see if a keystroke has been made, or if it was made and already put into the Pascal keyboard input buffer. Returns TRUE if key was pressed.

This mention of the keyboard input buffer at $3B1 is something I discovered the hard way back in 1990 or 1991.

BEGIN VERY VERY LONG STORY:

I started the Wizardry III journey by working my way through the bootstrap code for the Wizardry III boot diskette. I first copied as much of the diskette that would copy using COPYII+. Next I edited Track 0, Sector 0, and put a BRK instruction (byte value of 0) at the second byte in the sector. This sector gets loaded at $800, and $801 is the first instruction executed after it is loaded. By doing this, I can boot the diskette and it will drop me into the Apple monitor with the code at $800. I can then change the value at $801 and use the monitor commands to begin my bootstrap investigation.

The code at $800 - $8FF will load another bunch of sectors from the diskette and then start to execute that code as the next part of the bootstrap process. So just after those sectors have been read from the diskette, and before executing that code, I find the place on Track 0, Sector 0, and change the instruction to a BRK (and also restore the second byte in this sector to its original value). Now the diskette can be booted and code will be loaded at $800 - $8FF, and then the next chunk of code gets loaded to where it goes, and then the Apple puts me in the monitor so I can examine memory, etc.

Ok, this worked great for awhile, and I got quite far, but somewhere down the road instead of dropping me into the Apple monitor, the machine would just keep rebooting. Ah! Of course! The bytes at $3F2, $3F3, and $3F4 were being cleared to 0 at some point, so the handling of the BRK instruction by the monitor would think the machine was just turned on and go through its boot sequence. Ok, so I managed to patch the code on the diskette so that those bytes at #3F2 - #3F4 were not cleared. And eventually I got a long way into the bootstrap, and into the execution of the Pascal system, and the loading of SYSTEM.STARTUP, and execution of the Wizardry program.

But I was just getting to the hard part.

One way of continuing this process once you get into the Pascal pcode interpreter is to modify the pcode you are interested in. But you cannot put a "BRK" instruction. One way is to put a "HALT" instruction into the pcode where you want it to stop. But you also need to modify the Pascal handler for the HALT instruction by putting a BRK instruction there. Ok, I did all that.

During the execution of SYSTEM.STARTUP, you press a key and it stops the title screen from displaying and displays the first menu to the user. And since I had placed the HALT instruction at the proper place, it put me into the Apples monitor as expected and I could poke around the Pascal Heap stack, etc.

Now sometimes when I was booting this modified diskette, I would press and hold a key down to get to my inserted HALT instruction. But something weird happened. Instead of putting me into the monitor, it rebooted! Ok, so just press one key and then everything would work fine.

And this was ok for awhile. But then after executing a lot of code I wanted to HALT the program at the point where I was just going to enter the maze. And now the HALT instruction caused the Apple to reboot every time. Now obviously there were many keystrokes entered from the time of first booting until actually entering the maze.

And to make a long story short, the reason the Apple was always rebooting is because the keyboard input buffer which starts at #3B1 was filling up and clobbering (as it should) the bytes $3F2, $3F3, $3F4.

Was I at a dead end? No, I simply modified the Pascal runtime system to think the input buffer was shorter than #$4E, so that it would not clobber those magic power on bytes.

Please let me know if you enjoyed this "detour" from our current journey.

END OF VERY VERY LONG STORY

Up next is P070208.

awanderin

unread,
Apr 16, 2014, 12:05:23 AM4/16/14
to

I'm reading every post! Keep them coming, they are quite interesting!
Thanks!


--
Jerry awanderin at gmail dot com

qkumba

unread,
Apr 16, 2014, 12:51:01 AM4/16/14
to
copyprot:

0000-009D - nibble check #1
looks like a patch 009E from 84 to 00 will defeat it.

00A2-011B - nibble check #2
looks like a patch 0107 from F0 to B0 will defeat it.

011B - 01AA - move the drive head (seek track). standard routine.

511A... - looks like LZW decompression routine.

> LDA L04BC,Y ; LOOKS UNRESOLVED ??? MAYBE P070005 STARTS AT $54BC

this is part of a pre-computed line table for the graphics screen ($54BC, as you have it)
--

I am enjoying these posts very much.
Please let me know if I can be of assistance with understanding any particular part of the disassembly.

TommyGoog

unread,
Apr 17, 2014, 2:37:35 AM4/17/14
to
Thank you Jerry (awanderin) and qkumba (and Vladimir Ivanov and Rob Craig and sicklittlemonkey) for your comments. It's good to see I have at least a small audience and not an empty classroom :)

I hope you've all had a chance to read my earlier thread regarding Wizardry III (Legacy of Llylgamyn). There was one thing I never figured out with that decompiling effort. I could never get the order of the PROCEDURES (and FUNCTIONS) to be in the same order in the final ".CODE" file as they did. Normally the PROCEDUREs are placed in the file in the order in which their "END;" statement is compiled. I don't know if there is a Compiler (or Linker) option I am not aware of that could affect that. My guess 2 years ago (and still today) is that they may have had a specialized Linker or perhaps their own "incremental" Linker to put the pieces into the final ".CODE" file. If you'd like to solve a problem I could not, that would be a good one! Note the order for LOL WIZUTIL.CODE was correct, but the order for WIZARDRY.CODE was not. I suspect I may run into this with Wizardry I also.

As far as my understanding and figuring out the code for Wizardry I, if something comes up that I cannot figure out, I'll ask for help or explain what I have. Sometimes I'll leave my early comments like "LOOKS UNRESOLVED ???" in the code even after I've figured it out. It sort of documents what I was thinking during this work-in-progress. At the very end, in the final cleanup phase, I usually remove things might be confusing to the first time reader.

Regarding defeating the "nibble checks" in the code, another way is to just NOP out the call to the copy protection code (provided no residual information is needed), or to just ignore the result of CHKCOPY after the call.

What's that you say? Pascal has a NOP instruction? If so, how do you put a NOP into Pascal code? See p. 284 of Apple Pascal Operating System. Opcode 215 ($D7) is a NOP. In this instance, CHKCOPY( P070004) saves information at SERIAL, so we must at least make the call to CHKCOPY. If you look at the "IF MP05 THEN EXIT( CHKCOPY);" you will see that we can modify this instruction to always take the "EXIT" instead of getting to the "HALT" instruction.

50AB A1 04       UJP.   IF NOT (TOS) THEN JUMP TO 50B1 We can NOP the 50AB and 50AC instructions and the EXIT will always be taken. These are located on the original diskette at: TRACK $22, SECTOR $7, at address $AB and $AC. How did I determine that? From DeCompiler, FILE: 7 SEG: 0 PROC: 4 has P070004 starting at $5000 (what luck! beginning of segment!). The DeCompiler also shows FILE: 7 starting at Track 34 Sector 7 (DOS formatting,and the "34" is a decimal number not hex like it really should be). Use COPYII+ to read TRACK $22, SECTOR $7, move down to AB and change 2 consecutive bytes (from A1 and 04) to D7 and D7.

If you really want to be clever, you could change the UJP instruction to jump to 50AD instead of jumping to 50B1. I think changing 50AC from 04 to 00 will accomplish this. So just a 1 byte change to defeat the copy protection scheme, and it will be obvious to anyone looking at the modified code that this is what was done!

I haven't really begun analyzing the code for LOL yet. Right now its just "get Pascal source to compile to the pcode". Later I will spend more time trying to see what the code does when fixing the names for variables and procedures.

It takes a lot of time to put these postings together which detracts from my time to do the actual work:) I had almost gotten to the point of beginning to post minimal information, but perhaps some of you would still like to see what I'm doing. At some point it will become quite repetitive. After all, there are over 500 PROCEDUREs in this effort.

I've actually been working a bit further ahead than what I've posted. On April 15 I already completed the entire Pascal (and assembly language) code to compile and get the pcode for all of SYSTEM.STARTUP. I think it actually helps to do the work the first time, then get away from it for a few days, and then come back to it and then try to re-figure out what I did so I can explain it to others.

Once again, thanks for your comments and don't be afraid to ask questions.

Tommy





TommyGoog

unread,
Apr 18, 2014, 5:44:38 PM4/18/14
to

> Up next is P070208.

Here is the pcode we want:

FILE: 7 SEG: 2 PROC: 8

JTAB FOR SUBROUTINE 8:
DATA SIZE: 80
PARAM SIZE: 0
EXIT AT: 530C
ENTER AT: 52DE
PROC NUMBER: 8
LEXICAL LEVEL: 2
52DE C6 01 LLA. PUSH #MP.01
52E0 C6 81 2D LLA. PUSH #MP.012D
52E3 C7 01 00 LDCI. PUSH #0001
52E6 91 NGI. PUSH -(TOS) (2'S COMP)
52E7 CD 00 03 CXP. CALL EXTERNAL PROCEDURE: 03 IN SEGMENT: 00
52EA C6 01 LLA. PUSH #MP.01
52EC D7 NOP. NOP
52ED A6 02 57 54
WT
LSA. PUSH #(PC+1) POINTER TO THE STRING
52F1 01 SLDC. PUSH #0001
52F2 00 SLDC. PUSH #0000
52F3 CD 00 05 CXP. CALL EXTERNAL PROCEDURE: 05 IN SEGMENT: 00
52F6 C6 01 LLA. PUSH #MP.01
52F8 B2 01 03 LDA. PUSH #ACTREC(-01).03
52FB 00 SLDC. PUSH #0000
52FC 12 SLDC. PUSH #0012
52FD 00 SLDC. PUSH #0000
52FE 01 SLDC. PUSH #0001
52FF 00 SLDC. PUSH #0000
5300 00 SLDC. PUSH #0000
5301 CD 00 1C CXP. CALL EXTERNAL PROCEDURE: 1C IN SEGMENT: 00
5304 AB 04 SRO. BASE.04 := (TOS)
5306 C6 01 LLA. PUSH #MP.01
5308 00 SLDC. PUSH #0000
5309 CD 00 06 CXP. CALL EXTERNAL PROCEDURE: 06 IN SEGMENT: 00
530C C6 01 LLA. PUSH #MP.01
530E 00 SLDC. PUSH #0000
530F CD 00 06 CXP. CALL EXTERNAL PROCEDURE: 06 IN SEGMENT: 00
5312 AD 00 RNP. RETURN FROM NON-BASE PROCEDURE.


WIZBOOT calls TITLELOA, and TITLELOA then calls P070208 right away.

It is a procedure (see RNP instruction) with no parameters (PARAM SIZE: 0).

I'm confused by the procedure calls in this routine. I'm not familiar with:

EXTERNAL PROCEDURE: 03 in SEGMENT: 00
EXTERNAL PROCEDURE: 05 in SEGMENT: 00
EXTERNAL PROCEDURE: 1C in SEGMENT: 00
EXTERNAL PROCEDURE: 06 in SEGMENT: 00

Segment 00 is part of the Pascal system's standard routines.

In LOL for SYSTEM.STARTUP (something I have not re-engineered into Pascal) I notice there is a CALL EXTERNAL PROCEDURE: 05 in SEGMENT: 00. One of its parameters is "picture.bits".

I see "WT" in Wiz1 as input to PROCEDURE: 05. It would seem "PROCEDURE: 05" has something to do with files. I never encountered "PROCEDURE: 05 in SEGMENT: 00" in the LOL re-engineering.

Time for a little testing.

Here is the test program:

PROGRAM TEST;
VAR F: FILE OF CHAR;

BEGIN
RESET( F)
END.

Here is the pcode:

JTAB FOR SUBROUTINE 1:
DATA SIZE: 602
PARAM SIZE: 4
EXIT AT: 5015
ENTER AT: 5000
PROC NUMBER: 1
LEXICAL LEVEL: 0
5000 D7 NOP. NOP
5001 D7 NOP. NOP
5002 A5 03 LA0. PUSH #BASE.03
5004 A5 81 2F LA0. PUSH #BASE.012F
5007 C7 02 00 LDCI. PUSH #0002
500A 91 NGI. PUSH -(TOS) (2'S COMP)
500B CD 00 03 CXP. CALL EXTERNAL PROCEDURE: 03 IN SEGMENT: 00
500E A5 03 LA0. PUSH #BASE.03
5010 CD 00 04 CXP. CALL EXTERNAL PROCEDURE: 04 IN SEGMENT: 00
5013 9E 00 AN UNKNOWN STANDARD PROCEDURE ?!?!
5015 A5 03 LA0. PUSH #BASE.03
5017 00 SLDC. PUSH #0000
5018 CD 00 06 CXP. CALL EXTERNAL PROCEDURE: 06 IN SEGMENT: 00
501B C1 00 RBP. RETURN FROM BASE PROCEDURE.
501D 00 SLDC. PUSH #0000


Well, I didn't expect that much pcode from such little Pascal code!

We got a "PROCEDURE: 03" and "PROCEDURE: 06", but no PROCEDURE: 05.

Let's try another test. I will add all the compiler options that LOL had (and Wiz1 too), and try with no code, and try putting (INPUT, OUTPUT) in the program header. (I later learned that putting INPUT and OUTPUT in the header for Apple Pascal programs does nothing.)

Program:
(*$S++*)
(*$R-*)
(*$I-*)
(*$V-*)

PROGRAM TEST( INPUT, OUTPUT);

VAR FILE1 : FILE OF INTEGER;

BEGIN
END.

pcode:

DATA SIZE: 602
PARAM SIZE: 4
EXIT AT: 500B
ENTER AT: 5000
PROC NUMBER: 1
LEXICAL LEVEL: 0
5000 D7 NOP. NOP
5001 D7 NOP. NOP
5002 A5 03 LA0. PUSH #BASE.03
5004 A5 81 2F LA0. PUSH #BASE.012F
5007 01 SLDC. PUSH #0001
5008 CD 00 03 CXP. CALL EXTERNAL PROCEDURE: 03 IN SEGMENT: 00
500B A5 03 LA0. PUSH #BASE.03
500D 00 SLDC. PUSH #0000
500E CD 00 06 CXP. CALL EXTERNAL PROCEDURE: 06 IN SEGMENT: 00
5011 C1 00 RBP. RETURN FROM BASE PROCEDURE.
5013 00 SLDC. PUSH #0000

Another big surprise! With no Pascal instructions, there was a bunch of pcode generated. This is coming from the " VAR FILE1" declaration!

Ok, looks like declaring a file in the VAR section generates a call to "PROCEDURE: 03" at the beginning of the procedure, and a "PROCEDURE: 06" at the end. Also notice the input to "PROCEDURE: 03". With "FILE OF CHAR" it was -2, but with "FILE OF INTEGER" it is +1.

We want the input to 03 to be "-1". Time to experiment again. I tried all the following:

FILE OF INTEGER 0001
FILE OF REAL 0002
FILE OF CHAR -0002
FILE OF BOOLEAN 0001
FILE OF INTERACTIVE 012D
FILE OF STRING 0029
FILE OF TEXT 012D

PACKED FILE OF xxxx didn't make any difference

It sometimes takes a lot of energy to re-engineer 1 freaking simple line of code. You can quote me on that!

VAR FILE1 : FILE; (* -0001 *)

Removing the "type" from FILE1 gives us -1 which is what we want!

With a little more experimenting I found how to generate PROCEDURE: 05

RESET( FILE1, 'WT');

This next chunk of pcode looks like a call to BLOCKREAD()

52F6 C6 01 LLA. PUSH #MP.01
52F8 B2 01 03 LDA. PUSH #ACTREC(-01).03
52FB 00 SLDC. PUSH #0000
52FC 12 SLDC. PUSH #0012
52FD 00 SLDC. PUSH #0000
52FE 01 SLDC. PUSH #0001
52FF 00 SLDC. PUSH #0000
5300 00 SLDC. PUSH #0000
5301 CD 00 1C CXP. CALL EXTERNAL PROCEDURE: 1C IN SEGMENT: 00
5304 AB 04 SRO. BASE.04 := (TOS)

BLOCKREAD() is a function that returns a value.
First parameter is the declared filename.
Second parameter is a buffer.

Here #ACTREC(-1).03 refers to the parent procedure that called P070208, and it is referring to P070201 MP03.

Right now, MP03 in P070208 is defined as ARRAY[ 1..4608] OF INTEGER.
I'm not sure if all of that is for MP03, but it makes sense that it is a buffer.

Note, if P070208 had a variable named MP03, then I would need to change the name MP03 in P070201 or MP03 in P070208.

This next chunk looks like CLOSE( FILE1);

5306 C6 01 LLA. PUSH #MP.01
5308 00 SLDC. PUSH #0000
5309 CD 00 06 CXP. CALL EXTERNAL PROCEDURE: 06 IN SEGMENT: 00

Note, this sequence appears twice in the code we want; the second one is because of the declaration of the FILE1.

BASE04 is the name I gave to the variable in LOL that generates pcode with BASE.04. (Actually most variables that I re-engineer start out something like BASE04.) I left that variable as the final name because its real name was probably something like "TEMP". It had many uses in LOL. And also there were a few bugs associated with it, where I think the authors used the wrong variable name in a couple places associated with "TEMP" (or BASE04, or whatever they called it.)

Hmmm, I tried to use BASE04, but now realize I had already removed it. So this means the variable currently defined as RANDNUM is BASE.04. Hmmmm. Its likely that RANDNUM is not the correct name for BASE.04.

To get things to compile right now, I will use the name RANDNUM in P070208.

I think I may have been wrong about removing BASE04 and not removing RANDNUM earlier.

I think there was a bug I discovered in LOL where RANDNUM was never initialized. Maybe they removed this code and forgot to initialize RANDNUM in LOL (?)


After a little trial and error, I have the final (rough draft) version:

970 8 8:D 1 PROCEDURE P070208;
971 8 8:D 1
972 8 8:D 1 VAR
973 8 8:D 1 FILE1 : FILE; (* UNTYPED FILE *)
974 8 8:D 41
975 8 8:D 41
976 8 8:0 0 BEGIN
977 8 8:1 0 RESET( FILE1, 'WT');
978 8 8:1 24 RANDNUM := BLOCKREAD( FILE1, MP03, 18, 0);
979 8 8:1 40 CLOSE( FILE1)
980 8 8:0 46 END;

Note, 18 x 512 = 4608. Looks like MP03 is already defined with the correct size.

P070204 is next. It has 3 child procedures: P070205, P070206, P070207.

Here is the pcode we want:

FILE: 7 SEG: 2 PROC: 4

JTAB FOR SUBROUTINE 4:
DATA SIZE: 14
PARAM SIZE: 0
EXIT AT: 52BD
ENTER AT: 50D8
PROC NUMBER: 4
LEXICAL LEVEL: 2
50D8 B2 01 03 LDA. PUSH #ACTREC(-01).03
50DB 00 SLDC. PUSH #0000
50DC A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
50DE B2 01 03 LDA. PUSH #ACTREC(-01).03
50E1 08 SLDC. PUSH #0008
50E2 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
50E4 F8 SIND. PUSH (TOS)^.0
50E5 CD 01 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 01
50E8 C7 00 20 LDCI. PUSH #2000
50EB B8 01 92 03 STR. ACTREC(-01).1203 := TOS
50EF B6 01 92 03 LOD. PUSH ACTREC(-01).1203
50F3 00 SLDC. PUSH #0000
50F4 C7 00 20 LDCI. PUSH #2000
50F7 00 SLDC. PUSH #0000
50F8 9E 0A FLC. FILLCHAR (DST+IDX,LEN,CHR)
50FA B6 03 03 LOD. PUSH ACTREC(-03).03
50FD 0C SLDC. PUSH #000C
50FE 00 SLDC. PUSH #0000
50FF CD 00 11 CXP. CALL EXTERNAL PROCEDURE: 11 IN SEGMENT: 00
5102 0C SLDC. PUSH #000C
5103 0A SLDC. PUSH #000A
5104 CD 00 1D CXP. CALL EXTERNAL PROCEDURE: 1D IN SEGMENT: 00
5107 B6 03 03 LOD. PUSH ACTREC(-03).03
510A D7 NOP. NOP
510B A6 10 50 52 45 50 41 52 45 20 59 4F 55 52 53 45 4C 46
PREPARE YOURSELF
LSA. PUSH #(PC+1) POINTER TO THE STRING
511D 00 SLDC. PUSH #0000
511E CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
5121 C7 96 00 LDCI. PUSH #0096
5124 CE 05 CLP. CALL CHILD PROCEDURE: 05
5126 0C SLDC. PUSH #000C
5127 0C SLDC. PUSH #000C
5128 CD 00 1D CXP. CALL EXTERNAL PROCEDURE: 1D IN SEGMENT: 00
512B B6 03 03 LOD. PUSH ACTREC(-03).03
512E D7 NOP. NOP
512F A6 10 46 4F 52 20 54 48 45 20 55 4C 54 49 4D 41 54 45
FOR THE ULTIMATE
LSA. PUSH #(PC+1) POINTER TO THE STRING
5141 00 SLDC. PUSH #0000
5142 CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
5145 C7 96 00 LDCI. PUSH #0096
5148 CE 05 CLP. CALL CHILD PROCEDURE: 05
514A 0C SLDC. PUSH #000C
514B 0E SLDC. PUSH #000E
514C CD 00 1D CXP. CALL EXTERNAL PROCEDURE: 1D IN SEGMENT: 00
514F B6 03 03 LOD. PUSH ACTREC(-03).03
5152 D7 NOP. NOP
5153 A6 10 49 4E 20 46 41 4E 54 41 53 59 20 47 41 4D 45 53
IN FANTASY GAMES
LSA. PUSH #(PC+1) POINTER TO THE STRING
5165 00 SLDC. PUSH #0000
5166 CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
5169 C7 F4 01 LDCI. PUSH #01F4
516C CE 05 CLP. CALL CHILD PROCEDURE: 05
516E C7 AC 3F LDCI. PUSH #3FAC
5171 91 NGI. PUSH -(TOS) (2'S COMP)
5172 AE 02 CIP. CALL INTERMEDIATE PROCEDURE: 02
5174 C7 A9 3F LDCI. PUSH #3FA9
5177 91 NGI. PUSH -(TOS) (2'S COMP)
5178 AE 02 CIP. CALL INTERMEDIATE PROCEDURE: 02
517A C7 AE 3F LDCI. PUSH #3FAE
517D 91 NGI. PUSH -(TOS) (2'S COMP)
517E AE 02 CIP. CALL INTERMEDIATE PROCEDURE: 02
5180 C7 B0 3F LDCI. PUSH #3FB0
5183 91 NGI. PUSH -(TOS) (2'S COMP)
5184 AE 02 CIP. CALL INTERMEDIATE PROCEDURE: 02
5186 B6 03 03 LOD. PUSH ACTREC(-03).03
5189 0C SLDC. PUSH #000C
518A 00 SLDC. PUSH #0000
518B CD 00 11 CXP. CALL EXTERNAL PROCEDURE: 11 IN SEGMENT: 00
518E 29 SLDC. PUSH #0029
518F 00 SLDC. PUSH #0000
5190 CD 00 1D CXP. CALL EXTERNAL PROCEDURE: 1D IN SEGMENT: 00
5193 B2 01 03 LDA. PUSH #ACTREC(-01).03
5196 00 SLDC. PUSH #0000
5197 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
5199 B2 01 03 LDA. PUSH #ACTREC(-01).03
519C 00 SLDC. PUSH #0000
519D A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
519F F8 SIND. PUSH (TOS)^.0
51A0 CD 01 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 01
51A3 00 SLDC. PUSH #0000
51A4 CC 04 STL. MP.04 := (TOS)
51A6 04 SLDC. PUSH #0004
51A7 CC 05 STL. MP.05 := (TOS)
51A9 01 SLDC. PUSH #0001
51AA CC 02 STL. MP.02 := (TOS)
51AC 14 SLDC. PUSH #0014
51AD CC 06 STL. MP.06 := (TOS)
51AF D9 SLDL. PUSH MP.02
51B0 DD SLDL. PUSH MP.06
51B1 C8 LEQI. PUSH ((TOS-1) <= (TOS))
51B2 A1 0C UJP. IF NOT (TOS) THEN JUMP TO 51C0
51B4 0F SLDC. PUSH #000F
51B5 CE 05 CLP. CALL CHILD PROCEDURE: 05
51B7 CE 06 CLP. CALL CHILD PROCEDURE: 06
51B9 D9 SLDL. PUSH MP.02
51BA 01 SLDC. PUSH #0001
51BB 82 ADI. PUSH ((TOS) + (TOS-1))
51BC CC 02 STL. MP.02 := (TOS)
51BE B9 F6 UJP. JUMP TO 51AF
51C0 01 SLDC. PUSH #0001
51C1 CC 02 STL. MP.02 := (TOS)
51C3 18 SLDC. PUSH #0018
51C4 CC 06 STL. MP.06 := (TOS)
51C6 D9 SLDL. PUSH MP.02
51C7 DD SLDL. PUSH MP.06
51C8 C8 LEQI. PUSH ((TOS-1) <= (TOS))
51C9 A1 20 UJP. IF NOT (TOS) THEN JUMP TO 51EB
51CB 01 SLDC. PUSH #0001
51CC CC 01 STL. MP.01 := (TOS)
51CE 02 SLDC. PUSH #0002
51CF CC 07 STL. MP.07 := (TOS)
51D1 D8 SLDL. PUSH MP.01
51D2 DE SLDL. PUSH MP.07
51D3 C8 LEQI. PUSH ((TOS-1) <= (TOS))
51D4 A1 0C UJP. IF NOT (TOS) THEN JUMP TO 51E2
51D6 0C SLDC. PUSH #000C
51D7 CE 05 CLP. CALL CHILD PROCEDURE: 05
51D9 CE 06 CLP. CALL CHILD PROCEDURE: 06
51DB D8 SLDL. PUSH MP.01
51DC 01 SLDC. PUSH #0001
51DD 82 ADI. PUSH ((TOS) + (TOS-1))
51DE CC 01 STL. MP.01 := (TOS)
51E0 B9 F4 UJP. JUMP TO 51D1
51E2 CE 07 CLP. CALL CHILD PROCEDURE: 07
51E4 D9 SLDL. PUSH MP.02
51E5 01 SLDC. PUSH #0001
51E6 82 ADI. PUSH ((TOS) + (TOS-1))
51E7 CC 02 STL. MP.02 := (TOS)
51E9 B9 F2 UJP. JUMP TO 51C6
51EB B2 01 03 LDA. PUSH #ACTREC(-01).03
51EE 00 SLDC. PUSH #0000
51EF A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
51F1 B2 01 03 LDA. PUSH #ACTREC(-01).03
51F4 08 SLDC. PUSH #0008
51F5 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
51F7 F8 SIND. PUSH (TOS)^.0
51F8 CD 01 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 01
51FB CE 06 CLP. CALL CHILD PROCEDURE: 06
51FD 09 SLDC. PUSH #0009
51FE CC 02 STL. MP.02 := (TOS)
5200 17 SLDC. PUSH #0017
5201 CC 06 STL. MP.06 := (TOS)
5203 D9 SLDL. PUSH MP.02
5204 DD SLDL. PUSH MP.06
5205 C8 LEQI. PUSH ((TOS-1) <= (TOS))
5206 A1 30 UJP. IF NOT (TOS) THEN JUMP TO 5238
5208 01 SLDC. PUSH #0001
5209 CC 01 STL. MP.01 := (TOS)
520B 02 SLDC. PUSH #0002
520C CC 07 STL. MP.07 := (TOS)
520E D8 SLDL. PUSH MP.01
520F DE SLDL. PUSH MP.07
5210 C8 LEQI. PUSH ((TOS-1) <= (TOS))
5211 A1 0E UJP. IF NOT (TOS) THEN JUMP TO 5221
5213 05 SLDC. PUSH #0005
5214 D9 SLDL. PUSH MP.02
5215 82 ADI. PUSH ((TOS) + (TOS-1))
5216 CE 05 CLP. CALL CHILD PROCEDURE: 05
5218 CE 06 CLP. CALL CHILD PROCEDURE: 06
521A D8 SLDL. PUSH MP.01
521B 01 SLDC. PUSH #0001
521C 82 ADI. PUSH ((TOS) + (TOS-1))
521D CC 01 STL. MP.01 := (TOS)
521F B9 F0 UJP. JUMP TO 520E
5221 B2 01 03 LDA. PUSH #ACTREC(-01).03
5224 00 SLDC. PUSH #0000
5225 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
5227 B2 01 03 LDA. PUSH #ACTREC(-01).03
522A D9 SLDL. PUSH MP.02
522B A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
522D F8 SIND. PUSH (TOS)^.0
522E CD 01 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 01
5231 D9 SLDL. PUSH MP.02
5232 01 SLDC. PUSH #0001
5233 82 ADI. PUSH ((TOS) + (TOS-1))
5234 CC 02 STL. MP.02 := (TOS)
5236 B9 EE UJP. JUMP TO 5203
5238 18 SLDC. PUSH #0018
5239 CC 02 STL. MP.02 := (TOS)
523B 20 SLDC. PUSH #0020
523C CC 06 STL. MP.06 := (TOS)
523E D9 SLDL. PUSH MP.02
523F DD SLDL. PUSH MP.06
5240 C8 LEQI. PUSH ((TOS-1) <= (TOS))
5241 A1 2E UJP. IF NOT (TOS) THEN JUMP TO 5271
5243 01 SLDC. PUSH #0001
5244 CC 01 STL. MP.01 := (TOS)
5246 04 SLDC. PUSH #0004
5247 CC 07 STL. MP.07 := (TOS)
5249 D8 SLDL. PUSH MP.01
524A DE SLDL. PUSH MP.07
524B C8 LEQI. PUSH ((TOS-1) <= (TOS))
524C A1 0C UJP. IF NOT (TOS) THEN JUMP TO 525A
524E 0A SLDC. PUSH #000A
524F CE 05 CLP. CALL CHILD PROCEDURE: 05
5251 CE 06 CLP. CALL CHILD PROCEDURE: 06
5253 D8 SLDL. PUSH MP.01
5254 01 SLDC. PUSH #0001
5255 82 ADI. PUSH ((TOS) + (TOS-1))
5256 CC 01 STL. MP.01 := (TOS)
5258 B9 EC UJP. JUMP TO 5249
525A B2 01 03 LDA. PUSH #ACTREC(-01).03
525D 00 SLDC. PUSH #0000
525E A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
5260 B2 01 03 LDA. PUSH #ACTREC(-01).03
5263 D9 SLDL. PUSH MP.02
5264 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
5266 F8 SIND. PUSH (TOS)^.0
5267 CD 01 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 01
526A D9 SLDL. PUSH MP.02
526B 01 SLDC. PUSH #0001
526C 82 ADI. PUSH ((TOS) + (TOS-1))
526D CC 02 STL. MP.02 := (TOS)
526F B9 EA UJP. JUMP TO 523E
5271 01 SLDC. PUSH #0001
5272 CC 02 STL. MP.02 := (TOS)
5274 28 SLDC. PUSH #0028
5275 CC 06 STL. MP.06 := (TOS)
5277 D9 SLDL. PUSH MP.02
5278 DD SLDL. PUSH MP.06
5279 C8 LEQI. PUSH ((TOS-1) <= (TOS))
527A A1 0C UJP. IF NOT (TOS) THEN JUMP TO 5288
527C 0C SLDC. PUSH #000C
527D CE 05 CLP. CALL CHILD PROCEDURE: 05
527F CE 06 CLP. CALL CHILD PROCEDURE: 06
5281 D9 SLDL. PUSH MP.02
5282 01 SLDC. PUSH #0001
5283 82 ADI. PUSH ((TOS) + (TOS-1))
5284 CC 02 STL. MP.02 := (TOS)
5286 B9 E8 UJP. JUMP TO 5277
5288 01 SLDC. PUSH #0001
5289 CC 02 STL. MP.02 := (TOS)
528B 50 SLDC. PUSH #0050
528C CC 06 STL. MP.06 := (TOS)
528E D9 SLDL. PUSH MP.02
528F DD SLDL. PUSH MP.06
5290 C8 LEQI. PUSH ((TOS-1) <= (TOS))
5291 A1 13 UJP. IF NOT (TOS) THEN JUMP TO 52A6
5293 B2 01 01 LDA. PUSH #ACTREC(-01).01
5296 00 SLDC. PUSH #0000
5297 CD 01 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 01
529A 07 SLDC. PUSH #0007
529B CE 05 CLP. CALL CHILD PROCEDURE: 05
529D CE 06 CLP. CALL CHILD PROCEDURE: 06
529F D9 SLDL. PUSH MP.02
52A0 01 SLDC. PUSH #0001
52A1 82 ADI. PUSH ((TOS) + (TOS-1))
52A2 CC 02 STL. MP.02 := (TOS)
52A4 B9 E6 UJP. JUMP TO 528E
52A6 01 SLDC. PUSH #0001
52A7 CC 02 STL. MP.02 := (TOS)
52A9 28 SLDC. PUSH #0028
52AA CC 06 STL. MP.06 := (TOS)
52AC D9 SLDL. PUSH MP.02
52AD DD SLDL. PUSH MP.06
52AE C8 LEQI. PUSH ((TOS-1) <= (TOS))
52AF A1 0C UJP. IF NOT (TOS) THEN JUMP TO 52BD
52B1 0C SLDC. PUSH #000C
52B2 CE 05 CLP. CALL CHILD PROCEDURE: 05
52B4 CE 06 CLP. CALL CHILD PROCEDURE: 06
52B6 D9 SLDL. PUSH MP.02
52B7 01 SLDC. PUSH #0001
52B8 82 ADI. PUSH ((TOS) + (TOS-1))
52B9 CC 02 STL. MP.02 := (TOS)
52BB B9 E4 UJP. JUMP TO 52AC
52BD AD 00 RNP. RETURN FROM NON-BASE PROCEDURE.
52BF 00 SLDC. PUSH #0000
52C0 14 SLDC. PUSH #0014
52C1 00 SLDC. PUSH #0000
52C2 34 SLDC. PUSH #0034
52C3 00 SLDC. PUSH #0000
52C4 4D SLDC. PUSH #004D
52C5 00 SLDC. PUSH #0000
52C6 88 CHK. IF (TOS-1) <= (TOS-2) <= (TOS) THEN PUSH TOS-2 ELSE ERROR
52C7 00 SLDC. PUSH #0000
52C8 7F SLDC. PUSH #007F
52C9 00 SLDC. PUSH #0000
52CA C7 00 BE LDCI. PUSH #BE00
52CD 00 SLDC. PUSH #0000
52CE 08 SLDC. PUSH #0008
52CF 01 SLDC. PUSH #0001
52D0 FF SIND. PUSH (TOS)^.7
52D1 00 SLDC. PUSH #0000
52D2 23 SLDC. PUSH #0023
52D3 01 SLDC. PUSH #0001


Lets work on this section first:

50D8 B2 01 03 LDA. PUSH #ACTREC(-01).03
50DB 00 SLDC. PUSH #0000
50DC A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
50DE B2 01 03 LDA. PUSH #ACTREC(-01).03
50E1 08 SLDC. PUSH #0008
50E2 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
50E4 F8 SIND. PUSH (TOS)^.0
50E5 CD 01 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 01

#ACTREC(-01).03 is MP03 in P070201. It is a BUFFER of 4608 INTEGERS, enough to hold 18 sectors. I will rename #ACTREC(-01).03 to BUFFER and use that name instead of MP03 in all routines.

I realize now that I misplaced the routines P070002 through P070004. At least P07002 needs to be above TITLELOA segment so that it gets the proper procedure number assigned to it.

SYSTEM.STARTUP
PROGRAM WIZBOOT P070001
$I WIZ1E:WIZUTILB
$I WIZ1E:WIZUTILC
$I WIZ1E:TITLELOA
$I WIZ1E:OPTIONS
FUNCTION P070002 : BOOLEAN; EXTERNAL;
TITLELOA; called by WIZBOOT main P070201

I neglected the parameters passed to P070002. Looks like there are 2.
Now I need to re-assemble P070002 with "2" parameters, and re-link P070002 into STARTUP.CODE. Then I can COMPILE STARTUP and have the P070002( 0, 0) call work properly in P070204.

Procedure: 02 might be a PROCEDURE and not a FUNCTION as in LOL.

This is my first try at the first instruction in P070204:

P070002( BUFFER[ 0], BUFFER[ 8]);

My first attempt at declaring BUFFER was wrong (see 5084 and 5085 below):

BUFFER : ARRAY[ 1..4608] OF CHAR;

5080 B2 01 03 LDA. PUSH #ACTREC(-01).03
5083 00 SLDC. PUSH #0000
5084 01 SLDC. PUSH #0001
5085 95 SBI. PUSH ((TOS-1) - (TOS))
5086 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01

Therefore, I need to start the index for BUFFER at 0, not 1, and of course adjust 4608 to 4607.

This is what it now generates:

5080 B2 01 03 LDA. PUSH #ACTREC(-01).03
5083 00 SLDC. PUSH #0000
5084 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
5086 F8 SIND. PUSH (TOS)^.0
5087 B2 01 03 LDA. PUSH #ACTREC(-01).03
508A 08 SLDC. PUSH #0008
508B A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
508D F8 SIND. PUSH (TOS)^.0
508E 00 SLDC. PUSH #0000
508F 00 SLDC. PUSH #0000
5090 CD 01 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 01

But line 5086 is wrong. It is pushing a value from the array onto the stack, but the code we want pushes only the pointer. We don't want line 5086 to be generated at all. Therefore, this is telling me to change the parameter passage to P070002 to be by REFERENCE (VAR) and not by VALUE (no VAR).

Note the second parameter IS passed by value as deteremined by the instruction at 508D above which we want.

The 2 pushes of #0 are extra noise for calling an EXTERNAL procedure.

Since the code we want does not immediately do something with a value after calling PROCEDURE: 02, this is therefore a PROCEDURE and not a FUNCTION.

This code generates the first instruction properly:

141 1 2:D 1 PROCEDURE P070002( VAR A1:INTEGER; A2:INTEGER); EXTERNAL; (* FORMERLY COPYPROT *)
973 8 4:0 0 BEGIN (* P070204 *)
974 8 4:1 0 P070002( BUFFER[ 0], BUFFER[ 8]);
975 8 4:0 16 END;

921 8 1:D 1 SEGMENT PROCEDURE TITLELOA; (* P070201 *)
936 8 1:D 3 BUFFER : ARRAY[ 0..4607] OF INTEGER;

P070002.TEXT:
.PROC P070002,2 ; WITH 2 PARAMETERS PASSED INTO (FORMERLY COPYPROT)


This took a lot more time to fix up than I thought it should. It took me as much time to re-engineer that first instruction as it did for the rest of the entire procedure!

There is an instruction in P070204 that de-compiles and uses MP01 in the calling procedure( P070201). Since P070204 has its own variable named MP01 I have changed MP01 in P070201 to MPXX01 for now.

The rest of this procedure is easy to re-engineer once you realize it is mostly GOTOXY() and WRITE().

Here is the code for P070204:

959 8 4:D 1 PROCEDURE P070204;
960 8 4:D 1
961 8 4:D 1 VAR
962 8 4:D 1 MP01 : INTEGER;
963 8 4:D 2 MP02 : INTEGER;
964 8 4:D 3 MP03 : INTEGER;
965 8 4:D 4 MP04 : INTEGER;
966 8 4:D 5 MP05 : INTEGER;
967 8 4:D 6 MP06 : INTEGER;
968 8 4:D 7 MP07 : INTEGER;
969 8 4:D 8
970 8 4:D 8
971 8 5:D 1 PROCEDURE P070205( MP01 : INTEGER);
972 8 5:0 0 BEGIN
973 8 5:0 0 END;
974 8 5:0 12
975 8 6:D 1 PROCEDURE P070206;
976 8 6:0 0 BEGIN
977 8 6:0 0 END;
978 8 6:0 12
979 8 7:D 1 PROCEDURE P070207;
980 8 7:0 0 BEGIN
981 8 7:0 0 END;
982 8 7:0 12
983 8 4:0 0 BEGIN (* P070204 *)
984 8 4:1 0 P070002( BUFFER[ 0], BUFFER[ 8]);
985 8 4:1 16 MP1203.I := 8192; (* $2000 *)
986 8 4:1 23 FILLCHAR( MP1203.P^, 8192, 0);
987 8 4:1 34 WRITE( CHR(12)); (* LINEFEED (?) *)
988 8 4:1 42 GOTOXY( 12, 10);
989 8 4:1 47 WRITE( 'PREPARE YOURSELF');
990 8 4:1 73 P070205( 150); (* $96 *)
991 8 4:1 78 GOTOXY( 12, 12);
992 8 4:1 83 WRITE( 'FOR THE ULTIMATE');
993 8 4:1 109 P070205( 150); (* $96 *)
994 8 4:1 114 GOTOXY( 12, 14);
995 8 4:1 119 WRITE( 'IN FANTASY GAMES');
996 8 4:1 145 P070205( 500); (* $1F4 *)
997 8 4:1 150
998 8 4:1 150 P070202( -16300); (* $3FAC *)
999 8 4:1 156 P070202( -16297); (* $3FA9 *)
1000 8 4:1 162 P070202( -16302); (* $3FAE *)
1001 8 4:1 168 P070202( -16304); (* $3FB0 *)
1002 8 4:1 174
1003 8 4:1 174 WRITE( CHR( 12));
1004 8 4:1 182 GOTOXY( 41, 0); (* OFF SCREEN *)
1005 8 4:1 187
1006 8 4:1 187 P070002( BUFFER[ 0], BUFFER[ 0]);
1007 8 4:1 203 MP04 := 0;
1008 8 4:1 206 MP05 := 4;
1009 8 4:1 209 MP02 := 1;
1010 8 4:1 212 MP06 := 20;
1011 8 4:1 215
1012 8 4:1 215 WHILE MP02 <= MP06 DO
1013 8 4:2 220 BEGIN
1014 8 4:3 220 P070205( 15);
1015 8 4:3 223 P070206;
1016 8 4:3 225 MP02 := MP02 + 1;
1017 8 4:2 230 END;
1018 8 4:2 232
1019 8 4:1 232 MP02 := 1;
1020 8 4:1 235 MP06 := 24;
1021 8 4:1 238 WHILE MP02 <= MP06 DO
1022 8 4:2 243 BEGIN
1023 8 4:3 243 MP01 := 1;
1024 8 4:3 246 MP07 := 2;
1025 8 4:3 249 WHILE MP01 <= MP07 DO
1026 8 4:4 254 BEGIN
1027 8 4:5 254 P070205( 12);
1028 8 4:5 257 P070206;
1029 8 4:5 259 MP01 := MP01 + 1
1030 8 4:4 260 END;
1031 8 4:3 266 P070207;
1032 8 4:3 268 MP02 := MP02 + 1;
1033 8 4:2 273 END;
1034 8 4:1 275 P070002( BUFFER[ 0], BUFFER[ 8]);
1035 8 4:1 291 P070206;
1036 8 4:1 293 MP02 := 9;
1037 8 4:1 296 MP06 := 23;
1038 8 4:1 299 WHILE MP02 <= MP06 DO
1039 8 4:2 304 BEGIN
1040 8 4:3 304 MP01 := 1;
1041 8 4:3 307 MP07 := 2;
1042 8 4:3 310 WHILE MP01 <= MP07 DO
1043 8 4:4 315 BEGIN
1044 8 4:5 315 P070205( 5 + MP02);
1045 8 4:5 320 P070206;
1046 8 4:5 322 MP01 := MP01 + 1
1047 8 4:4 323 END;
1048 8 4:3 329 P070002( BUFFER[ 0], BUFFER[ MP02]);
1049 8 4:3 345 MP02 := MP02 + 1
1050 8 4:2 346 END;
1051 8 4:1 352 MP02 := 24;
1052 8 4:1 355 MP06 := 32;
1053 8 4:1 358 WHILE MP02 <= MP06 DO
1054 8 4:2 363 BEGIN
1055 8 4:3 363 MP01 := 1;
1056 8 4:3 366 MP07 := 4;
1057 8 4:3 369 WHILE MP01 <= MP07 DO
1058 8 4:4 374 BEGIN
1059 8 4:5 374 P070205( 10);
1060 8 4:5 377 P070206;
1061 8 4:5 379 MP01 := MP01 + 1
1062 8 4:4 380 END;
1063 8 4:3 386 P070002( BUFFER[ 0], BUFFER[ MP02]);
1064 8 4:3 402 MP02 := MP02 + 1
1065 8 4:2 403 END;
1066 8 4:1 409 MP02 := 1;
1067 8 4:1 412 MP06 := 40;
1068 8 4:1 415 WHILE MP02 <= MP06 DO
1069 8 4:2 420 BEGIN
1070 8 4:3 420 P070205( 12);
1071 8 4:3 423 P070206;
1072 8 4:3 425 MP02 := MP02 + 1;
1073 8 4:2 430 END;
1074 8 4:1 432 MP02 := 1;
1075 8 4:1 435 MP06 := 80;
1076 8 4:1 438 WHILE MP02 <= MP06 DO
1077 8 4:2 443 BEGIN
1078 8 4:3 443 P070002( MPXX01, 0);
1079 8 4:3 450 P070205( 7); (* BELL *)
1080 8 4:3 453 P070206;
1081 8 4:3 455 MP02 := MP02 + 1
1082 8 4:2 456 END;
1083 8 4:2 462
1084 8 4:1 462 MP02 := 1;
1085 8 4:1 465 MP06 := 40;
1086 8 4:1 468 WHILE MP02 <= MP06 DO
1087 8 4:2 473 BEGIN
1088 8 4:3 473 P070205( 12);
1089 8 4:3 476 P070206;
1090 8 4:3 478 MP02 := MP02 + 1
1091 8 4:2 479 END
1092 8 4:0 483 END;

The 3 child procedures to P070204 were easy and follow in order:
P070205
P070206
P070207

P070205 Pcode:

FILE: 7 SEG: 2 PROC: 5

JTAB FOR SUBROUTINE 5:
DATA SIZE: 0
PARAM SIZE: 2
EXIT AT: 5077
ENTER AT: 505C
PROC NUMBER: 5
LEXICAL LEVEL: 3
505C 29 SLDC. PUSH #0029
505D 00 SLDC. PUSH #0000
505E CD 00 1D CXP. CALL EXTERNAL PROCEDURE: 1D IN SEGMENT: 00
5061 D8 SLDL. PUSH MP.01
5062 00 SLDC. PUSH #0000
5063 C5 GRTI. PUSH ((TOS-1) > (TOS))
5064 A1 11 UJP. IF NOT (TOS) THEN JUMP TO 5077
5066 00 SLDC. PUSH #0000
5067 00 SLDC. PUSH #0000
5068 AE 03 CIP. CALL INTERMEDIATE PROCEDURE: 03
506A A1 04 UJP. IF NOT (TOS) THEN JUMP TO 5070
506C 08 SLDC. PUSH #0008
506D 04 SLDC. PUSH #0004
506E 9E 04 EXIT. EXIT FROM PROCEDURE. (TOS)=PROC# (TOS-1)=SEG#
5070 D8 SLDL. PUSH MP.01
5071 01 SLDC. PUSH #0001
5072 95 SBI. PUSH ((TOS-1) - (TOS))
5073 CC 01 STL. MP.01 := (TOS)
5075 B9 F6 UJP. JUMP TO 5061
5077 AD 00 RNP. RETURN FROM NON-BASE PROCEDURE.
5079 00 SLDC. PUSH #0000
507A 19 SLDC. PUSH #0019
507B 00 SLDC. PUSH #0000


P070205 Pascal code:

971 8 5:D 1 PROCEDURE P070205( MP01 : INTEGER);
972 8 5:0 0 BEGIN
973 8 5:1 0 GOTOXY( 41, 0);
974 8 5:1 5 WHILE MP01 > 0 DO
975 8 5:2 10 BEGIN
976 8 5:3 10 IF P070203 THEN
977 8 5:4 16 EXIT( P070204);
978 8 5:3 20 MP01 := MP01 - 1;
979 8 5:2 25 END;
980 8 5:0 27 END;


P070206 pcode:

FILE: 7 SEG: 2 PROC: 6

JTAB FOR SUBROUTINE 6:
DATA SIZE: 0
PARAM SIZE: 0
EXIT AT: 50A2
ENTER AT: 5086
PROC NUMBER: 6
LEXICAL LEVEL: 3
5086 01 SLDC. PUSH #0001
5087 B6 01 04 LOD. PUSH ACTREC(-01).04
508A 03 SLDC. PUSH #0003
508B 8E MODI. PUSH ((TOS-1) MOD (TOS))
508C 82 ADI. PUSH ((TOS) + (TOS-1))
508D B8 01 04 STR. ACTREC(-01).04 := TOS
5090 B2 02 03 LDA. PUSH #ACTREC(-02).03
5093 00 SLDC. PUSH #0000
5094 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
5096 B2 02 03 LDA. PUSH #ACTREC(-02).03
5099 B6 01 04 LOD. PUSH ACTREC(-01).04
509C A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
509E F8 SIND. PUSH (TOS)^.0
509F CD 01 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 01
50A2 AD 00 RNP. RETURN FROM NON-BASE PROCEDURE.


P070206 Pascal code:

983 8 6:D 1 PROCEDURE P070206;
984 8 6:D 1
985 8 6:0 0 BEGIN
986 8 6:1 0 MP04 := 1 + (MP04 MOD 3);
987 8 6:1 10 P070002( BUFFER[ 0], BUFFER[ MP04])
988 8 6:0 25 END;


P070207 pcode

FILE: 7 SEG: 2 PROC: 7

JTAB FOR SUBROUTINE 7:
DATA SIZE: 0
PARAM SIZE: 0
EXIT AT: 50CC
ENTER AT: 50AE
PROC NUMBER: 7
LEXICAL LEVEL: 3
50AE 05 SLDC. PUSH #0005
50AF B6 01 05 LOD. PUSH ACTREC(-01).05
50B2 04 SLDC. PUSH #0004
50B3 95 SBI. PUSH ((TOS-1) - (TOS))
50B4 03 SLDC. PUSH #0003
50B5 8E MODI. PUSH ((TOS-1) MOD (TOS))
50B6 82 ADI. PUSH ((TOS) + (TOS-1))
50B7 B8 01 05 STR. ACTREC(-01).05 := TOS
50BA B2 02 03 LDA. PUSH #ACTREC(-02).03
50BD 00 SLDC. PUSH #0000
50BE A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
50C0 B2 02 03 LDA. PUSH #ACTREC(-02).03
50C3 B6 01 05 LOD. PUSH ACTREC(-01).05
50C6 A4 01 IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=01
50C8 F8 SIND. PUSH (TOS)^.0
50C9 CD 01 02 CXP. CALL EXTERNAL PROCEDURE: 02 IN SEGMENT: 01
50CC AD 00 RNP. RETURN FROM NON-BASE PROCEDURE.

P070207 Pascal code:

991 8 7:D 1 PROCEDURE P070207;
992 8 7:D 1
993 8 7:0 0 BEGIN
994 8 7:1 0 MP05 := 5 + ((MP05 - 4) MOD 3);
995 8 7:1 12 P070002( BUFFER[ 0], BUFFER[ MP05])
996 8 7:0 27 END;


At this point, all of WIZBOOT and all of TITLELOA are completed.

SYSTEM.STARTUP

Segment: Procedures
0 (1) WIZBOOT 5
1 (7) UTILS 36
2 (8) TITLELOA 8
3 (9) OPTIONS 1

Up next is P070301 (SEGMENT OPTIONS)

TommyGoog

unread,
Apr 19, 2014, 12:22:57 AM4/19/14
to
On Tuesday, April 15, 2014 11:51:01 PM UTC-5, qkumba wrote:

>
> 511A... - looks like LZW decompression routine.
>

Here's something to brighten your day (I hope).

I don't doubt that the code at 511A in Wizardry I is *some* kind of decompression, but there might be a liiiiiittle problem with calling it LZW.

Copyright notice displayed by the software for Wizardry I:

COPYRIGHT (C)1981

LZW described in Wikipedia:

Lempel-Ziv-Welch (LZW) is a universal lossless data compression algorithm created by Abraham Lempel, Jacob Ziv, and Terry Welch. It was published by Welch in 1984 as an improved implementation of the LZ78 algorithm published by Lempel and Ziv in 1978.

The authors of Wizardry were good, but I don't think they were time travelers :)

And I hope by pointing this out I don't discourage you (or anyone else) from participating in this thread!

I'm posting this with a smile!

Tommy

qkumba

unread,
Apr 20, 2014, 6:27:04 PM4/20/14
to
> > 511A... - looks like LZW decompression routine.
> Here's something to brighten your day (I hope).
> I don't doubt that the code at 511A in Wizardry I is *some* kind of
> decompression, but there might be a liiiiiittle problem with calling it LZW.

Yes, I am aware that LZW did not exist at that time.
Originally, I wrote LZ, but then the auto-correct in my brain changed it to LZW, since most everything LZ-like these days is really LZW-based.

> And I hope by pointing this out I don't discourage you (or anyone else) from
> participating in this thread!

:-) No chance of that. I don't mind when people point out that I'm wrong.

Didier VALLET

unread,
Apr 21, 2014, 12:23:35 PM4/21/14
to
>
> And I hope by pointing this out I don't discourage you (or anyone else) from participating in this thread!
>
> I'm posting this with a smile!
>
> Tommy

Hello, it's crazy.
You've done more in a few days than i'm able to understand about your job.
At the start, i've try like you to see if some routines are the same in the 2 versions of wizardry.
And on an other hand, i'm looking to make a new version of wiz3 (and wiz1 first, that's the reason for me to get the source code of it) on Oric1 and Apple based on C code. It's quite difficult to understand where is starting wiz3 code in your source because there's a lot of lines and datas aren't linked to the code.

TommyGoog

unread,
Apr 23, 2014, 8:12:23 PM4/23/14
to
On Monday, April 21, 2014 11:23:35 AM UTC-5, Didier VALLET wrote:
>
>
>
> Hello, it's crazy.
>
> You've done more in a few days than i'm able to understand about your job.
>
> At the start, i've try like you to see if some routines are the same in the 2 versions of wizardry.
>
> And on an other hand, i'm looking to make a new version of wiz3 (and wiz1 first, that's the reason for me to get the source code of it) on Oric1 and Apple based on C code. It's quite difficult to understand where is starting wiz3 code in your source because there's a lot of lines and datas aren't linked to the code.

Hi Didier,

I will assume when you are asking for information about "wiz3 code" that you are referring to my program written in Applesoft Basic to take a diskette with compiled Pascal code and display the formatted pcode output.

At the end of this message I will include the source code for this "wiz3" program. To try to stop confusion about the names I am usually now calling the "wiz3" basic program "DeCompiler" (wiz3 is too similar to Wizardry III or Wizardry3).

The code for DeCompiler is not pretty, and not my best coding effort, but as a small tool it definitely made life easier for me 25 years ago and 2 years ago, and today.

DeCompiler is used to display pcode for any Pascal (1.1) diskette which contains pcode. It is not specifically written for Wizardry diskettes.

There are 2 main paths in the DeCompiler. One is if you want the program to decompile all the files and all the procedures on a diskette. The other main path is if you are interested in one particular decompiled procedure on the diskette.

These 2 mainlines are similar. The code to display "ALL" files starts at line 5100, and for just one file at line 5000.

The routine at line 5 sets up the RWTS routine in memory at $9500 as 6502 code. At line 80 is the subroutine that is called to use RWTS to read a sector of information from the diskette in drive 2 of slot 6. As noted, this routine requires input in the array RW as follows:

RW(0) : Track number
RW(1) : Sector number
RW(2) : Buffer pointer (insignificant byte)
RW(3) : Buffer pointer (significant byte)

At line 100 is code to read the Pascal Directory into memory at $8D00 to $94FF. That's 8 sectors of 256 bytes or 4 Pascal blocks.

http://code.google.com/p/profuse/wiki/PascalFileSystem is a good reference describing the Pascal directory structure.

At line 140 we look in the Pascal directory looking for files. We display the file index and the filename.

At line 200 we get the file index for the file that contains the code you are interested in. (Typing "-1" ends the program.)

Starting at line 210 we use the file index to point to the file entry in the directory. At line 212 we examine this file entry to see if it is either a Pascal Code file, or the file "SYSTEM.LIBRARY". Both of those contain pcode.

At line 217 we display the Track/Sector where the file begins on the diskette. All Pascal files written to a diskette occupy one contiguous sequence of blocks. There are no "gaps" and the file is not spread out in smaller pieces about the diskette. The information for sector is displayed in 2 formats: DOS and PASCAL. DOS and PASCAL use different numbering for sectors.

Line 222 sets up to read the "Segment sector" to $8C00 in memory. This is the "Segment Dictionary" as described in the Apple Pascal Operating System. It is described in the section "Operation of P-machine".

When interested in one procedure, we now ask for the "Segment Number" where the code resides that you are interested in. Entering "-1" takes you back to the previous prompt.

At line 285 we calculate the Track and Sector to be able to read the selected Segment into memory. The comment at line 333 says it is read into the Apples memory at $4000, but that is an old comment. It is actually read into memory at $5000.

At line 375 we ask for the address ($5000 is default) that we want to use for the segments "load address". The segment is always read into memory at $5000, but by typing a different number here, you can get different relative addresses displayed by the DeCompiler. For example, if you enter $5400, then the first instruction will be labeled $5400 and not $5000. Usually you will just want to use the default of $5000.

At line 390 we display the count of the number of PROCEDURES in this SEGMENT.

At line 420 you enter the procedure number you are interested in. Entering "-1" takes you back to a previous prompt.

At line 440 we calculate where the PROCEDURE begins in the segment.

At line 460 we display the JTAB for this procedure.

At line 480 we begin the process of de-compiling the code in the procedure. The variable P8 is similar to the "program counter" and P9 is the contents that we find at the memory pointed to by P8.

From there it is one giant case statement to process each of the different pcode instructions that are possible in P9.

If you (or anyone) needs more help in understanding "wiz3" (DeCompiler) let me know and I will try to help.

Tom Ewers (aka TommyGOOG)

As promised, here is the Basic code for the DeCompiler:

PR#1
]POKE 33,33

]LIST

1 INPUT "PROCESS ALL?";XX$
2 IF XX$ = "Y" THEN 5100
3 GOTO 5000
5 RW = 9 * 16 ^ 3 + 5 * 16 ^ 2
6 HH = 5
7 HM = HH * 16 ^ 3
10 HIMEM: HM
20 DATA A9,95,A0,09,20,D9,03,60,00,01,60,02,00,12,06,1A,95,00,40,00,00,01,00,00,60,01,00,01,EF,D8,00
30 FOR X = 0 TO 29
40 READ A$
60 A1$ = LEFT$ (A$,1)
61 A2$ = RIGHT$ (A$,1)
62 A1 = 16 * ( ASC (A1$) - ASC ("A") + 10)
63 IF A1$ < "A" THEN A1 = 16 * ( ASC (A1$) - ASC ("0"))
64 A2 = ASC (A2$) - ASC ("A") + 10
65 IF A2$ < "A" THEN A2 = ASC (A2$) - ASC ("0")
66 POKE RW + X,A1 + A2
70 NEXT X
71 READ A$
75 RETURN
80 POKE RW + 13,RW(0): REM TRACK NUMBER
81 POKE RW + 14,RW(1): REM SECTOR
82 POKE RW + 17,RW(2): REM LOW BUFF
83 POKE RW + 18,RW(3): REM HIGH BUFF
90 CALL 9 * 16 ^ 3 + 5 * 16 ^ 2
92 RETURN
100 RW(0) = 0
104 Y = 0
105 FOR X = 11 TO 4 STEP - 1
106 RW(1) = X
108 RW(2) = 0
109 RW(3) = 8 * 16 + 13 + Y
110 GOSUB 80
115 Y = Y + 1
120 NEXT X
130 DD = 8 * 16 ^ 3 + 13 * 16 ^ 2: REM DIR AT $8D00
132 FC = PEEK (DD + 16): PRINT "FILES: ";FC
133 FX = 0
135 RETURN
140 PRINT :FQ(1) = 0: REM FQ(1)=HIGHEST FILE INDEX
141 FOR X = 1 TO 77
142 D1 = DD + 26 * X: REM D1 = FILE ENTRY ADDRESS
143 IF FX > = FC THEN 198
145 IF PEEK (D1 + 4) = 0 THEN 198
146 IF PEEK (D1 + 4) > 5 THEN 198
147 PRINT X;" ";
150 FOR Y = 0 TO PEEK (D1 + 6) - 1
155 PRINT CHR$ ( PEEK (D1 + 7 + Y));
160 NEXT Y
161 FX = FX + 1
165 PRINT
167 FQ(1) = X
198 NEXT X: PRINT
199 RETURN
200 REM
201 INPUT "TYPE A FILE NUMBER (OR -1) ";FF
202 PRINT
203 RETURN
210 D1 = DD + 26 * FF: REM D1 POINTS TO FILE ENTRY IN DIRECTOR
211 T2$ = "": FOR X = 0 TO 13:T2$ = T2$ + CHR$ ( PEEK (D1 + 7 + X)): NEXT
212 FQ(4) = 0: IF ( PEEK (D1 + 4) < > 2) AND (T2$ < > "SYSTEM.LIBRARY") THEN FQ(4) = - 1: RETURN : REM FILEKIND, 2==CODEFILE
214 T1 = PEEK (D1 + 0):T2 = PEEK (D1 + 1): REM SEG T/S INFO. 5/3/1 FORMAT
215 T = INT (T1 / 8) + (T2 / 2 < > INT (T2 / 2)) * 32
216 S = (T1 - INT (T1 / 8) * 8) * 2
217 PRINT "SEGMENT T/S = ";T;"/";S;" --- PASCAL T/S"
218 IF S < > 15 AND S < > 0 THEN S = 15 - S
219 PRINT "SEGMENT T/S = ";T;"/";S;" --- DOS 3.3 T/S"
220 PRINT
221 RW(0) = T:RW(1) = S
222 RW(2) = 0:RW(3) = 8 * 16 + 12: REM READ SEGMENT SECTOR TO $8C00
225 GOSUB 80
235 SS = 8 * 16 ^ 3 + 12 * 16 ^ 2: REM SEG DICTIONARY AT BEGIN OF FILE
240 FOR X = 0 TO 15
241 IF PEEK (SS + 4 * X) = 0 AND PEEK (SS + 4 * X + 1) = 0 AND PEEK (SS + 4 * X + 2) = 0 AND PEEK (SS + 4 * X + 3) = 0 THEN 257
242 PRINT X;" ";
243 FQ(2) = X
245 FOR Y = 0 TO 7
250 PRINT CHR$ ( PEEK (SS + 64 + 8 * X + Y));
255 NEXT Y
256 PRINT
257 NEXT X
260 RETURN
280 PRINT
281 INPUT "TYPE A SEGMENT NUMBER (OR -1) ";SS
282 PRINT : IF SS > FQ(2) THEN 281
283 RETURN
285 S1 = 8 * 16 ^ 3 + 12 * 16 ^ 2 + SS * 4: REM CALC SEGMENT POINTER START FOR SS
290 T3 = PEEK (S1)
291 T4 = PEEK (S1 + 1)
295 T5 = T1 + T3
299 T6 = 0
300 IF T5 > 255 THEN T5 = T5 - 256:T6 = 1
302 T6 = T2 + T4 + T6
303 T = INT (T5 / 8) + (T6 / 2 < > INT (T6 / 2)) * 32
304 S = (T5 - INT (T5 / 8) * 8) * 2
305 SD = S
306 IF S < > 15 AND S < > 0 THEN SD = 15 - S
315 PRINT "T/S FOR SEGMENT ";T;"/";S;" --- PASCAL"
316 PRINT "T/S FOR SEGMENT ";T;"/";SD;" --- DOS "
320 LL = PEEK (S1 + 3) + ( PEEK (S1 + 2) < > 0)
322 IF LL = 0 THEN RETURN
330 RW(0) = T
331 RW(1) = SD
332 RW(2) = 0
333 RW(3) = HH * 16: REM $4000 IS WHERE SEGMENT IS READ INTO
340 FOR X = 0 TO (LL - 1)
350 GOSUB 80: REM READ A SECTOR
360 IF RW(1) = 1 THEN RW(1) = 15: GOTO 370
361 IF RW(1) = 15 THEN RW(1) = 0:RW(0) = RW(0) + 1: GOTO 370
362 IF RW(1) = 0 THEN RW(1) = 14: GOTO 370
363 RW(1) = RW(1) - 1
370 RW(3) = RW(3) + 1
371 NEXT : PRINT
372 RETURN
375 INPUT "SEGMENT'S START ADDR($5000):";A$
376 IF LEN (A$) = 0 THEN 387: REM 0 TO ADD TO P8
377 IF LEN (A$) > 4 THEN 375
379 FOR X = 0 TO LEN (A$) - 1
380 A1$ = MID$ (A$, LEN (A$) - X,1)
381 A1 = 16 * ( ASC (A1$) - ASC ("A") + 10)
382 IF A1$ < "A" THEN A1 = 16 * ( ASC (A1$) - ASC ("0"))
383 PA = PA + (16 ^ (X - 1)) * A1
385 NEXT X
386 PA = PA - HM
387 RETURN
390 PRINT
400 P1 = HH * 16 ^ 3 + PEEK (S1 + 3) * 16 ^ 2 + PEEK (S1 + 2) - 1: REM LAST BYTE IN SEGMENT IS "PROCEDURE COUNT"
410 P2 = PEEK (P1): REM P2 = NUMBER OF PROCEDURES IN SEGMENT
412 FQ(3) = P2
415 PRINT "THERE ARE ";P2;" PROCEDURES."
417 PRINT
418 RETURN
420 PRINT
421 INPUT "ENTER PROCEDURE # (OR -1) ";P3: REM P3 = PROCEDURE NUMBER
422 PRINT
425 IF P3 = - 1 THEN RETURN
430 IF P3 > P2 OR P3 < 1 THEN 420
435 RETURN
440 P4 = P1 - 2 * P3 - 1: REM P4=PTR TO SUBROUTINE POINTER
450 P5 = P4 - PEEK (P4 + 1) * 16 ^ 2 - PEEK (P4) - 8: REM P5=PTR TO BEGIN OF SUBROUTINE'S JTAB
459 PRINT
460 PRINT "JTAB FOR SUBROUTINE ";P3;":"
462 PRINT "DATA SIZE: "; PEEK (P5) + PEEK (P5 + 1) * 16 ^ 2
464 PRINT "PARAM SIZE: "; PEEK (P5 + 2) + PEEK (P5 + 3) * 16 ^ 2
465 P6 = P5 + 4 - ( PEEK (P5 + 4) + PEEK (P5 + 5) * 16 ^ 2): REM P6=EXIT ADDRESS
466 PRINT "EXIT AT: ";:A = P6 + PA: GOSUB 550: PRINT A$
467 P7 = P5 + 6 - ( PEEK (P5 + 6) + PEEK (P5 + 7) * 16 ^ 2): REM P7=START ADDRESS
468 PRINT "ENTER AT: ";:A = P7 + PA: GOSUB 550: PRINT A$
470 PRINT "PROC NUMBER: "; PEEK (P5 + 8)
472 IF PEEK (P5 + 8) = 0 THEN PRINT "6502 CODE": RETURN
475 PRINT "LEXICAL LEVEL: "; PEEK (P5 + 9)
477 REM RETURN
480 P8 = P7: REM P8 IS THE PROGRAM-COUNTER
500 P9 = PEEK (P8): REM P9=CONTENTS AT PC
501 IF P8 > = P5 THEN RETURN
502 A = P8 + PA: GOSUB 550: PRINT A$;" ";
503 A = P9: GOSUB 550: PRINT RIGHT$ (A$,2);" ";
510 IF P9 < 128 THEN 1000
520 ON P9 - 127 GOTO 1280,1290,1300,1310,1320,1330,1340,1350,1360,1370,1380,1390,1400,1410,1420,1430,1440,1450,1460,1470,1480,1490,1500,1510,1520,1530,1540,1550,1560,1570,1580,1590,1600,1610,1620,1630,1640,1650,1660,1670,1680,1690,1700
522 ON P9 - 170 GOTO 1710,1720,1730,1740,1750,1760,1770,1780,1790,1800,1810,1820,1830,1840,1850,1860,1870,1880,1890,1900,1910,1920,1930,1940,1950,1960,1970,1980,1990,2000,2010,2020,2030,2040,2050,2060,2070,2080,2090,2100
524 ON P9 - 210 GOTO 2110,2120,2130,2140,2150,2160,2170,2180,2190,2200,2210,2220,2230,2240,2250,2260,2270,2280,2290,2300,2310,2320,2320,2320,2320,2320,2320,2320,2320,2320,2320,2320,2320,2320,2320,2320,2320,2480,2480,2480
526 ON P9 - 250 GOTO 2480,2480,2480,2480,2480
530 PRINT
531 P8 = P8 + 1: GOTO 500
532 P8 = P8 + 2: GOTO 500
533 P8 = P8 + 3: GOTO 500
534 P8 = P8 + 4: GOTO 500
550 REM A=DECIMAL NUMBER. RETURNS A$=4 DIGIT HEX NUMBER
551 A$ = ""
552 FOR A1 = 3 TO 0 STEP - 1
555 A2 = INT (A / 16 ^ A1)
556 A = A - A2 * 16 ^ A1
557 IF A2 > 9 THEN A$ = A$ + CHR$ ( ASC ("A") + A2 - 10): GOTO 559
558 A$ = A$ + CHR$ ( ASC ("0") + A2)
559 NEXT
560 RETURN
1000 PRINT " SLDC. PUSH #";:A = P9: GOSUB 550: PRINT A$
1001 GOTO 531
1100 REM GIVEN B1 DETERMINE "B"IG AND PRINT IT (SPLIT RAW FORMAT)
1102 A = PEEK (B1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1103 IF PEEK (B1) > 127 THEN A = PEEK (B1 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";: RETURN
1104 PRINT " ";: RETURN
1119 REM GIVEN B1 DETERMINE "B"IG AND PRINT IT (XX OR XXXX)
1120 B = PEEK (B1): IF B > 127 THEN B = ( PEEK (B1) - 128) * 256 + PEEK (B1 + 1)
1121 A = B: GOSUB 550: PRINT RIGHT$ (A$,2 + 2 * (B > 255));
1122 RETURN
1130 IF B1 > 127 THEN 532
1131 GOTO 531
1280 PRINT SPC( 9);"ABI. PUSH ABS( (TOS) ) )
1281 GOTO 531
1290 PRINT SPC( 9);"ABR. PUSH ABS( (TOS) ) )
1291 GOTO 531
1300 PRINT SPC( 9);"ADI. PUSH ((TOS) + (TOS-1))
1301 GOTO 531
1310 PRINT SPC( 9);"ADR. PUSH ((TOS) + (TOS-1))
1311 GOTO 531
1320 PRINT SPC( 9);"LAND. PUSH ((TOS-1) AND (TOS))
1321 GOTO 531
1330 PRINT SPC( 9);"DIF. DIFFERENCE OF SETS (TOS) AND (TOS-1)": GOTO 531
1340 PRINT SPC( 9);"DVI. PUSH ((TOS-1) / (TOS))
1341 GOTO 531
1350 PRINT SPC( 9);"DVR PUSH ((TOS-1) / (TOS))
1351 GOTO 531
1360 PRINT SPC( 9);"CHK. IF (TOS-1) <= (TOS-2) <= (TOS) THEN PUSH TOS-2 ELSE ERROR
1361 GOTO 531
1370 PRINT SPC( 9);"FLO. PUSH ( REAL(TOS-1))
1371 GOTO 531
1380 PRINT SPC( 9);"FLT. PUSH ( REAL(TOS) )
1381 GOTO 531
1390 PRINT SPC( 9);"INN. PUSH TRUE IF (TOS-1) IN SET (TOS)": GOTO 531
1400 PRINT SPC( 9);"INT. INTERSECTION OF SETS (TOS) AND (TOS-1)": GOTO 531
1410 PRINT SPC( 9);"LOR. PUSH ((TOS-1) OR (TOS))
1411 GOTO 531
1420 PRINT SPC( 9);"MODI. PUSH ((TOS-1) MOD (TOS))
1421 GOTO 531
1430 PRINT SPC( 9);"MPI. PUSH ((TOS-1) * (TOS))
1431 GOTO 531
1440 PRINT SPC( 9);"MPR. PUSH ((TOS) * (TOS))
1441 GOTO 531
1450 PRINT SPC( 9);"NGI. PUSH -(TOS) (2'S COMP)
1451 GOTO 531
1460 PRINT SPC( 9);"NGR. PUSH -(TOS)
1461 GOTO 531
1470 PRINT SPC( 9);"LNOT. PUSH -(TOS) (1'S COMP)
1471 GOTO 531
1480 PRINT SPC( 9);"SRS.": GOTO 2560
1490 PRINT SPC( 9);"SBI. PUSH ((TOS-1) - (TOS))
1491 GOTO 531
1500 PRINT SPC( 9);"SBR. PUSH ((TOS-1) - (TOS))
1501 GOTO 531
1510 PRINT SPC( 9);"SGS.": GOTO 2560
1520 PRINT SPC( 9);"SQI. PUSH ((TOS)**2)
1521 GOTO 531
1530 PRINT SPC( 9);"SQR. PUSH ((TOS)**2)
1531 GOTO 531
1540 PRINT " STO. (TOS-1)^ := (TOS)
1541 GOTO 531
1550 PRINT SPC( 9);"IXS. PUSH #((TOS-1)^.(TOS)) --INDEX STRING ARRAY"
1551 GOTO 531
1560 PRINT SPC( 9);"UNI. UNION OF SETS (TOS) OR (TOS-1)": GOTO 531
1570 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1571 B1 = P8 + 2: GOSUB 1100: PRINT "LDE. PUSH DATASEG(";
1572 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);").";
1573 B1 = P8 + 2: GOSUB 1100: PRINT
1575 IF PEEK (P8 + 2) > 127 THEN 534
1576 GOTO 533
1580 REM MANY SUB FUNCTIONS TO THIS ONE
1581 GOTO 3000: REM 158
1590 PRINT SPC( 9);"LDCN. PUSH #0000"
1591 GOTO 531
1600 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2); SPC( 7);"ADJ. ";"ADJ SET TO "; RIGHT$ (A$,2);" WORDS"
1601 GOTO 532
1610 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2); SPC( 7);"UJP. IF NOT (TOS) THEN JUMP TO ";
1611 A = PEEK (P8 + 1): IF A < 128 THEN A = P8 + A + 2: GOTO 1615
1612 X = P5 + 8 - 256 + A
1613 A = X - PEEK (X) - PEEK (X + 1) * 256
1615 A = A + PA: GOSUB 550: PRINT A$
1616 GOTO 532
1620 B1 = P8 + 1: GOSUB 1100: PRINT " INC. PUSH #(TOS)^.(";
1621 B1 = P8 + 1: GOSUB 1120: PRINT ")"
1622 IF PEEK (P8 + 1) > 127 THEN 533
1623 GOTO 532
1630 B1 = P8 + 1: GOSUB 1100: PRINT " IND. PUSH (TOS)^.";:B1 = P8 + 1: GOSUB 1120: PRINT
1632 IF PEEK (P8 + 1) > 127 THEN GOTO 533
1633 GOTO 532
1640 B1 = P8 + 1: GOSUB 1100: PRINT " IXA. PUSH #((TOS-1)[TOS]). ARRAY SIZE=";
1641 B1 = P8 + 1: GOSUB 1120: PRINT
1642 IF PEEK (P8 + 1) > 127 THEN 533
1643 GOTO 532
1650 B1 = P8 + 1: GOSUB 1100: REM PRINT "B"IG WORD
1651 PRINT " LA0. PUSH #BASE.";:B1 = P8 + 1: GOSUB 1120: PRINT
1652 IF PEEK (P8 + 1) > 127 THEN 533
1653 GOTO 532
1660 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";: IF PEEK (P8 + 1) < = 0 THEN 1662
1661 FOR X = 1 TO PEEK (P8 + 1):A = PEEK (P8 + 1 + X): GOSUB 550: PRINT RIGHT$ (A$,2);" ";: NEXT X
1662 PRINT : FOR X = 1 TO PEEK (P8 + 1): PRINT CHR$ ( PEEK (P8 + 1 + X));: NEXT
1663 PRINT : PRINT SPC( 17);"LSA. PUSH #(PC+1) POINTER TO THE STRING"
1664 P8 = P8 + PEEK (P8 + 1) + 2: GOTO 500
1670 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1671 B1 = P8 + 2: GOSUB 1100: PRINT "LAE. PUSH #DATASEG(";
1672 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);").";
1673 B1 = P8 + 2: GOSUB 1120: PRINT
1675 IF PEEK (P8 + 2) > 127 THEN 534
1676 GOTO 533
1680 B1 = P8 + 1: GOSUB 1100: PRINT " MOV. (TOS-1)^ := (TOS)^ BT ";
1681 B1 = P8 + 1: GOSUB 1120: PRINT " WORDS"
1683 IF PEEK (P8 + 1) > 127 THEN 533
1684 GOTO 532
1690 B1 = P8 + 1: GOSUB 1100: REM PRINT "B"IG WORD "XX XX " OR "XX " IN RAW FORMAT
1691 PRINT " LDO. PUSH BASE.";:B1 = P8 + 1: GOSUB 1120: PRINT : REM PRINT"B"IG WORD "XXXX" OR "XX"
1692 IF PEEK (P8 + 1) > 127 THEN 533
1693 GOTO 532
1700 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2); SPC( 7);"SAS. TOS=CHAR::(TOS-1)^ := TOS CHAR"
1701 PRINT SPC( 17);" TOS=PTR ::(TOS-1)^ := (TOS)^ "; RIGHT$ (A$,2);" CHARACTERS MAX
1702 GOTO 532
1710 B1 = P8 + 1: GOSUB 1100: REM PRINT "B"IG WORD
1711 PRINT " SRO. BASE.";:B1 = P8 + 1: GOSUB 1120: PRINT " := (TOS)
1712 IF PEEK (P8 + 1) > 127 THEN 533
1713 GOTO 532
1720 PZ = 0: IF P8 / 2 = INT (P8 / 2) THEN A = PEEK (P8 + 1): PRINT "(";: GOSUB 550: PRINT RIGHT$ (A$,2);")";:PZ = 1
1721 W1 = PEEK (P8 + PZ + 1) + PEEK (P8 + PZ + 2) * 256:W2 = PEEK (P8 + PZ + 3) + PEEK (P8 + PZ + 4) * 256:W3 = PEEK (P8 + PZ + 5) + PEEK (P8 + PZ + 6) * 256
1722 FOR X = 1 TO 6:A = PEEK (P8 + PZ + X): GOSUB 550: PRINT RIGHT$ (A$,2);" ";: NEXT X
1723 PRINT "TABLE: ";:PY = 2 * (W2 - W1 + 1): REM # OF BYTES
1724 FOR X = 1 TO PY:A = PEEK (P8 + PZ + 6 + X): GOSUB 550: PRINT RIGHT$ (A$,2);" ";: NEXT X
1725 PRINT : PRINT SPC( 17);"XJP. W1,W2,W3,<TABLE>"
1726 P8 = P8 + PZ + 6 + PY * (PY > 0) + 1: GOTO 500
1730 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" "; SPC( 6);
1731 PRINT "RNP. RETURN FROM NON-BASE PROCEDURE."
1732 GOTO 532
1740 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" "; SPC( 6);
1741 PRINT "CIP. CALL INTERMEDIATE PROCEDURE: ";: PRINT RIGHT$ (A$,2)
1742 GOTO 532
1750 REM EQU
1751 GOTO 2900
1760 REM GEQ
1761 GOTO 2900
1770 REM GRT
1771 GOTO 2900
1780 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1781 B1 = P8 + 2: GOSUB 1100: REM PRINT "B"IG WORD
1782 PRINT "LDA. PUSH #ACTREC(-";:A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);").";:B1 = P8 + 2: GOSUB 1120: PRINT
1783 IF PEEK (P8 + 2) > 127 THEN 534
1784 GOTO 533
1790 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1791 PZ = 0: IF (P8 + 1) / 2 = INT ((P8 + 1) / 2) THEN A = PEEK (P8 + 1): PRINT "(";: GOSUB 550: PRINT RIGHT$ (A$,2);")";:PZ = 1: REM THE WORD BLOCK IS WORD ALIGNED
1792 X = 2 * PEEK (P8 + 1): REM # BYTES IN BLOCK
1793 FOR Y = 1 TO X:A = PEEK (P8 + PZ + 2 + Y - 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";: NEXT Y
1794 PRINT : PRINT SPC( 17);"LDC. PUSH ";:A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" WORDS"
1795 P8 = P8 + PZ + 2 + 2 * PEEK (P8 + 1): GOTO 500
1800 REM LEQ
1801 GOTO 2900
1810 REM LES
1811 GOTO 2900
1820 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1821 B1 = P8 + 2: GOSUB 1100: REM PRINT "B"IG WORD
1822 PRINT "LOD. PUSH ACTREC(-";:A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);").";:B1 = P8 + 2: GOSUB 1120: PRINT
1823 IF PEEK (P8 + 2) > 127 THEN 534
1824 GOTO 533
1830 REM NEQ
1831 GOTO 2900
1840 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1841 B1 = P8 + 2: GOSUB 1100: REM PRINT "B"IG WORD
1842 PRINT "STR. ACTREC(-";:A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);").";:B1 = P8 + 2: GOSUB 1120: PRINT " := TOS"
1843 IF PEEK (P8 + 2) > 127 THEN 534
1844 GOTO 533
1850 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2); SPC( 7);"UJP. JUMP TO ";
1851 A = PEEK (P8 + 1): IF A < 128 THEN A = P8 + A + 2: GOTO 1855
1852 X = P5 + 8 - 256 + A
1853 A = X - PEEK (X) - PEEK (X + 1) * 256
1855 A = A + PA: GOSUB 550: PRINT A$
1856 GOTO 532
1860 PRINT SPC( 9);"LDP. PUSH FIELD. TOS: RTBIT;#;^"
1861 GOTO 531
1870 PRINT SPC( 9);"STP. (TOS-1)^FIELDPTR := TOS. (TOS)-1: RTBIT;#;^"
1871 GOTO 531
1880 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" LDM. PUSH "; RIGHT$ (A$,2);" WORDS USING (TOS)^"
1881 GOTO 532
1890 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" STM. (TOS-1)^ := (TOS)^ ";: PRINT RIGHT$ (A$,2);" WORDS"
1891 GOTO 532
1900 PRINT SPC( 9);"LDB. PUSH #00, PUSH (TOS-1)^.TOS BYTE"
1901 GOTO 531
1910 PRINT SPC( 9);"STB. (TOS-2)^.(TOS-1) := TOS BYTE"
1911 GOTO 531
1920 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1921 A = PEEK (P8 + 2): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1922 PRINT " IXP. INDEX PACKED ARRAY. USE TOS & TOS-1, UB1, UB2. ???"
1923 GOTO 533
1930 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" "; SPC( 6);
1931 PRINT "RBP. RETURN FROM BASE PROCEDURE."
1932 GOTO 532
1940 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" "; SPC( 6);
1941 PRINT "CBP. CALL BASE PROCEDURE: "; RIGHT$ (A$,2)
1942 GOTO 532
1950 PRINT SPC( 9);"EQUI. PUSH ((TOS-1) = (TOS))
1951 GOTO 531
1960 PRINT SPC( 9);"GEQI. PUSH ((TOS-1) >= (TOS))
1961 GOTO 531
1970 PRINT SPC( 9);"GRTI. PUSH ((TOS-1) > (TOS))
1971 GOTO 531
1980 REM
1981 B1 = P8 + 1: GOSUB 1100: REM PRINT "B"IG WORD
1984 PRINT " LLA. PUSH #MP.";:B1 = P8 + 1: GOSUB 1120: PRINT
1985 IF PEEK (P8 + 1) > 127 THEN GOTO 533
1986 GOTO 532
1990 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1991 A = PEEK (P8 + 2): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
1992 PRINT " LDCI. PUSH #";
1993 A = PEEK (P8 + 2) * 256 + PEEK (P8 + 1): GOSUB 550: PRINT A$
1994 GOTO 533
2000 PRINT SPC( 9);"LEQI. PUSH ((TOS-1) <= (TOS))
2001 GOTO 531
2010 PRINT SPC( 9);"LESI. PUSH ((TOS-1) < (TOS))
2011 GOTO 531
2020 B1 = P8 + 1: GOSUB 1100: REM PRINT "B"IG
2022 PRINT " LDL. PUSH MP.";:B1 = P8 + 1: GOSUB 1120: PRINT
2025 IF PEEK (P8 + 1) > 127 THEN GOTO 533
2026 GOTO 532
2030 PRINT SPC( 9);"NEQI. PUSH ((TOS-1) <> (TOS))
2031 GOTO 531
2040 B1 = P8 + 1: GOSUB 1100: REM PRINT "B"IG
2041 PRINT " STL. MP.";:B1 = P8 + 1: GOSUB 1120: PRINT " := (TOS)"
2045 IF PEEK (P8 + 1) > 127 THEN GOTO 533
2046 GOTO 532
2050 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";:A = PEEK (P8 + 2): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
2051 PRINT "CXP. CALL EXTERNAL PROCEDURE: "; RIGHT$ (A$,2);" IN SEGMENT: ";:A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2)
2052 GOTO 533
2060 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" "; SPC( 6);
2061 PRINT "CLP. CALL CHILD PROCEDURE: "; RIGHT$ (A$,2)
2062 GOTO 532
2070 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" "; SPC( 6);
2071 PRINT "CGP. CALL GLOBAL PROCEDURE: "; RIGHT$ (A$,2)
2072 GOTO 532
2080 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
2081 FOR X = 1 TO PEEK (P8 + 1):A = PEEK (P8 + 1 + X): GOSUB 550: PRINT RIGHT$ (A$,2);" ";: NEXT X
2082 PRINT : PRINT SPC( 17);"LPA. PUSH #(PC+2) POINTER TO THE ARRAY"
2083 P8 = P8 + PEEK (P8 + 1) + 2: GOTO 500
2090 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" ";
2091 B1 = P8 + 2: GOSUB 1100: PRINT "STE. DATASEG(";
2092 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);").";
2093 B1 = P8 + 2: GOSUB 1120: PRINT " := (TOS)
2095 IF PEEK (P8 + 2) > 127 THEN 534
2096 GOTO 533
2100 PRINT SPC( 9);"???.": GOTO 2560
2110 PRINT SPC( 9);"EFJ.": GOTO 2560
2120 PRINT SPC( 9);"NFJ.": GOTO 2560
2130 B1 = P8 + 1: GOSUB 1100: PRINT "BPT. BREAKPOINT"
2131 IF PEEK (P8 + 1) > 127 THEN 533
2132 GOTO 532
2140 PRINT SPC( 9);"XIT. EXIT OPERATING SYSTEM."
2141 GOTO 531
2150 PRINT SPC( 9);"NOP. NOP"
2151 GOTO 531
2160 X = 1
2161 GOTO 2311
2170 X = 2
2171 GOTO 2311
2180 X = 3
2181 GOTO 2311
2190 X = 4
2191 GOTO 2311
2200 X = 5
2201 GOTO 2311
2210 X = 6
2211 GOTO 2311
2220 X = 7
2221 GOTO 2311
2230 X = 8
2231 GOTO 2311
2240 X = 9
2241 GOTO 2311
2250 X = 10
2251 GOTO 2311
2260 X = 11
2261 GOTO 2311
2270 X = 12
2271 GOTO 2311
2280 X = 13
2281 GOTO 2311
2290 X = 14
2291 GOTO 2311
2300 X = 15
2301 GOTO 2311
2310 X = 16
2311 PRINT SPC( 9);"SLDL.";:A = X: GOSUB 550: PRINT " PUSH MP."; RIGHT$ (A$,2)
2312 GOTO 531
2320 REM
2473 PRINT SPC( 9);"SLDO. PUSH BASE.";:A = P9 - 231: GOSUB 550: PRINT RIGHT$ (A$,2)
2475 GOTO 531
2480 REM
2550 X = P9 - 248
2552 PRINT SPC( 9);"SIND. PUSH (TOS)^.";X
2553 GOTO 531
2560 PRINT "NOT IMPLEMENTED.": GOTO 1531
2900 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);: GOSUB 2930
2901 IF P9 = 175 THEN PRINT "EQU. PUSH ((TOS-1) = (TOS))";
2902 IF P9 = 183 THEN PRINT "NEQ. PUSH ((TOS-1) <> (TOS))";
2903 IF P9 = 180 THEN PRINT "LEQ. PUSH ((TOS-1) <= (TOS))";
2904 IF P9 = 181 THEN PRINT "LES. PUSH ((TOS-1) < (TOS))";
2905 IF P9 = 176 THEN PRINT "GEQ. PUSH ((TOS-1) >= (TOS))";
2906 IF P9 = 177 THEN PRINT "GRT. PUSH ((TOS-1) > (TOS))";
2910 A = PEEK (P8 + 1)
2911 IF A = 2 THEN PRINT "--REALS"
2912 IF A = 4 THEN PRINT "--STRINGS"
2913 IF A = 6 THEN PRINT "--BOOLEANS"
2914 IF A = 8 THEN PRINT "--SETS"
2915 IF A = 10 THEN PRINT "--BYTE ARRAYS"
2916 IF A = 12 THEN PRINT "--WORDS"
2918 IF A = 10 OR A = 12 THEN 1575
2920 GOTO 532
2930 A = PEEK (P8 + 1)
2932 IF A = 10 OR A = 12 THEN 2935
2934 PRINT SPC( 7);: RETURN
2935 PRINT " ";:B1 = P8 + 2: GOSUB 1100
2937 RETURN
3000 REM 158
3002 A = PEEK (P8 + 1): GOSUB 550: PRINT RIGHT$ (A$,2);" "; SPC( 6);
3004 X = PEEK (P8 + 1): IF X < > 1 THEN 3010
3005 PRINT "NEW. (TOS) HAS # WORDS, (TOS-1)^ IS THE VARIABLE
3006 GOTO 532
3010 IF X < > 32 THEN 3020
3011 PRINT "MRK. MARK HEAP. (TOS)^ := NP"
3012 GOTO 532
3020 IF X < > 33 THEN 3030
3021 PRINT "RLS. RELEASE HEAP. NP := (TOS)^"
3022 GOTO 532
3030 IF X < > 22 THEN 3040
3031 PRINT "DUSE. DEC USE CNT FOR SEG #(TOS)
3032 GOTO 532
3040 IF X < > 23 THEN 3050
3041 PRINT "RND. PUSH ROUND(TOS)
3042 GOTO 532
3050 IF X < > 35 THEN 3060
3051 PRINT "POT. POWER OF TEN. PUSH 10^(TOS)
3052 GOTO 532
3060 IF X < > 4 THEN 3070
3061 PRINT "EXIT. EXIT FROM PROCEDURE. (TOS)=PROC# (TOS-1)=SEG#
3062 GOTO 532
3070 IF X < > 10 THEN 3080
3071 PRINT "FLC. FILLCHAR (DST+IDX,LEN,CHR)"
3072 GOTO 532
3080 IF X < > 11 THEN 3090
3081 PRINT "SCAN. SCAN???"
3082 GOTO 532
3090 IF X < > 02 THEN 3100
3091 PRINT "MVL. MOVELEFT"
3092 GOTO 532
3100 IF X < > 3 THEN 3110
3101 PRINT "MVR. MOVERIGHT"
3102 GOTO 532
3110 IF X < > 9 THEN 3130
3111 PRINT "TIM. TIME."
3112 GOTO 532
3120 PRINT "AN UNKNOWN STANDARD PROCEDURE ?!?!"
3121 GOTO 532
3130 IF X < > 5 THEN 3140
3131 PRINT "READ FROM VOL#"
3132 GOTO 532
3140 IF X < > 21 THEN 3150
3141 PRINT "RSEG. READ SEGMENT #(TOS) FROM ACTIVE SEG TABLE"
3142 GOTO 532
3150 IF X < > 38 THEN 3160
3151 PRINT "CHECK VOL#"
3152 GOTO 532
3160 IF X < > 6 THEN 3170
3161 PRINT "WRITE VOL#"
3162 GOTO 532
3170 IF X < > 34 THEN 3120
3171 PRINT "PUSH I/O ERROR STATUS"
3172 GOTO 532
5000 GOSUB 5: REM SET UP RWTS
5005 GOSUB 100: REM READ DIR
5010 GOSUB 140: REM DISP FNAMES
5015 GOSUB 200: REM GET FILE #
5017 IF FF = - 1 THEN END
5020 GOSUB 210: REM USE FILE#
5025 GOSUB 280: REM GET SEG#
5026 IF SS = - 1 THEN 5010
5030 GOSUB 285
5031 IF LL = 0 THEN 5025
5032 PA = 0
5035 GOSUB 375: REM GET $4000
5037 GOSUB 390
5040 GOSUB 420: REM GET PROC#
5042 IF P3 = - 1 THEN 5020
5045 GOSUB 440
5047 REM GOSUB 480
5048 GOTO 5040
5090 REM ----------
5100 GOSUB 5
5105 GOSUB 100
5110 GOSUB 140
5115 FOR FF = 1 TO FQ(1)
5120 GOSUB 210
5122 IF FQ(4) = - 1 THEN 5154
5125 FOR SS = 0 TO FQ(2)
5130 GOSUB 285
5131 IF LL = 0 THEN 5152
5132 PA = 0
5134 GOSUB 390
5140 FOR P3 = 1 TO FQ(3)
5142 PRINT : PRINT "FILE: ";FF;" SEG: ";SS;" PROC: ";P3
5145 GOSUB 440
5150 NEXT P3
5152 NEXT SS
5154 NEXT FF
5160 END

]


Tommy

Didier VALLET

unread,
Apr 23, 2014, 9:23:41 PM4/23/14
to
Le jeudi 24 avril 2014 02:12:23 UTC+2, TommyGoog a écrit :
> On Monday, April 21, 2014 11:23:35 AM UTC-5, Didier VALLET wrote:
>
>
> I will assume when you are asking for information about "wiz3 code" that you are referring to my program written in Applesoft Basic to take a diskette with compiled Pascal code and display the formatted pcode output.
>
> At the end of this message I will include the source code for this "wiz3" program. To try to stop confusion about the names I am usually now calling the "wiz3" basic program "DeCompiler" (wiz3 is too similar to Wizardry III or Wizardry3).
>

Ooops, Ok
I didn't intend to remake another wiz3. Your process is working well and it will be loosing time to work on another tool like it.
Thanks for your informations about the process. It will help me to understand the datas.

I'm sorry for the confusion (linked to my low english level). I wanted to :
- looking at the pcode of Wizardry 1 and i saw that you're quicker than me in this.
- working on a "remake" on 8bits computers of the Wizardry serie (in C and 6502 code) starting on the original code (and your work on Wizardry 3 is a "gift") because halito and other works were a great piece of time when i was younger.

Didier

TommyGoog

unread,
Apr 23, 2014, 10:12:23 PM4/23/14
to

>
>
> Up next is P070301 (SEGMENT OPTIONS)

With this posting I complete the decompiling for STARTUP.CODE.

P070301 pcode (SEGMENT OPTIONS)

This is the pcode we want to generate:

FILE: 7 SEG: 3 PROC: 1

JTAB FOR SUBROUTINE 1:
DATA SIZE: 512
PARAM SIZE: 0
EXIT AT: 5227
ENTER AT: 5000
PROC NUMBER: 1
LEXICAL LEVEL: 1
5000 04 SLDC. PUSH #0004
5001 C6 01 LLA. PUSH #MP.01
5003 00 SLDC. PUSH #0000
5004 C7 00 02 LDCI. PUSH #0200
5007 00 SLDC. PUSH #0000
5008 00 SLDC. PUSH #0000
5009 9E 05 READ FROM VOL#
500B 04 SLDC. PUSH #0004
500C C6 01 LLA. PUSH #MP.01
500E 00 SLDC. PUSH #0000
500F C7 00 02 LDCI. PUSH #0200
5012 00 SLDC. PUSH #0000
5013 00 SLDC. PUSH #0000
5014 9E 06 WRITE VOL#
5016 9E 22 PUSH I/O ERROR STATUS
5018 10 SLDC. PUSH #0010
5019 CB NEQI. PUSH ((TOS-1) <> (TOS))
501A A1 03 UJP. IF NOT (TOS) THEN JUMP TO 501F
501C 00 SLDC. PUSH #0000
501D A1 F6 UJP. IF NOT (TOS) THEN JUMP TO 501C
501F B6 02 03 LOD. PUSH ACTREC(-02).03
5022 0C SLDC. PUSH #000C
5023 00 SLDC. PUSH #0000
5024 CD 00 11 CXP. CALL EXTERNAL PROCEDURE: 11 IN SEGMENT: 00
5027 B6 02 03 LOD. PUSH ACTREC(-02).03
502A D7 NOP. NOP
502B A6 28 43 4F 50 59 52 49 47 48 54 20 28 43 29 31 39 38 31 20 41 4C 4C 20 52 49 47 48 54 53 20 52 45 53 45 52 56 45 44 20 42 59
COPYRIGHT (C)1981 ALL RIGHTS RESERVED BY
LSA. PUSH #(PC+1) POINTER TO THE STRING
5055 00 SLDC. PUSH #0000
5056 CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
5059 B6 02 03 LOD. PUSH ACTREC(-02).03
505C CD 00 16 CXP. CALL EXTERNAL PROCEDURE: 16 IN SEGMENT: 00
505F B6 02 03 LOD. PUSH ACTREC(-02).03
5062 D7 NOP. NOP
5063 A6 28 41 4E 44 52 45 57 20 47 52 45 45 4E 42 45 52 47 2C 20 49 4E 43 20 26 20 52 4F 42 45 52 54 20 57 4F 4F 44 48 45 41 44 2C
ANDREW GREENBERG, INC & ROBERT WOODHEAD,
LSA. PUSH #(PC+1) POINTER TO THE STRING
508D 00 SLDC. PUSH #0000
508E CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
5091 B6 02 03 LOD. PUSH ACTREC(-02).03
5094 CD 00 16 CXP. CALL EXTERNAL PROCEDURE: 16 IN SEGMENT: 00
5097 B6 02 03 LOD. PUSH ACTREC(-02).03
509A D7 NOP. NOP
509B A6 28 49 4E 43 2E 20 20 54 48 49 53 20 50 52 4F 47 52 41 4D 20 20 49 53 20 20 50 52 4F 54 45 43 54 45 44 20 20 55 4E 44 45 52
INC. THIS PROGRAM IS PROTECTED UNDER
LSA. PUSH #(PC+1) POINTER TO THE STRING
50C5 00 SLDC. PUSH #0000
50C6 CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
50C9 B6 02 03 LOD. PUSH ACTREC(-02).03
50CC CD 00 16 CXP. CALL EXTERNAL PROCEDURE: 16 IN SEGMENT: 00
50CF B6 02 03 LOD. PUSH ACTREC(-02).03
50D2 D7 NOP. NOP
50D3 A6 28 54 48 45 20 4C 41 57 53 20 4F 46 20 54 48 45 20 55 4E 49 54 45 44 20 53 54 41 54 45 53 20 20 41 4E 44 20 4F 54 48 45 52
THE LAWS OF THE UNITED STATES AND OTHER
LSA. PUSH #(PC+1) POINTER TO THE STRING
50FD 00 SLDC. PUSH #0000
50FE CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
5101 B6 02 03 LOD. PUSH ACTREC(-02).03
5104 CD 00 16 CXP. CALL EXTERNAL PROCEDURE: 16 IN SEGMENT: 00
5107 B6 02 03 LOD. PUSH ACTREC(-02).03
510A D7 NOP. NOP
510B A6 28 43 4F 55 4E 54 52 49 45 53 2C 20 20 41 4E 44 20 49 4C 4C 45 47 41 4C 20 44 49 53 54 52 49 42 55 54 49 4F 4E 20 4D 41 59
COUNTRIES, AND ILLEGAL DISTRIBUTION MAY
LSA. PUSH #(PC+1) POINTER TO THE STRING
5135 00 SLDC. PUSH #0000
5136 CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
5139 B6 02 03 LOD. PUSH ACTREC(-02).03
513C CD 00 16 CXP. CALL EXTERNAL PROCEDURE: 16 IN SEGMENT: 00
513F B6 02 03 LOD. PUSH ACTREC(-02).03
5142 D7 NOP. NOP
5143 A6 28 52 45 53 55 4C 54 20 49 4E 20 43 49 56 49 4C 20 20 4C 49 41 42 49 4C 49 54 59 20 20 41 4E 44 20 43 52 49 4D 49 4E 41 4C
RESULT IN CIVIL LIABILITY AND CRIMINAL
LSA. PUSH #(PC+1) POINTER TO THE STRING
516D 00 SLDC. PUSH #0000
516E CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
5171 B6 02 03 LOD. PUSH ACTREC(-02).03
5174 CD 00 16 CXP. CALL EXTERNAL PROCEDURE: 16 IN SEGMENT: 00
5177 B6 02 03 LOD. PUSH ACTREC(-02).03
517A D7 NOP. NOP
517B A6 0C 50 52 4F 53 45 43 55 54 49 4F 4E 2E
PROSECUTION.
LSA. PUSH #(PC+1) POINTER TO THE STRING
5189 00 SLDC. PUSH #0000
518A CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
518D B6 02 03 LOD. PUSH ACTREC(-02).03
5190 CD 00 16 CXP. CALL EXTERNAL PROCEDURE: 16 IN SEGMENT: 00
5193 00 SLDC. PUSH #0000
5194 0C SLDC. PUSH #000C
5195 CD 00 1D CXP. CALL EXTERNAL PROCEDURE: 1D IN SEGMENT: 00
5198 B6 02 03 LOD. PUSH ACTREC(-02).03
519B A6 20 20 20 56 45 52 53 49 4F 4E 20 32 2E 31 20 4F 46 20 32 32 2D 4A 41 4E 2D 38 32 20 20 53 45 52 3A
VERSION 2.1 OF 22-JAN-82 SER:
LSA. PUSH #(PC+1) POINTER TO THE STRING
51BD D7 NOP. NOP
51BE 00 SLDC. PUSH #0000
51BF CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
51C2 B6 02 03 LOD. PUSH ACTREC(-02).03
51C5 A5 05 LA0. PUSH #BASE.05
51C7 00 SLDC. PUSH #0000
51C8 CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
51CB B6 02 03 LOD. PUSH ACTREC(-02).03
51CE CD 00 16 CXP. CALL EXTERNAL PROCEDURE: 16 IN SEGMENT: 00
51D1 B6 02 03 LOD. PUSH ACTREC(-02).03
51D4 CD 00 16 CXP. CALL EXTERNAL PROCEDURE: 16 IN SEGMENT: 00
51D7 B6 02 03 LOD. PUSH ACTREC(-02).03
51DA CD 00 16 CXP. CALL EXTERNAL PROCEDURE: 16 IN SEGMENT: 00
51DD B6 02 03 LOD. PUSH ACTREC(-02).03
51E0 D7 NOP. NOP
51E1 A6 26 20 20 53 29 54 41 52 54 20 47 41 4D 45 20 20 55 29 54 49 4C 49 54 49 45 53 20 20 54 29 49 54 4C 45 20 50 41 47 45
S)TART GAME U)TILITIES T)ITLE PAGE
LSA. PUSH #(PC+1) POINTER TO THE STRING
5209 00 SLDC. PUSH #0000
520A CD 00 13 CXP. CALL EXTERNAL PROCEDURE: 13 IN SEGMENT: 00
520D 29 SLDC. PUSH #0029
520E 00 SLDC. PUSH #0000
520F CD 00 1D CXP. CALL EXTERNAL PROCEDURE: 1D IN SEGMENT: 00
5212 B6 02 02 LOD. PUSH ACTREC(-02).02
5215 A5 03 LA0. PUSH #BASE.03
5217 CD 00 10 CXP. CALL EXTERNAL PROCEDURE: 10 IN SEGMENT: 00
521A EA SLDO. PUSH BASE.03
521B 53 SLDC. PUSH #0053
521C C3 EQUI. PUSH ((TOS-1) = (TOS))
521D EA SLDO. PUSH BASE.03
521E 55 SLDC. PUSH #0055
521F C3 EQUI. PUSH ((TOS-1) = (TOS))
5220 8D LOR. PUSH ((TOS-1) OR (TOS))
5221 EA SLDO. PUSH BASE.03
5222 54 SLDC. PUSH #0054
5223 C3 EQUI. PUSH ((TOS-1) = (TOS))
5224 8D LOR. PUSH ((TOS-1) OR (TOS))
5225 A1 F4 UJP. IF NOT (TOS) THEN JUMP TO 520D
5227 AD 00 RNP. RETURN FROM NON-BASE PROCEDURE.
5229 00 SLDC. PUSH #0000
522A 1D SLDC. PUSH #001D
522B 00 SLDC. PUSH #0000
522C 10 SLDC. PUSH #0010
522D 02 SLDC. PUSH #0002

PROCEDURE OPTIONS is different from the one in LOL.

WRITELN( BASE05) is not correct.
I currently have it called RANDNUM, but see now that it is the SERIALNM
This is my first draft after changing BASE05 to RANDNUM.

1152 9 1:D 1 SEGMENT PROCEDURE OPTIONS; (* P050301 *)
1153 9 1:D 1
1154 9 1:D 1 CONST
1155 9 1:D 1 HOMECLR = 12;
1156 9 1:D 1
1157 9 1:D 1 VAR
1158 9 1:D 1 IOBUFF : PACKED ARRAY[ 0..511] OF CHAR;
1159 9 1:D 257
1160 9 1:0 0 BEGIN
1161 9 1:0 0
1162 9 1:1 0 UNITREAD( DRIVE1, IOBUFF, SIZEOF( IOBUFF), 0, 0);
1163 9 1:1 11 UNITWRITE( DRIVE1, IOBUFF, SIZEOF( IOBUFF), 0, 0);
1164 9 1:1 22
1165 9 1:1 22 IF IORESULT = 16 THEN
1166 9 1:2 28 REPEAT
1167 9 1:2 28 UNTIL FALSE;
1168 9 1:2 31
1169 9 1:1 31 WRITE( CHR( HOMECLR));
1170 9 1:1 39
1171 9 1:1 39 WRITELN( 'COPYRIGHT (C)1981 ALL RIGHTS RESERVED BY');
1172 9 1:1 95 WRITELN( 'ANDREW GREENBERG, INC & ROBERT WOODHEAD,');
1173 9 1:1 151 WRITELN( 'INC. THIS PROGRAM IS PROTECTED UNDER');
1174 9 1:1 204 WRITELN( 'THE LAWS OF THE UNITED STATES AND OTHER');
1175 9 1:1 259 WRITELN( 'COUNTRIES, AND ILLEGAL DISTRIBUTION MAY');
1176 9 1:1 314 WRITELN( 'RESULT IN CIVIL LIABILITY AND CRIMINAL');
1177 9 1:1 368 WRITELN( 'PROSECUTION.');
1178 9 1:1 396
1179 9 1:1 396 GOTOXY( 0, 12);
1180 9 1:1 401
1181 9 1:1 401 WRITE( ' VERSION 2.1 OF 22-JAN-82 SER:');
1182 9 1:1 444 WRITELN( RANDNUM);
1183 9 1:1 458 WRITELN;
1184 9 1:1 464 WRITELN;
1185 9 1:1 470
1186 9 1:1 470 WRITE( 'S)TART GAME U)TILITIES T)ITLE PAGE');
1187 9 1:1 514
1188 9 1:1 514 REPEAT
1189 9 1:2 514 GOTOXY( 41,0);
1190 9 1:2 519 READ( INCHAR)
1191 9 1:1 527 UNTIL (INCHAR = 'S') OR (INCHAR = 'T') OR (INCHAR = 'U')
1192 9 1:1 537
1193 9 1:1 537 (*
1194 9 1:1 537 GOTOXY( 0, 12);
1195 9 1:1 537 WRITE( 'VERSION -4- OF 04-MAY-83 SER:');
1196 9 1:1 537 WRITELN( SERIAL);
1197 9 1:1 537 WRITELN;
1198 9 1:1 537 WRITELN;
1199 9 1:1 537 WRITELN( ' S)TART GAME U)TILITIES' : 32);
1200 9 1:1 537 WRITELN;
1201 9 1:1 537 WRITELN( 'NOTE - YOU MUST MAKE AN ADDITIONAL SCEN-');
1202 9 1:1 537 WRITELN( ' ARIO DISKETTE BEFORE PLAYING. SEE');
1203 9 1:1 537 WRITE ( ' THE MANUAL FOR MORE DETAILS.' );
1204 9 1:1 537
1205 9 1:1 537 REPEAT
1206 9 1:1 537 GOTOXY( 41, 0);
1207 9 1:1 537 READ( INCHAR)
1208 9 1:1 537 UNTIL (INCHAR = 'S') OR (INCHAR = 'U')
1209 9 1:1 537
1210 9 1:1 537 *)
1211 9 1:0 537 END;

Sometimes first drafts have lots of errors, so now it is time to fix them.

Change "IORESULT = 16" to "IORESULT <> 16".

Change "INC. THIS PROGRAM IS PROTECTED UNDER" to "INC. THIS PROGRAM IS PROTECTED UNDER"

(Add some spaces to the message.)

change "THE LAWS OF THE UNITED STATES AND OTHER" to "THE LAWS OF THE UNITED STATES AND OTHER"
change "COUNTRIES, AND ILLEGAL DISTRIBUTION MAY" to "COUNTRIES, AND ILLEGAL DISTRIBUTION MAY
change "RESULT IN CIVIL LIABILITY AND CRIMINAL" to "RESULT IN CIVIL LIABILITY AND CRIMINAL"
change " VERSION 2.1 OF 22-JAN-82 SER:" to " VERSION 2.1 OF 22-JAN-82 SER:"

Now my code says it is using BASE.04 and not BASE.05.
For some reason the routine is generated as PROCEDURE: 0D instead of PROCEDURE: 13.
change "'S)TART GAME U)TILITIES T)ITLE PAGE'" to "' S)TART GAME U)TILITIES T)ITLE PAGE'
Remove temporary comments and old code from LOL.
53 55 54
The order in the UNTIL statement is "S" "U" "T".
Change RANDNUM to SERIAL

Final rough draft for P070301.

1151 8 1:0 104 (*$I WIZ1E:OPTIONS *)
1152 9 1:D 1 SEGMENT PROCEDURE OPTIONS; (* P070301 *)
1153 9 1:D 1
1154 9 1:D 1 CONST
1155 9 1:D 1 HOMECLR = 12;
1156 9 1:D 1
1157 9 1:D 1 VAR
1158 9 1:D 1 IOBUFF : PACKED ARRAY[ 0..511] OF CHAR;
1159 9 1:D 257
1160 9 1:0 0 BEGIN
1161 9 1:0 0
1162 9 1:1 0 UNITREAD( DRIVE1, IOBUFF, SIZEOF( IOBUFF), 0, 0);
1163 9 1:1 11 UNITWRITE( DRIVE1, IOBUFF, SIZEOF( IOBUFF), 0, 0);
1164 9 1:1 22
1165 9 1:1 22 IF IORESULT <> 16 THEN
1166 9 1:2 28 REPEAT
1167 9 1:2 28 UNTIL FALSE;
1168 9 1:2 31
1169 9 1:1 31 WRITE( CHR( HOMECLR));
1170 9 1:1 39
1171 9 1:1 39 WRITELN( 'COPYRIGHT (C)1981 ALL RIGHTS RESERVED BY');
1172 9 1:1 95 WRITELN( 'ANDREW GREENBERG, INC & ROBERT WOODHEAD,');
1173 9 1:1 151 WRITELN( 'INC. THIS PROGRAM IS PROTECTED UNDER');
1174 9 1:1 207 WRITELN( 'THE LAWS OF THE UNITED STATES AND OTHER');
1175 9 1:1 263 WRITELN( 'COUNTRIES, AND ILLEGAL DISTRIBUTION MAY');
1176 9 1:1 319 WRITELN( 'RESULT IN CIVIL LIABILITY AND CRIMINAL');
1177 9 1:1 375 WRITELN( 'PROSECUTION.');
1178 9 1:1 403
1179 9 1:1 403 GOTOXY( 0, 12);
1180 9 1:1 408
1181 9 1:1 408 WRITE( ' VERSION 2.1 OF 22-JAN-82 SER:');
1182 9 1:1 450 WRITELN( SERIAL);
1183 9 1:1 465 WRITELN;
1184 9 1:1 471 WRITELN;
1185 9 1:1 477