In order to give on example of what kind of problems could be encountered I decided to port Will Crowther and Don Woods' "Adventure" to the ICL 1900 running George 3.
The version chosen is Woods' "350 point" variant. (Copy here). This version of Adventure was written in Fortran IV for the DEC PDP 10, a 36 bit word machine with 6, 7, 8 or 9 bit characters.
(Much of this information, worked out with great loss of hair, turns out to be available from the Altas Computer Lab: Atlas Computing Division: Engineering Reports: FORTRAN Compilers and Loaders, R E Thomas, 29.04.76 ACD: Engineering Paper No 42).
The PDP source code format uses a TAB to seperate the label number field from the instruction field, rather than the traditional fixed 6 character field. Continuation lines are indicated by a numeric chacter as the first character of the instruction field, rather than the tradinional nonspace/nonzero in the 7th character position.
It is possible to store text containing TAB characters in George 3 NORMAL or ALLCHAR files, but the operating system and most available programming languages are rather poor at manipulating such files.
Eventualy I decided to write an Algol 60 program to convert from the PDP-10 source format to something readable by the ICL compilers.
The Fortran IV computed GOTO is written as:
GOTO (1, 2, 3) EXPRESSIONwhile the ICL Fortran computed GOTO looks like:
GOTO (1, 2, 3), VARIABLEWe will have to use temporary variables in the places where the expression is too complicated for ICL Fortran.
Fortran IV has some extra verbs for doing I/O to the console, TYPE and ACCEPT. These can be trivialy replaced by READ and WRITE for ICL Extended Fortran.
The program uses the IMPLICIT INTEGER statement to implicitly declare all variables as integer. This is not implemented by the smaller ICL compilers (#XFAT) so the larger compilers (e.g. #XFIV) will need to be used.
PDP Fortran IV allows character constants to be used anywhere integer constants are allowed, for example in code like:
IF (WD1 .EQ. 'PLUGH') GOTO 2100In ICL Fortran 66 character constants can only be used in DATA statements and subroutine and function calls, so this code will have to be rewritten as:
IF (EQUAL (WD1, 'PLUGH')) GOTO 2100(Assuming a suitable LOGICAL FUNCTION EQUAL).
PDP Fortran IV allows logical operations (.AND., .OR., .XOR. and .SHIFT.) on integer variables. Functions will have to be written in PLAN to replace them. (See here).
PDP-10 Fortran uses the format "G" for free-format input. This is similar to "G0" or "I0" in ICL Fortran with one unfortunate difference - the PDP-10 version stops reading at EOL. This means that code like this:
READ (1, 1000) LOC, NEWLOC, (TK (I), I = 1, 20) 1000 FORMAT (99G)will read only as many integers as are on the line, setting subsequent values to zero. The naïve translation into ICL Fortran would read exactly 22 integers, skipping any line boundaries. In order to work around this we will write a routine to emulate the PDP-10 behaviour by reading the line as text then doing in-core reads to convert the numbers. (See here).
PDP-10 Fortran allows octal constants, prefixed by a double quote:
DATA MASKS/"4000000000,"20000000,"100000,"400,"2,0/These will have to be replaced by decimal constants.
Practicaly this meant that programs could be written to store text in six, seven or nine bit bytes, stored six, five or four bytes to the word.
Adventure was written to use seven bit bytes, five to the word, manipulated using Fortran A5 format. (Five characters, left justified in the word, padded with spaces on the right).
The routine GETIN reads from the console, and uses bit manipulation instructions to split the input into two five character words (with optional five character extensions used only for output). For example the user input:
GO DOWNSTREAMwill be parsed into "GO" and "DOWNS" with an extension of "TREAM". The available commands and items have been carefully named to be unique in the first five characters, for example "DOWN" is distinguished from "DOWNS" in one important place.
To reduce the problems of porting, and avoid changing the gameplay we will keep the basic five-character names for comamnds and items.
However the ICL 1900 can only store 4 (six bit) characters per word, so we will need two machine words per five character "word" of user input. Luckily for us the ICL 1900 Fortran compiler normally allocates two words per INTEGER variable (to make sure that INTEGER is the same size as REAL, for compatability with IBM Fortran). We will have to be careful when copying user input as a simple assignment will only copy the first machine word (four characters). Similarly we will use the LOCATION compilation option to make sure subroutine arguments are passed by location rather than value.
(Later on we might like to reduce the memory usage of the program by compiling with the COMPRESS INTEGER AND LOGICAL option which instructs the compiler to only use one machine word per integer, and modifying the code to use two word arrays to hold the five characters of user input.)
We will write our own version of GETIN, using the Fortran library function COPY for byte copying.
The subroutine A5TOA1 converts some words input by the user in A5 format to A1 format for output, also by bit twiddling. We will write our own version of A5TOA1 using the COPY subroutine.
The function RAN generates random numbers, using:
R=MOD(R*1021,1048576) RAN=(RANGE*R)/1048576which will overflow with 24 bit integers. From sheer laziness we will use the routine FPMCRV from the SUBGROUPFSCE library.
A similar algorithm is used by the function WIZARD to produce a random challenge, which the user has to manipulate in some undocumented way. This will also require changing.
The array TRAVEL is initialised from the database to hold "NEWLOC * 1000 + KEYWORD", Unfortunatly "NEWLOC" can be up to 700,000 and 700,000,000 is too large to fit into an ICL 1900 integer (the largest positive integer is 8,388,607). The simple solution is to break the TRAVEL table into two arrays, one holding NEWLOC and the other KEYWORD.
To reduce the chance of the user examining the core image the list of commands is obscured by XORing them with a secret constant. As we have no easy access to both machine words of the 5 character "words" this may be difficult.
The TOPS-10 version of Adventure was known as ADVENT - TOPS-10 had 6 character filenames (6 x 6bit characters in one 36 bit word). We'll call ours ADVENTURE as we have the luxury of 12 character filenames, although we'll also stick to good old 1960's style shouting.
The TOPS-10 version read its database from unit 1, which was attached to the data file by the IFILE subroutine. We will attach unit 1 to *TR0 using a standard INPUT statement in the program description and the George 3 ASSIGN command. We use a tape reader as the database contains TAB characters.
On TOPS-10 Adventure reads from the console with the ACCEPT verb and writes to the console with TYPE. We will use standard READ and WRITE from *CR0 and *LP0.
After initialising Adventure performs a PAUSE and the initialised core image is saved. This will work unchanged on George 3.
If the user wants to save the game Adventure will PAUSE and the core image can be saved. This will produce rather large savegames, maybe later on we should write code to save just the variable part.
The code needs to know the current date and time. On TOPS-10 this was quite difficult, it had to extract the information from text strings. On the ICL 1900 we can just use the library ITIME and IDATE subroutines (which give the time in seconds past midnight and the date in days since 31 DEC 1899).
Compilation and initialisation:
:JOHN.ADVENT(3/FORT) IS ALREADY ONLINE FILES ALREADY ONLINE: :MACROS.CONSOLIDATE(2/) :LIB.SUBGROUPSRF4(1/V9P) :JOHN.ADVENT(1/PROG) IS ALREADY ONLINE :JOHN.BITOPS(1/SEMI) IS ALREADY ONLINE :LIB.SUBGROUPFSCE(1/V3) IS ALREADY ONLINE 09.58.04 FREE *DA14,0 TRANSFERS 09.58.04 0.34 DELETED,CLOCKED 0.02 09.58.04 0.34 CORE GIVEN 32576 FORTRAN COMPILATION BY #XFIV MK 3B DATE 26/06/10 TIME 09/58/04 0000 0001 ERRORLIST 0.34 :HALTED : BP 0.35 :HALTED : BP 09.58.08 FREE *DA3 ,108 TRANSFERS 09.58.08 FREE *CR0 ,3117 TRANSFERS 09.58.08 FREE *DA1 ,61 TRANSFERS 09.58.08 FREE *DA4 ,143 TRANSFERS 0.41 :DELETED : FI 09.58.08 FREE *LP0 ,7 TRANSFERS 09.58.08 FREE *DA0 ,3713 TRANSFERS 09.58.08 0.41 DELETED,CLOCKED 0.03 :JOHN.BITOPS(1/SEMI) IS ALREADY ONLINE :LIB.SUBGROUPFSCE(1/V3) IS ALREADY ONLINE :LIB.SUBGROUPSRF4(1/V9P) IS ALREADY ONLINE :JOHN.ADVENT(1/PROG) IS ALREADY ONLINE 09.58.08 0.43 CORE GIVEN 11392 CONSOLIDATED BY XPCK 12K DATE 26/06/10 TIME 09/58/08 09.58.09 0.43 CORE GIVEN 43904 09.58.09 FREE *LP0 ,8 TRANSFERS 09.58.09 FREE *DA1 ,66 TRANSFERS 09.58.09 FREE *DA2 ,7 TRANSFERS 09.58.09 FREE *DA3 ,98 TRANSFERS 09.58.09 FREE *DA4 ,87 TRANSFERS 09.58.09 FREE *DA13,9 TRANSFERS 09.58.09 0.44 CORE GIVEN 43840 0.44 :HALTED : LD END OF MACRO PARAMETER NUMBER 8 UNACCESSED END OF MACRO INITIALISING... TABLE SPACE USED: 9626 OF 9650 WORDS OF MESSAGES 741 OF 750 TRAVEL OPTIONS 297 OF 300 VOCABULARY WORDS 140 OF 150 LOCATIONS 53 OF 100 OBJECTS 31 OF 35 ACTION VERBS 201 OF 205 RTEXT MESSAGES 10 OF 12 CLASS MESSAGES 9 OF 20 HINTS 32 OF 35 MAGIC MESSAGES 09.58.11 FREE *TR0 ,1809 TRANSFERS 0.47 :HALTED : INIT DONE *DA14 NOT SAVED *LP0 NOT SAVED *CR0 NOT SAVEDInitial run:
10.08.13_ en WELCOME TO ADVENTURE!! WOULD YOU LIKE INSTRUCTIONS? _ y SOMEWHERE NEARBY IS COLOSSAL CAVE, WHERE OTHERS HAVE FOUND FORTUNES IN TREASURE AND GOLD, THOUGH IT IS RUMORED THAT SOME WHO ENTER ARE NEVER SEEN AGAIN. MAGIC IS SAID TO WORK IN THE CAVE. I WILL BE YOUR EYES AND HANDS. DIRECT ME WITH COMMANDS OF 1 OR 2 WORDS. I SHOULD WARN YOU THAT I LOOK AT ONLY THE FIRST FIVE LETTERS OF EACH WORD, SO YOU'LL HAVE TO ENTER "NORTHEAST" AS "NE" TO DISTINGUISH IT FROM "NORTH". (SHOULD YOU GET STUCK, TYPE "HELP" FOR SOME GENERAL HINTS. FOR INFOR- MATION ON HOW TO END YOUR ADVENTURE, ETC., TYPE "INFO".) - - - THIS PROGRAM WAS ORIGINALLY DEVELOPED BY WILLIE CROWTHER. MOST OF THE FEATURES OF THE CURRENT PROGRAM WERE ADDED BY DON WOODS (DON @ SU-AI). CONTACT DON IF YOU HAVE ANY QUESTIONS, COMMENTS, ETC. YOU ARE STANDING AT THE END OF A ROAD BEFORE A SMALL BRICK BUILDING. AROUND YOU IS A FOREST. A SMALL STREAM FLOWS OUT OF THE BUILDING AND DOWN A GULLY. _ enter YOU ARE INSIDE A BUILDING, A WELL HOUSE FOR A LARGE SPRING. THERE ARE SOME KEYS ON THE GROUND HERE. THERE IS A SHINY BRASS LAMP NEARBY. THERE IS FOOD HERE. THERE IS A BOTTLE OF WATER HERE. _ get GET WHAT? _ keys OK _ lamp WHAT DO YOU WANT TO DO WITH THE LAMP? _ get OK _ bottle WHAT DO YOU WANT TO DO WITH THE BOTTLE? _ get OK _ get food OK _ look SORRY, BUT I AM NOT ALLOWED TO GIVE MORE DETAIL. I WILL REPEAT THE LONG DESCRIPTION OF YOUR LOCATION. YOU ARE INSIDE A BUILDING, A WELL HOUSE FOR A LARGE SPRING. _ out YOU'RE AT END OF ROAD AGAIN. _ quit DO YOU REALLY WANT TO QUIT NOW? _ y OK YOU SCORED 27 OUT OF A POSSIBLE 350, USING 11 TURNS. YOU ARE OBVIOUSLY A RANK AMATEUR. BETTER LUCK NEXT TIME. TO ACHIEVE THE NEXT HIGHER RATING, YOU NEED 9 MORE POINTS. 10.09.44 FREE *CR0 ,26 TRANSFERS 10.09.44 FREE *LP0 ,130 TRANSFERS 1.07 :DELETED : 00 10.09.44 1.07 DELETED,CLOCKED 0.02 10.09.44_
10.45.02 2.08 CORE GIVEN 37632 2.08 :HALTED : LD END OF MACRO PARAMETER NUMBER 8 UNACCESSED END OF MACRO INITIALISING... TABLE SPACE USED: 6523 OF 6550 WORDS OF MESSAGES 741 OF 750 TRAVEL OPTIONS 297 OF 300 VOCABULARY WORDS 140 OF 150 LOCATIONS 53 OF 100 OBJECTS 31 OF 35 ACTION VERBS 201 OF 205 RTEXT MESSAGES 10 OF 12 CLASS MESSAGES 9 OF 20 HINTS 32 OF 35 MAGIC MESSAGES 10.45.04 FREE *TR0 ,1809 TRANSFERS 2.10 :HALTED : INIT DONEThe changes required were minor:
Index: adven.f4 =================================================================== RCS file: /usr/local/lib/cvs-repo/adventure/adv350-pdp10/adven.f4,v retrieving revision 1.21 diff -u -r1.21 adven.f4 --- adven.f4 27 May 2010 20:52:13 -0000 1.21 +++ adven.f4 26 Jun 2010 08:52:13 -0000 @@ -16,7 +16,7 @@ C ADVENTURES C CURRENT LIMITS: -C 9650 WORDS OF MESSAGE TEXT (LINES, LINSIZ). +C 6550 WORDS OF MESSAGE TEXT (LINES, LINSIZ). C 750 TRAVEL OPTIONS (TRAVEL, TRVSIZ). C 300 VOCABULARY WORDS (KTAB, ATAB, TABSIZ). C 150 LOCATIONS (LTEXT, STEXT, KEY, COND, ABB, ATLOC, LOCSIZ). @@ -47,7 +47,7 @@ COMMON /WIZCOM/ WKDAY,WKEND,HOLID,HBEGIN,HEND,HNAME, 1 SHORT,MAGIC,MAGNM,LATNCY,SAVED,SAVET,SETUP - DIMENSION LINES(9650) + DIMENSION LINES(6550) DIMENSION TRAVEL(750) DIMENSION TRAVL2(750) DIMENSION KTAB(300),ATAB(300) @@ -62,7 +62,7 @@ DIMENSION MTEXT(35) DIMENSION TK(20),DSEEN(6),DLOC(6),ODLOC(6),HNAME(4) - DATA LINSIZ/9650/,TRVSIZ/750/,LOCSIZ/150/, + DATA LINSIZ/6550/,TRVSIZ/750/,LOCSIZ/150/, 1 VRBSIZ/35/,RTXSIZ/205/,CLSMAX/12/,HNTSIZ/20/,MAGSIZ/35/ C STATEMENT FUNCTIONS C @@ -253,13 +253,13 @@ C SECTIONS 1, 2, 5, 6, 10, 12. READ MESSAGES AND SET UP POINTERS. -1004 READ(1,1005)LOC,(LINES(J),J=LINUSE+1,LINUSE+14),KK -1005 FORMAT(I0,15A5) +1004 READ(1,1005)LOC,(LINES(J),J=LINUSE+1,LINUSE+9),KK +1005 FORMAT(I0,9A8,A1) CALL OVERFL (J) IF(.NOT. EQUAL (KK, ' '))CALL BUG(0) IF(LOC.EQ.-1)GOTO 1002 - DO 1006 K=1,14 - KK=LINUSE+15-K + DO 1006 K=1,9 + KK=LINUSE+10-K IF(.NOT. EQUAL (LINES(KK), ' '))GOTO 1007 1006 CONTINUE IF(LOC.EQ.0)GOTO 1004 @@ -298,7 +298,7 @@ 1020 LINUSE=KK+1 LINES(LINUSE)=-1 OLDLOC=LOC - IF(LINUSE+14.GT.LINSIZ)CALL BUG(2) + IF(LINUSE+9.GT.LINSIZ)CALL BUG(2) GOTO 1004 C THE STUFF FOR SECTION 3 IS ENCODED HERE. EACH "FROM-LOCATION" GETS A Index: advn2.f4 =================================================================== RCS file: /usr/local/lib/cvs-repo/adventure/adv350-pdp10/advn2.f4,v retrieving revision 1.13 diff -u -r1.13 advn2.f4 --- advn2.f4 26 Jun 2010 08:23:33 -0000 1.13 +++ advn2.f4 26 Jun 2010 08:52:14 -0000 @@ -50,7 +50,7 @@ LOGICAL BLKLIN COMMON /TXTCOM/ RTEXT,LINES COMMON /BLKCOM/ BLKLIN - DIMENSION RTEXT(205),LINES(9650) + DIMENSION RTEXT(205),LINES(6550) IF(N.EQ.0)RETURN IF(EQUAL(LINES(N+1),'>$<'))RETURN @@ -59,7 +59,7 @@ 1 L=IABS(LINES(K))-1 K=K+1 WRITE (2,2) (LINES(I),I=K,L) -2 FORMAT(' ',14A5) +2 FORMAT(' ',9A8) K=L+1 IF(LINES(K).GE.0)GOTO 1 RETURN @@ -75,7 +75,7 @@ IMPLICIT INTEGER(A-Z) COMMON /TXTCOM/ RTEXT,LINES COMMON /PTXCOM/ PTEXT - DIMENSION RTEXT(205),LINES(9650),PTEXT(100) + DIMENSION RTEXT(205),LINES(6550),PTEXT(100) M=PTEXT(MSG) IF(SKIP.LT.0)GOTO 9Note that the original "FORMAT(I0,15A5)" has been replaced by "FORMAT(I0,9A8,A1)" rather than the obvious translation "FORMAT(I0,10A8)" as the Fortran runtime crashes if we even hint that we are going to read a record longer that 80 characters. Herman Holerith rules from beyond the grave.
All questions to john@AtlanTech.com