Cross-OS Operation of Papertape BASIC ===================================== This document describes an overlay for BASIC (20392 RevA/B) and a package for HP-IPL/OS that permits calling BASIC from HP-IPL/OS then returning. The overlay provides several CALL commands for exiting, peeking and poking memory, executing arbitrary machine code and directly accessing the console for single-character I/O. The IPL package provides words for checking to make sure BASIC is in alt mem and there is sufficient "common" memory for the requested transfer, words for setting and retrieving common variables, and words for initializing, editing and running BASIC. These components make it possible to create a BASIC system containing code that can be operated manually or called from a HP-IPL/OS application. Once set up, VDOS and XDOS/SFS apps can be programmed to load the BASIC portion of the application automatically, papertape apps can be programmed to prompt to attach the BASIC portion then load it into alternate memory. Apps can be programmed to check common memory to detect if the proper BASIC app exists in alternate memory to avoid reloading if already present. Saving the configured BASIC system and reloading it into alternate memory varies depending on the HP-IPL/OS system being used, options include raw emulated papertape, VDOS for using with a VDRIVE USB disk module, and/or XDOS for using with a SFS-formatted IDE disk. These components require a HP21MX-class machine such as a HP2113 with floating point instructions, DMS and at least 64KW memory. The HP-IPL/OS build must contain the dms.ipl, altutil.ipl and float.ipl packages in the dictionary before loading the cross.ipl package. For VDOS or papertape operation the fcam.ipl package is highly recommended for saving the base BASIC binary with the overlay as well as BASIC application binaries, otherwise PTZERO and AAOUT must be used to manually save ABS files. For XDOS/SFS, the AM2F and F2AM words can be used to save and load BASIC binary files. Preparing a base BASIC system containing the overlay ---------------------------------------------------- First the overlay in cross.asm needs to be assembled to cross.abs if not already done, EXTASMB or the Asm cross-assembler can assemble the code. The essential steps are... Load a plain configured BASIC binary Load the cross.abs overlay Patch BASIC to add a run vector and jump to 77000 when BYE is used Run the system (default location 100) to initialize with the overlay Exit BASIC and save the base BASIC system with the overlay The specifics of these steps vary depending on the HP-IPL/OS system. The overlay can also be used independent of HP-IPL/OS but the exit calls are HP-IPL/OS-specific and must not be used unless run from HP-IPL/OS. Procedure for making the base BASIC overlay system with papertape... Boot a HP-IPL/OS build containing dms, altutil and fcam packages Enter ALTSAVE ZAM to add the swapper and clear alt mem Attach the plain configured BASIC ABS binary to PTR Enter ABSLOAD to load it into alt mem Attach the cross.abs binary to PTR Enter ABSLOAD to load it into alt mem Enter ALTRUN to patch BASIC and run it, the READY prompt should appear Enter BYE to exit BASIC and return to HP-IPL/OS Enter AM2ABS and wait for it to scan alt mem Press Y to accept the detected ranges and save as ABS Attach PTP to the output ABS file for the base BASIC system with overlay press Y at the halt prompt if you need to halt to do this otherwise press N to continue The utility should say it's saving Detach the PTP output file, continue if halt was selected. Procedure for making the base BASIC overlay system with VDOS... These instructions assume booting from the USB disk adapter or similar, adapt as needed if booting from something else. Copy the plain configured BASIC ABS and cross.abs binaries to a thumbdrive Make sure there's a VDOS boot build in the HPBOOT, preferably containing the fcam package but if not make sure there's a VDOS build with fcam on the thumbdrive that can be loaded after booting Boot the HP from the thumbdrive and if needed VLOAD a build with fcam Enter VDIR to ensure that the BASIC and overlay files are present Enter ALTSAVE ZAM to add the swapper and clear alt mem Enter "BASIC28.ABS" VREAD ABSLOAD to load BASIC (adjust fn as needed) Enter "CROSS.ABS" VREAD ABSLOAD to load the overlay (adjust fn as needed) Enter ALTRUN to patch BASIC and run it, the READY prompt should appear Enter BYE to exit BASIC and return to HP-IPL/OS Enter "BASCROSS.ABS" VWRITE to attach output binary (adjust fn as needed) Enter AM2ABS to run the save utility, after it prompts press Y then N Enter VCLOSE to close the output file Procedure for making the base BASIC overlay system with XDOS/SFS... This requires PTR capability using a pass-through emulator or other means to load the binaries. If a plain BASIC is already saved as a system file, replace the initial ALTSAVE ZAM Attach ABSLOAD commands with "filename" F2AM to accomplish the same thing, in which case only the cross.abs overlay needs to be loaded via PTR. Boot the XDOS system, if SFS present enter -SFS to close all buffers Enter ALTSAVE ZAM to add the swapper and clear alt mem Attach the plain configured BASIC ABS to PTR Enter ABSLOAD to load it into alt mem Attach the cross.abs binary to PTR Enter ABSLOAD to load it into alt mem Enter ALTRUN to patch BASIC and run it, the READY prompt should appear Enter BYE to exit BASIC and return to HP-IPL/OS Enter "BASCROSS.SYS" 174000 AM2F to save the system to a file Manual save procedure... If the fcam package isn't loaded (or is deemed too slow), the 28KW BASIC with the overlay can be punched to PTP or another MS output device using the following commands... Attach PTP to output file or set MS to output driver PTZERO 2 13200 AAOUT 67100 67677 AAOUT 72000 72377 AAOUT PTZERO Detach output file If BASIC wasn't prepared for 28KW then adjust the middle AAOUT command. This assumes no BASIC program is entered and the cross overlay is the only extra code loaded, otherwise the numbers have to be adjusted. If in doubt a single 2 72377 AAOUT command will save everything up to the end of the overlay but the resulting file will be much larger. AM2ABS from the fcam.ipl package automatically detects BASIC and other code to avoid having to determine which areas of memory to save. Using the cross.ipl package --------------------------- The cross.ipl package isn't necessary to use BASIC with the overlay but it makes it easier to pass data back and forth between HP-IPL/OS and BASIC, and contains words for initializing, editing and running BASIC programs. The cross.ipl package can also be used with the stock BASIC for general use without the ability to return to HP-IPL/OS under program control. Load the cross.ipl package (LOAD VLOAD import and XLOAD depending on system) into an existing DMS/altutil/float build (with VDOS or XDOS if a disk system, fcam package also required with papertape or VDOS to save BASIC apps). If desired save to a new build (SYSALL VSAVE XSAVE depending on system). Load the "cross" BASIC with overlay into alternate memory. For papertape attach to PTR then ALTSAVE ZAM ABSLOAD to load into alt mem without running. For VDOS enter "BASCROSS.ABS" VREAD ALTSAVE ZAM ABSLOAD (adjust fn as needed), for XDOS enter "BASCROSS.SYS" F2AM (adjust fn as needed). IPL loading, saving builds and loading binaries for various systems are core operations and not covered here in detail, the main consideration is that ALTSAVE must be run at least once since powerup to put the swapper in memory since this is the mechanism used to run BASIC via the BAS words or by doing 77000 RUN. The cross.ipl words use locations 150-155 in main memory for temp usage, as does many other words so this shouldn't be an issue. To verify BASIC is in alt memory enter 0 CHKBAS DROP - if an error message is displayed then BASIC isn't loaded. CHKBAS can be used from programs to verify that BASIC is loaded and there is sufficient common memory for passing parameters, call with the needed number of variables on the stack, pushes 0 if OK, 1 if BASIC is not present, or 2 if there isn't at least the specified number of variables in the common memory area. Also prints messages to the console. A variation is in the CHKCOM word, except this word checks to see if a specific variable exists (1 for the first variable, 2 for the 2nd etc), does not push a result, and warmboots the system if BASIC isn't loaded or the specified variable doesn't exist. All of the transfer words call CHKCOM to cancel the process if misprogrammed. Enter BASINIT to run BASIC from scratch with no program in memory. In BASIC enter BYE to return to HP-IPL/OS. Enter BASEDIT to re-enter BASIC without clearing the program to continue editing a program. Enter BASRUN to run BASIC and execute the program in memory. If the BASIC program uses CALL(1) or CALL(2) it returns to HP-IPL/OS automatically without having to enter the BYE command. The BASAUTO word patches BASIC to auto-run without actually running it, do this manually or from another word before calling a BASIC program as a subroutine. Enter 77000 RUN or use from a word to execute the swapper and run the BASIC program. There are two ways to pass data between HP-IPL/OS and BASIC, the "hardcore" way is to use memory above 76001 octal and in BASIC use the peek and poke calls to directly access and set the memory. This method requires knowledge of the HP-IPL/OS memory map - memory from 76400-77177 (thereabouts) is used by the swappers and will be overwritten or break the system if used. The "proper" way to pass the data is just like it was in the late '60's, use COM to dimension an array at the beginning so the data exists in a known location and can be easily read and set from BASIC by simply accessing the array elements. For convenience the transfer words number the variables by the array element, starting at 1. To store a float into BASIC use fp1 fp2 varnum F>BAS where fp1 and fp2 are a floating point number (use $>FP to use a string) and varnum is the common array element into which to store the number. To store an integer into BASIC use integer varnum I>BAS where integer is a 16-bit number and varnum is the common array element. The I>BAS word merely converts the integer to float then calls F>BAS. To retrieve a float from BASIC use varnum F$ for a string. To retrieve an integer from BASIC use varnum IBAS, BASIC sees -32768. 177777 octal is -1 to BASIC. The BASIC number "32768" cannot be retrieved using IFP 1 F>BAS to set variable 1. Enter 2 2 I>BAS to put a 2 in variable 2. Enter 77000 RUN to execute the BASIC program Enter 3 F$ $PRINT to fetch and print variable 3. Should print 6.28318 to the console. These or similar commands could just as easily have been in a word. If many BASIC functions are needed by an application program the BASIC code can be programmed to check say the first COM element and branch accordingly. Multiple or 2-dimensional arrays can be used but you'll have to figure out which varnum corresponds with which array element. Using the overlay functions --------------------------- The cross.abs overlay provides the following CALL functions... CALL(1) EXIT - jumps to 77000 to exit, restarting HP-IPL/OS CALL(2) WEXIT - adds code to 77100 to "return" from BASIC CALL(3,address,data) POKE - put data into address CALL(4,address,var) PEEK - put data from address into var CALL(5,address) EXEC - execute subroutine at address and return CALL(6,address) JUMP - execute code at address, don't return CALL(7,var) GETCH - set var to next byte from console CALL(8,byte) PUTCH - send byte to console In BASIC addresses and data is specified in signed decimal so be very careful when using POKE PEEK EXEC and JUMP. For the POKE number, any value greater than 32767 *must* have 65536 subtracted from it to use the negative equivalent. If in the listing CALL parameters have a "." after the number then the number is out of range with one exception. Octal 100000 is written as -32768 but is still listed with a "." after it. Programmer beware... plus this code hasn't been exhaustively tested, if I discover bugs I'll fix or document, using floats to represent code values is scary stuff. Perhaps the most useful functions are CALL(1) and CALL(2) which exit BASIC under program control, CALL(1) does the same as the BYE patch and causes HP-IPL/OS to restart, CALL(2) acts as a "return" statement so that HP-IPL/OS can execute BASIC (77000 RUN) with BASIC patched to autorun (alt mem 2/3 = jump to 5137, or use the BASAUTO word), when the BASIC app runs CALL(2) it exits back to HP-IPL/OS to continue execution at whatever follows the 77000 RUN sequence. In other words, all of BASIC becomes essentially another word. The EXEC function permits calling a machine code subroutine without using the CALL mechanism and the manipulations needed to enable them, just put the subroutine in memory somewhere where it won't conflict then CALL(5,address) to run the code. Address must equal the initial "nop". The JUMP function permits jumping to non-subroutine code without returning. For example CALL(6,2655) causes the program to rerun. The GETCH and PUTCH functions bypass the TTY drivers to permit typing and sending arbitrary characters. Here is a demo program using these calls... 100 PRINT "CALL 7/8 DEMO, TYPE ESC TO EXIT" 110 PRINT "TYPE A KEY: "; 120 CALL (7,C) 130 IF C=27 THEN 300 140 PRINT " KEY "; 150 CALL (8,C) 160 PRINT " IS ASCII";C 170 GOTO 110 300 PRINT " " 310 STOP 999 END RUN CALL 7/8 DEMO, TYPE ESC TO EXIT TYPE A KEY: A KEY A IS ASCII 65 TYPE A KEY: B KEY B IS ASCII 66 TYPE A KEY: C KEY C IS ASCII 67 TYPE A KEY: [escape] READY ...thus papertape BASIC is no longer limited to just entered numbers. The BEASI game can definitely benefit from this. CALL 8 can also be used to send terminal control codes for overwriting and clearing the display. CALL 7 can be used to implement string input into an array. The solution isn't perfect - if a key is pressed while BASIC is running (such as during the delay or any other processing) then it can be interpreted as a STOP signal - game over - so the user has to be careful when keys are pressed. There's probably a way to disable this behavior... and there is... location 2201 - stock value is 114123, put a 126200 there and pressing keys no longer stops the program but they still echo to the screen so can mess up formatting. Hmmm... would be nice to backspace if a errant key detected but so far no luck getting that to work (interrupts..). Still for a game using calls for direct input, adding a CALL (3,1153,-21376) to disable stop is probably a lot better than the program halting at the first misplaced keystroke. Disabling stop on a HP21MX mini doesn't mean it can't be stopped - the machine has a halt button, just halt, select P, set to 2027, store, run, LIST and continue editing. Or under sim press control-E then run 2027. These GETCH and PUTCH calls are supposed to patch themselves to the configured TTY slot but this is a bit tricky - the prepare program rearranges and changes instructions in the driver code according to mysterious criteria. To compensate I used a configured system to check the code location 102 points to then counted ahead to the first TTY instruction then put the offset and base instructions in the TTYOS and TTYIS locations. If the instruction doesn't match it doesn't patch (default is TTY=slot 11). Location PSLOT can be checked to see if patching was done. Code for the test implementation -------------------------------- Here is the assembly code for the overlay, followed by the IPL package... ------- begin cross.asm --------------------------------------------- ASMB,A,B,L * * Overlay for BASIC 20392 running on HP21MX with HP-IPL/OS * Original 11/29/10 Last mod 12/4/10 * * CALL(1) EXIT - jumps to 77000 to exit, restarting HP-IPL/OS * CALL(2) WEXIT - adds code to 77100 to "return" from BASIC * CALL(3,address,data) POKE - put data into address * CALL(4,address,var) PEEK - put data from address into var * CALL(5,address) EXEC - execute subroutine at address and return * CALL(6,address) JUMP - execute code at address, don't return * CALL(7,var) GETCH - set var to next byte from console * CALL(8,byte) PUTCH - send byte to console * * Installation... * Load BASIC (attach to PTR then ALTSAVE ZAM ABSLOAD) * Load this overlay on top of it (attach to PTR then ABSLOAD) * Run BASIC from location 100 (ALTRUN) * Exit BASIC and save binary (BYE then AM2ABS or other means) * Note... this code (~72000-72377) must also be saved with binary * ORG 121B DEF LINKS DEF LKEND ORG 72000B HLT 1 wild execution barrior JMP *-1 don't allow continue * * link table... LINKS OCT 1 call 1 no parms DEF EXIT normal swap exit OCT 2 call 2 no parms DEF WEXIT exit to next word OCT 1003 call 3 two parms DEF POKE poke memory OCT 1004 call 4 two parms DEF PEEK peek memory OCT 405 call 5 one parm DEF EXEC execute subroutine OCT 406 call 6 one parm DEF JUMP jump to code OCT 407 call 7 one parm DEF GETCH get char from console OCT 410 call 8 one parm DEF PUTCH send char to console LKEND EQU * * * 21MX FP subs - this package is designed for running from * HP-IPL/OS with DMS enabled, assuming the machine has FP * If not then replace DOFLT and DOFIX with FP convert code * and don't use the exit calls (1 and 2). * * Convert 16 bit int in A to FP in A/B DOFLT NOP OCT 105120 JMP DOFLT,I * * Convert FP in A/B to 16 bit int in A * note - no error check, GIGO DOFIX NOP OCT 105100 JMP DOFIX,I * * Return code... swap main/alt (2-76001) then JMP 321,I * copy to 77100 then execute, mem from 76400-76777 used for buffer * ORG 77100B RCODE OCT 105734 OCT 105734 * SJP OCT 077102 DEF *+1 * just enable system map OCT 063131 LDA C2 OCT 073135 STA CADR * start at address 2 OCT 105745 LOOP OCT 105745 * LDX OCT 077134 DEF BSIZ * number of words, 400 octal OCT 063135 LDA CADR * source address OCT 067133 LDB BUFF * destination address = 76400 in alt OCT 105705 OCT 105705 * MWI move words into alt OCT 105745 OCT 105745 * LDX OCT 077134 DEF BSIZ * buffer size OCT 063135 LDA CADR * current address in alt OCT 067135 LDB CADR * current address in sys OCT 105706 OCT 105706 * MWF move words from alt map OCT 105745 OCT 105745 * LDX OCT 077134 DEF BSIZ * buffer size OCT 063133 LDA BUFF * source = buffer in alt OCT 067135 LDB CADR * dest = currentaddr in alt OCT 105707 OCT 105707 * MWW move words within alt map OCT 063135 LDA CADR OCT 043134 ADA BSIZ * add 400 oct to current address OCT 053132 CPA ENDA * if at end OCT 124321 JMP 321B,I * run HP-IPL/OS next code OCT 073135 STA CADR OCT 027104 JMP LOOP OCT 000002 C2 OCT 2 OCT 076002 ENDA OCT 76002 * terminate address OCT 076400 BUFF OCT 76400 * buffer at 76400-76777 OCT 000400 BSIZ OCT 400 * buffer size 256 words * CADR OCT 0 * current address RCLST EQU * * * jump to 77000 to exit, stock swapper assumed to exist EXIT NOP JMP *+1,I OCT 77000 * * word exit - copy return code to 77100 then jump to it WEXIT NOP LDA RCBEG STA RCPTR LDB RDEST WLOOP LDA RCPTR,I STA 1,I ISZ RCPTR INB LDA RCPTR CPA RCEND JMP RDEST,I JMP WLOOP RCBEG DEF RCODE RCEND DEF RCLST RDEST OCT 77100 RCPTR OCT 0 * * parm temps PAR1A OCT 0 address PAR1B OCT 0 float 1 PAR1C OCT 0 float 2 PAR1I OCT 0 int value PAR2A OCT 0 PAR2B OCT 0 PAR2C OCT 0 PAR2I OCT 0 M1 DEC -1 for decrementing * * parm subs GET2P NOP LDB 0,I get address of first parm STB PAR1A save address ADA M1 dec ptr LDB 0,I get address of second parm STB PAR2A save JSB PTRAN fetch FP values and convert to int JMP GET2P,I GET1P NOP LDB 0,I get address of first parm STB PAR1A save address JSB PTRAN JMP GET1P,I PTRAN NOP LDA PAR1A get address of parm 1 LDB 0,I get 1st FP word STB PAR1B save INA point to next FP word LDB 0,I get 2nd FP word STB PAR1C save LDA PAR2A same for parm 2 (even if not used) LDB 0,I STB PAR2B INA LDB 0,I STB PAR2C * convert parms to int LDA PAR1B get parm 1 fp 1 LDB PAR1C get parm 1 fp 2 JSB DOFIX convert to fixed STA PAR1I save in parm 1 int LDA PAR2B same for parm 2 LDB PAR2C JSB DOFIX STA PAR2I JMP PTRAN,I * * update parm 1 with int in A * overwrites PARM1B/C PARM1I not affected UPDP1 NOP JSB DOFLT convert to float STA PAR1B save fp 1 STB PAR1C save fp 2 LDB PAR1A get parm address LDA PAR1B get fp 1 STA 1,I save to parm var INB bump pointer LDA PAR1C get fp 2 STA 1,I save to parm var+1 JMP UPDP1,I * * update parm 2 with int in A * overwrites PARM2B/C PARM2I not affected UPDP2 NOP JSB DOFLT STA PAR2B STB PAR2C LDB PAR2A LDA PAR2B STA 1,I INB LDA PAR2C STA 1,I JMP UPDP2,I * * put 2nd parm into address spec'd by 1st parm POKE NOP JSB GET2P get 2 parms convert to int LDA PAR2I get data STA PAR1I,I store in address JMP POKE,I * * put data from address spec'd by 1st parm and put into 2nd parm PEEK NOP JSB GET2P LDA PAR1I,I get memory data JSB UPDP2 update 2nd parm JMP PEEK,I * * execute subroutine at address spec'd by parm EXEC NOP JSB GET1P JSB PAR1I,I JMP EXEC,I * * jump to address spec'd by parm (no return) JUMP NOP JSB GET1P JMP PAR1I,I * * Direct access non-interrupt console drivers * These bypass the normal TTY driver, slot is fetched from * the driver which is assumed to be a Rev A or Rev B version * (no patch occurs if it is not). * * The BASIC TTY driver config is a bit hard to parse... the * prepare program (and even the driver itself) rewrites the code. * The self-patch code here patches only if it finds the right * instruction, otherwise goes with what it has. TTYOS and TTYIS * can be modified if needed to adjust for different config. * TTY EQU 11B default TTY slot TTYOS OCT 11 offset for driver instruction TTYIS OCT 102600 instruction that's supposed to be there SLTCL OCT 177700 mask to clear slot SLTGT OCT 77 mask to get slot TTYIN OCT 160000 TTY input command TTYOT OCT 120000 TTY output command MASKC OCT 177 mask for 7 bits PSLOT OCT 0 patch slot * * patch TTY slot, disable interrupts CONIO NOP CLA STA PSLOT clear slot to determine if patch occured LDA 102B get TTY driver link ADA TTYOS add TTY instruction offset STA 1 put in B reg LDA 1,I get instruction AND SLTCL mask off slot CPA TTYIS is it the instruction we're looking for? RSS yes, skip to do patch JMP NOPAT no, don't patch LDA 1,I get instruction AND SLTGT get slot STA PSLOT save LDB PLIST put start of patchlist in B JSB PATCH do the patch NOPAT CLF 0 disable interrupts JMP CONIO,I * * patch sub - patch list address in B PATCH NOP PATLP LDA 1,I get instruction address to patch STA ADTMP save LDA ADTMP,I get instruction to patch AND SLTCL mask off slot IOR PSLOT set to new slot STA ADTMP,I store patched instruction INB increment patchlist pointer LDA 1,I check next patch address SZA skip if zero JMP PATLP patch some more JMP PATCH,I ADTMP OCT 0 * * list of locations to patch PLIST DEF *+1 DEF TTYP1 DEF TTYP2 DEF TTYP3 DEF TTYP4 DEF TTYP5 DEF TTYP6 DEF TTYP7 DEF TTYP8 DEF TTYP9 DEF TTYPA OCT 0 * * get byte from console and put in parm GETCH NOP JSB GET1P parse parm to set address JSB CONIO set up for non-int I/O LDA TTYIN get TTY input command TTYP1 OTA TTY send to interface TTYP2 STC TTY,C start interface TTYP3 SFS TTY got char? JMP *-1 no, keep looping TTYP4 LIA TTY get char TTYP5 CLC TTY turn off interface AND MASKC mask char JSB UPDP1 update parm STF 0 reenable interrupts JMP GETCH,I * * send byte in parm to console PUTCH NOP JSB GET1P get parm JSB CONIO set up for non-int I/O LDA TTYOT get TTY output command TTYP6 OTA TTY send to interface LDA PAR1I get byte to send AND MASKC mask char TTYP7 OTA TTY send char to interface TTYP8 STC TTY,C start interface TTYP9 SFS TTY accepted? JMP *-1 no, keep looping TTYPA CLC TTY turn off interface STF 0 reenable interrupts JMP PUTCH,I * END ------- end cross.asm ----------------------------------------------- ------- begin cross.ipl --------------------------------------------- ; Words for using the "cross" overlay for BASIC 20392 ; Requires HP-IPL/OS with dms, altutil and float, uses locs 150-155 ; Original version 11/30/10 - Last mod 12/1/10 ; ; size CHKBAS - makes sure BASIC exists and common area is big enough ; size = number of 2-word FP vars to check for ; pushes 0 if all is OK, pushes 1 if no basic, pushes 2 if no common ; (specify size 0 to just check for basic) ; varnum CHKCOM - makes sure there's room for variable, warmboots if not ; fp1 fp2 varnum F>BAS - pokes fp into common variable ; int varnum I>BAS - pokes integer into common variable ; varnum FCCOPY 150 GET IFZ ;if alt loc 2 not defined then DROP #1 "No run address " $PRINT ELSE 100 150 6 A>CCOPY ;get locs 100-105 2 ;matches needed 150 GET 124201 SUB IFZ DEC ENDIF 155 GET 002200 SUB IFZ DEC ENDIF IFNZ ;if not HPBASIC DROP #1 "Not BASIC " $PRINT ELSE DUP IFNZ ;if size <> 0 then check for COM space ;if zero leave zero on stack for OK ASL ;multiply size by 2 110 150 3 A>CCOPY ;get locs 110-112 152 GET 150 GET SUB ;push com size SWAP SUB ;subtract needed size from com size IF<0 ;if not enough room 2 ;indicate com error "Not enough COM " $PRINT ELSE #0 ;indicate all is OK ENDIF ENDIF ENDIF ENDIF ENDIF END ; ; calls CHKBAS to make sure specified variable exists in common area ; warm boots if not or if variable not correctly specified DEFINE CHKCOM ;usage: offset CHKCOM DUP DEC IF<0 WBOOT ENDIF CHKBAS IFNZ WBOOT ENDIF END ; ; puts float into specified common variable DEFINE F>BAS ;usage: fp1 fp2 varnum F>BAS DUP CHKCOM ;validate basic/common ;common start in loc 150 DEC ASL 150 GET ADD S>Z ;calculate address, save to z SWAP 154 SWAP PUT 155 SWAP PUT ;put FP words in 154,155 154 Z>S 2 C>ACOPY ;copy into common area END ; ; puts integer into specified common variable DEFINE I>BAS ;usage: value varnum I>BAS S>Z FLT Z>S F>BAS END ; ; pushes 2-word float from specified common variable DEFINE FCCOPY ;copy to locs 154,155 154 GET 155 GET ;push to stack END ; ; pushes integer from specified common offset DEFINE IACOPY ALTRUN ENDIF END ; ; patches BASIC to initialize (clear) then runs it DEFINE BASINIT #0 CHKBAS IFZ 155 100 PUT 155 3 #1 C>ACOPY ALTRUN ENDIF END ; ; patches BASIC to autostart program, run before calling as a sub DEFINE BASAUTO #0 CHKBAS IFZ 155 5137 PUT 155 3 #1 C>ACOPY ENDIF END ; ; patches BASIC to autostart then runs program DEFINE BASRUN #0 CHKBAS IFZ BASAUTO ALTRUN ENDIF END ; CONSOLE ------- end cross.ipl ----------------------------------------------- Bugs... Original versions of this code (as typical) contained bugs. Slot patching didn't work in 11/29/10 version (patched the patch locs, duh). Also in cross.ipl used 2050 for BASIC re-enter vector, 2027 works better. 12/1/10 version and before delayed before console I/O, don't need to as (unlike BCS) TTY processing in BASIC isn't interrupt-driven. Removed delay. 12/3/10 version and before failed for 7-bit serial with parity - a problem that only shows up on my real system with a 2400 baud console. Fixed mask. The present 12/4/10 versions seem to work on my HP2113, I think it's OK but we'll see... test versions are posted sooner rather than later to encourage myself to not mess with it too much other than fixing issues... when the code stops changing that's when I know it's "done" (enough for now). Going further... This "compact" version of the overlay is designed for HP-IPL/OS running on a MX-type machine with FP, as written it conflicts with Octapus (but can re-org) and has no options for saving BASIC apps without the help of HP-IPL/OS. Also saving using fcam's AM2ABS utility isn't the most efficient way to save BASIC apps (takes a long time to scan), need to add a word to cross.ipl for saving BASIC with the overlay, but it would be system-specific. For XDOS nothing really needs doing, just "BASICAPP" 174000 AM2F and it'll save everything. For papertape/VDOS need a word something like... OCTAL DEFINE SVBAS ;assumes MS output is attached to file, requires APUT/AGET from fcam.ipl 105 AGET 2200 SUB IFNZ "BASIC not detected " $PRINT ELSE "Saving BASIC w/overlay... " $PRINT PTZERO ;output leader 2 113 AGET AAOUT ;save BASIC and program 111 AGET DUP 176000 AND 1677 OR AAOUT ;save BASIC drivers 70000 75777 AAOUT ;save high mem, adjust as needed PTZERO ;output trailer ENDIF END CONSOLE ...the overlay save code saves all of high mem to catch all typical 28KW BASIC configs, for a smaller ABS edit the range(s) to save only the memory that's needed. Change the high mem range if using a different config with the overlay code located elsewhere (above the 28KW mark is best for HP21MX). For papertape, after returning to HP-IPL/OS attach PTP to output binary then enter SVBAS to punch it, detach PTP. For VDOS: "APP.ABS" VWRITE SVBAS VCLOSE An expanded "stand-alone" version that doesn't need FP, is compatible with Octapus-D, and can punch itself to an app binary is in the cross2.asm file. Add .txt for web. This version is a bit bloated, menu-driven with detected options for Octapus-D and HP-IPL/OS, and an option to print a summary of the available CALL commands. The expanded version isn't quite as fast as the original as it uses non-hardware BASIC subs for float and fix, but doubtful that can be noticed and probably the best version for general-purpose use with 12KW and greater BASIC configurations. Having Octapus available is handy for BASIC-hacking on real hardware as there's no handy built-in debug console like there is under the SimH HP2100 simulator. A non-HP-IPL/OS version that can be used with a 8KW BASIC system without PTR/PTP drivers is in the smovl.asm[.txt] file, this version inserts itself before the drivers and disables matrix instructions. Operation is simplistic, BYE halts, if continued punches all memory to default punch channel (can change a memory location to change), if continued again re-enters BASIC. Final thoughts for this doc... This is an exploration of vintage software, both what it does as-is, and also what can be done to make it do other stuff. Some of the things I bend the software to do are probably far beyond anything the creators of the software intended, yet the mechanisms to do anything the machine can do are often built-in (the only "non-official" mod in this doc was to overwrite an instruction in the stop code so it wouldn't stop.. nice of them to put that part in a subroutine to permit such a simple hack). I can't help but wonder what kinds of hacks HP21xx users did back then. ---------------------------------------------------------------------------- Terry Newton (wtn90125@yahoo.com) Last modified 12/4/10