; 300 To 2000 BAUD LOADER PROGRAM ; (C) 1981 Jay Fenton for Astrovision Inc. ; ; ******************************************************** ; ; Typed in on Dec. 16, 2007 by Adam Trionfo ; ; Compile with Zmac using: ; ; zmac -i -m -o 300-2000.bin -x 300-2000.lst 300-2000.asm ; ; See comments at end of program ; ; ******************************************************** ; ; This program loads audio tapes generated by the old ; version of BALLY BASIC into the New and Improved version ; of BALLY BASIC. ; ; Operating Instructions ; ; 1) Load the LOADER PROGRAM into memory using the :RUN ; command. When loaded the screen background ; brightness will change continuously. ; 2) Cue up the 300 baud tape and PLAY it. ; 3) Press the GO key to release the LOADER PROGRAM. ; 4) Observe the program statements accumulating in ; the buffer just below the program zone. The screen ; will reveal the scratchpad during this phase. ; 5) Program loading will stop on any of the following ; conditions: ; a) :RETURN is found in an unnumbered line. ; b) RUN is found in an unnumbered line. ; c) The HALT key is pressed, in which case we ; proceed to end loading. ; d) Any other key in the column beneath HALT ; is pressed. ; Cases a), b), and d) cause the program to go ; back to step 2) ; If no more segments are to be loaded, press ; HALT to proceed to final loading. ; 6) After HALT is pressed the program will convert the ; statements in the buffer into the representation ; used within BALLY BASIC. This is done by moving ; the buffer to the highest possible address and ; using special I/O routines which feed characters ; from this buffer to the BALLY BASIC input routines. ; This will be seen on the screen as a race between ; the input buffer and the program storage area. ; 7) The LOADER PROGRAM will then exit to BALLY BASIC. ; The variables A-Z will be zeroed out, and the screen ; will be cleared. The program may now be executed or ; written out at 2000 baud. ; ; NOTES: ; During the readin phase, lines without line numbers, ; rubout characters, and spaces appearing before and ; immediately after line numbers are filtered out. ; It is permissible to load tapes which contain line ; numbers out of sequence or which delete previous ; lines. INCLUDE HVGLIB.H ; Home Video Game Library Header ; ; These equates establish addresses within BALLY BASIC. ; INIT0 EQU 2531H ; HALT ROUTINE ENTRY CHKIO EQU 4E98H ; INPUT CHARACTER HOOK VECTOR OUTCH EQU 4E9BH ; OUTPUT CHARACTER HOOK VECTOR TXTUNF EQU 4E20H ; PROGRAM STORAGE AREA POINTER VARBGN EQU 4E22H ; VARIABLE AREA START ADDR BUFSTART EQU 4280H ; 300 BAUD BUFFER START LASTBUF EQU 4E55H ; LAST BYTE WHICH BUFFER CAN USE HKVECT EQU 4E92H ; HOOK VECTOR AREA START HOOKER EQU 218BH ; INITIAL HOOK VECTOR VALUES TARGET EQU 4F2AH ; ADDR TO RELOCATE I/O ROUTINE TO SAVDAT EQU 4F26H ; REMEMBERS DATA BENEATH TXTUNF POINTER EQU 4F28H ; 300 BAUD INPUT BUFFER POINTER STACK EQU 4FEAH ; TOP OF BASIC STACK ZONE GL2 EQU 2C68H ; RET ADDR FOR OUTCH TO SKIP GL2A EQU 2C70H ; ADDR IN INPUT LINE ROUTINE TO SKIP TO ; BIT BANGER GOODIES FOLLOW: BANGIN EQU 3C00H ; BIT BANGER READ PORT BANG1 EQU 3800H ; BIT BANG CODE TO WRITE A ONE BANG0 EQU 3C00H ; BIT BANG CODE TO WRITE A ZERO ; ; PARAMETERS FOR 300 BAUD BIT DETECTOR ; THESE SPECIFY THE MINIMUM AND MAXIMUM NUMBER ; OF CONSECUTIVE CYCLES OF TONE REQUIRED TO ; RECOGNIZE A ZERO OR A ONE BIT MIN0 EQU 3 MAX0 EQU 4 MIN1 EQU 6 MAX1 EQU 8 ; ; ; SOME CHARACTER EQUATES RUBOUT EQU 1FH ; BASIC 'ERASE' CHARACTER NL EQU 0DH ; ASCII NEW LINE ; HLTPORT EQU 15H ; KEYPAD COLUMN FOR HALT KEY ; ORG 4000H ; :RUN EXECUTION BEGINS HERE BEGIN STARTUP DI ; NIX INTERRUPTS XOR A ; USE OTHER COLOR REGISTERS OUT (HORCB),A LD A,2 ; GREY SCALE FOREGROUND OUT (COL1R),A RLCA OUT (COL2R),A LD A,7 OUT (COL3R),A LD A,204 OUT (VERBL),A LD HL,BUFSTART ; RESET 300 BAUD LD (POINTER),HL ; BUFFER POINTER ; WAIT FOR USER TO SWITCH TAPES ; WHEN DONE USING ORGANISM WILL PRESS 'GO' KEY REREAD CUEW IN A,(17H) ; SENSE 'GO' HEY COL. AND 3FH ; IS GO KEY DOWN? JR NZ,GOTQ ; YES - WE GOT ONE IN A,(HLTPORT) ; READ HLT COLUMN AND A ; CHECK HALT COLUMN JP NZ,TAF ; IF SO ENDIT INC BC ; SWEEP BC TO SHOW LD A,B ; WE ARE WAITING RRCA ; FOR CUE RRCA RRCA AND 7 ; SWEEP ONLY OUT (COL0R),A ; GRAY SCALE JR CUEW ; WE GOT THE CUE GOTQ XOR A ; BACK TO OUT (COL0R),A ; BLACK ; NOW WE WAIT FOR 10 CONSECUTIVE 1 BITS TO APPEAR ; THIS WILL IGNORE ANY GARBAGE APPEARING BEFORE THE ; PROGRAM DATA WLDR LD L,10 ; (RE)SET BIT CTR WLL CALL GETBIT ; GET BIT FROM TAPE JR Z,WLDR ; ZERO-START OVER DEC L ; ONE-COUNT IT JR NZ,WLL ; AWAIT QUOTA ; WE NOW FALL INTO THE ... ; AWAIT LINE NUMBER STATE-IGNORE EVERYTHING UNTIL A LINE ; NUMBER APPEARS - THIS WILL DISRREGARD ANY UNNUMBERED ; COMMANDS ; IF AN UNNUMBERED 'RUN' OR ; :RETURN COMMAND IS FOUND WE ENTER ; THE AWAIT NEXT SEGMENT CUE STATE WLN CALL GETBYTE ; GET BYTE FROM TAPE NRET CP ':' ; HAVE WE GOT A COLON? JR Z,COLN ; YEP, TRY FOR :RETURN CP 106 ; 'RUN' COMMAND? JR Z,REREAD ; YEP- THEN QUIT CALL TSTNUM ; IS SHE A NUMBA? JR NC,WLN ; NO-IGNORE IT STUF CALL STUFBUF ; STORE HER AWAY ; WE ARE NOT ON A NUMBER ; NOW WE COPY NUMBERS, AND IGNORE SPACES UNTIL A NONSPACE, ; NONNUMERIC IS DETECTED IGNS CALL GETBYTE ; FETCH ANOTHER VICTIM CALL TSTNUM ; TEST FOR NUMERIC JR C,STUF ; YEP-KEEP LOOKING CP ' ' ; A SPACE PERHAPS? JR Z,IGNS ; IGNORE THE BLANK JR LIN1 ; NONBLANK - LEAVE STATE ; TRY FOR :RETURN STATE - WE CAME HERE AFTER ; READING IN A COLON, SO IF WE GET A 'RETURN' ; WE CAN CEASE LOADING THE SEGMENT COLN CALL GETBYTE ; READ ANOTHER BYTE CP ' ' ; ALLOW JR Z,COLN ; INTERMIXED SPACES CP 112 ; :RETURN TOKEN JR NZ,NRET ; IF NOT GO BACK JP REREAD ; YEP-END THIS SEG ; READ LINE STATE ; WE WILL HANG OUT HERE UNTIL A NEW LINE COMES IN ; IN WHICH CASE WE WILL GO BACK TO 'AWAIT LINE NUMBER' LINL CALL GETBYTE ; FETCH NEXT BYTE LIN1 CP RUBOUT ; IF RUBOUT IGNORE IT JR Z,LINL CALL STUFBUF ; STUFFER IN THE BUFFER CP NL ; IF NEW LINE JR Z,WLN ; WAIT FOR NEXT LINE # JR LINL ; ELSE GOFOR NEXT CHAR ; ROUTINE TO TEST FOR CHARACTER BEING NUMERIC TSTNUM CP '0' ; LESS THAN ZERO? JR C,NN ; NO - JUMP CP '9'+1 ; GREATER THAN NINE? RET C ; RETURN CY IF NOT NN AND A ; CLEAR CY BIT RET ; TO SAY NOT NUMBER ; ROUTINE TO STORE A CHARACTER INTO THE BUFFER STUFBUF LD HL,(POINTER) ; GET BUFFER POINTER LD (HL),A ; STUFF CHAR WITHIN INC HL ; BUMP POINTER LD (POINTER),HL ; AND SAVE RET ; AND GO HOME ; GET A BYTE FROM AUDIO TAPE ROUTINE GETBYTE CALL GET0 ; GET A START BIT JR NZ,GETBYTE ; WAIT FOR IT LD HL,800H ; INIT BIT CTR AND ACCUM BYTL CALL GETBIT ; FETCH A BIT OR L ; OR IN DATA SO FAR RRCA ; SHIFT OVER LD L,A ; AND SAVE DEC H ; DCR BIT COUNTER JR NZ,BYTL ; FILL OUT BYTE RET ; GET BIT ROUTINE ; ; THIS ROUTINE INPUTS A BIT IN 300 BAUD FORMAT ; USING THE BUILT-IN AUDIO INTERFACE CIRCUIT ; IT DOES THIS BY MEASURING THE FREQUENCY ; OF THE INPUT SQUARE WAVES. ; AS 8 CONSECUTIVE SHORT SQUARE WAVES DENOTES A ONE BIT ; AND 4 CONSECUTIVE LONG WAVES DENOTES A ZERO BIT ; WE MAINTAIN COUNTERS FOR EACH TYPE, AND RETURN ; ONE OR ZERO WHEN ENOUGH CYCLES ARE COUNTED ; ; THE ENTRY 'GET0' IS ENTERED WHEN A START BIT IS ; SOUGHT. 'GET0' INSISTS ON RECIEVING A FULL LENGTH ; ZERO WAVE GET0 LD C,0 ; SYNC ON START BIT NEXW LD E,0 ; RESET BIT LENGTH TIMER IN A,(HLTPORT) ; SENSE HALT COLUMN AND A ; IF ANY DOWN JP NZ,TAF ; KICKOUT LD A,(BANGIN) ; GET TAPE DATA LD D,A ; STUFF IN TRACKER G0L LD A,(BANGIN) ; SENSE IT AGAIN XOR D ; ANY TRANSITION? RRCA JR C,GOTT ; JUMP IF SO INC E ; COUNT TIME JR NZ,G0L ; TIMEOUT COND? JR GET0 ; YEP - START OVER GOTT LD A,D ; LAST TIME TO ACC LD D,E ; SET NEW LAST TIME ADD E ; SUM LAST AND NOW CP 0FH ; GOOD ENOUGH? JR C,NEXW ; NO-KEEP LOOKIN LD BC,1 ; YEP-COUNT THAT ZERO JR GBNEXT ; AND JOIN GETBIT ; THIS ENTRY IMPOSES NO SPECIAL CRITERIA ; AND IS ENTERED FROM LEADER WAIT AND TO GET ; CHARACTER DATA BITS ; B=ONE COUNTER, C=ZERO COUNTER GETBIT LD BC,0 ; RESET BIT COUNTERS IN A,(HLTPORT) ; ANOTHER HALT COL AND A ; CHECK JP NZ,TAF GBNEXT LD E,0 ; RESET BIT TIMER LD A,(BANGIN) ; SAMPLE TAPE DATA LD D,A ; SAVE IN TRACKER TIME LD A,(BANGIN) ; SAMPLE AGAIN XOR D ; REVEAL TRANSITION RRCA ; IF WE GOT ONE JR C,TRAN ; JUMP OUT INC E ; COUNT TIME JR NZ,TIME ; TIMEOUT CHECK JR GETBIT ; TIMEOUT - START OVER ; WE HAVE ONE HALF CYCLE-SO WE GO FOR THE OTHER HALF ; SAME LOGIC AS ABOVE CODE TRAN LD A,(BANGIN) XOR D RRCA JR NC,GOTB INC E JR NZ,TRAN TIM0 JR GETBIT ; WE HAVE TIMED OUT ; WE HAVE A FULL WAVE TIME - WE WILL ; CLASSIFY IT AND INCREMENT THE APPROPRIATE BIT ; COUNTER IF THE 'OTHER' BIT COUNTER MEETS ; MINIMUM CRITERION WE WILL RETURN THE 'OTHER' BIT ; VALUE, ELSE IF THE 'NOW' BIT COUNTER IS HIGH ; ENOUGH WE WILL RETURN THE 'NOW' BIT ; IF NEITHER ARE LARGE ENOUGH WE WILL KEEP SAMPLING GOTB LD A,E CP 12 ; WHICH HAVE WE? JR C,TRY1 ; JUMP IF ONE TRY0 INC C ; COUNT THE ZERO LD A,B ; ENOUGH ONES? CP MIN1 JR NC,RET1 ; YES - RETURN 1 BIT LD A,C ; AT MAX ZEROS? CP MAX0 JR C,GBNEXT ; NO - GET MORE CYCLES RET0 XOR A ; RETURN A ZERO BIT RET TRY1 INC B ; COUNT A ONE BIT LD A,C ; ENOUGH ZERO BITS? CP MIN0 JR NC,RET0 ; YEP - GO TO ZERO RETURN LD A,B ; MAX ONE BITS? CP MAX1 JR C,GBNEXT ; YEP RET1 XOR A INC A RET ; ; THIS SEQUENCE IS ENTERED AFTER THE USING ORGANISM ; PRESSES A KEY IN THE HALT COLUMN ; IF THE KEY WAS NOT THE HALT KEY WE GO BACK FOR AN ; ADDITIONAL SEGMENT. IF IT WAS HALT WE CLOSE THE BUFFER ; AND THEN RELOCATE THE BUFFER TO THE HIGHEST POSSIBLE ; ADDRESS, ESTABLISH THE SPECIAL I/O ROUTINES IN ; THE BASIC STACK ZONE, AND MODIFY THE HOOK VECTORS ; POINT AT THEM ; WE THEN CALL BASIC TO CONVERT THE BUFFER TAF LD SP,STACK ; RESET THE STACK POINTER RRCA ; WAS THAT A HALT? JP NC,REREAD ; NO - GO BACK FOR NEXT SEGMENT XOR A ; DENOTE OUT OF HALT OUT (COL0R),A LD HL,LASTLINE ; CLOSE THE BUFFER WITH LD DE,(POINTER) ; NL,PRINT,NL,OFFH LD BC,EOLL-LASTLINE+1 LDIR EX DE,HL ; HL = POINTER ; MOVE BUFFER UP TO THE HIGHEST POSSIBLE ADDRESSES LD DE,LASTBUF+1 CPYL DEC HL ; DECREMENT POINTERS DEC DE LD A,(HL) ; FETCH SOURCE LD (HL),0 ; CLEAR SOURCE LD (DE),A ; STORE AT DEST LD A,H ; BACK AT START? CP BUFSTART >> 8 JR NZ,CPYL ; LOOP BACK LD A,L CP BUFSTART & 0FFH JR NZ,CPYL ; IF NOT YET LD (POINTER),DE ; SAVE CORRECTED PTR LD HL,(TXTUNF) ; REMEMBER DATA BENEATH LD (SAVDAT),HL ; TXTUNF LD HL,5555H ; INITIALIZE PROGRAM LD (4002H),HL ; STORAGE AREA LD HL,0A004H ; AND TXTUNF LD (TXTUNF),HL LD HL,TARGET ; PLUG HOOK VECTORS LD (CHKIO+1),HL ; WITH SPECIAL I/O INC HL ; ROUTINES INC HL LD (OUTCH+1),HL ; MOVE THE SPECIAL I/O ROUTINES ; INTO BASIC STACK AREA LD HL,CODS LD DE,TARGET LD BC,ENDPRG-CODS LDIR JP INIT0 ; ENTER BASIC ; THIS INFORMATION IS APPENDED TO THE TAPE BUFFER ; TO CLOSE IT OFF. IT WILL CLEAR THE SCREEN AFTER ; THE CONVERSION PROCESS IS COMPLETE LASTLINE DB NL DB 105 ; TOKEN CODE FOR 'CLEAR' DB NL DB 0FFH ; LIST TERMINATOR EOLL CODS JR LCHKIO ; SPECIAL OUTPUT CHARACTER ROUTINE ; IT REFUSES TO DO ANY PRINTING ; IT DOES CHECK TO SEE WHERE IT WAS CALLED FROM ; IF IT WOULD GO BACK TO GL2 IN ; GLED WE WILL SKIP SEVERAL UGLY INSTRUCTIONS ; WHICH WOULD PUT UP A CURSOR EX (SP),HL ; HL=RETURN ADDR PUSH AF ; SAVE A LD A,H ; CHECK FOR CALL CP GL2 >> 8 ; FROM GL2 JR NZ,OK LD A,L CP GL2 & 0FFH JR NZ,OK ; WE WERE CALLED FROM GL2, SO SHUFFLE STACK AND ; GO BACK AT GL2A POP AF POP HL PUSH BC PUSH HL PUSH DE JP GL2A ; CALL FROM ELSEWHERE - JUST GO HOME OK POP AF EX (SP),HL RET ; GET CHARACTER ROUTINE - FETCHES CHARACTER ; FROM 300 BAUD BUFFER ; WE STORE THE DATA BENEATH TXTUNF JUST IN ; CASE OUT POINTER POINTS THERE LCHKIO LD HL,(TXTUNF) ; SAVE CURRENT TXTUNF PUSH HL LD HL,(SAVDAT) ; GET BUFFER DATA LD (TXTUNF),HL ; AND FUDGE LD HL,(POINTER) ; GET BUFFER PTR LD A,(HL) ; AND CHARACTER LD (HL),0 ; CLEAR CHARACTER INC HL ; BUMP PTR LD (POINTER),HL ; SAVE PTR LD HL,(TXTUNF) ; SAVE BUFFER DATA LD (SAVDAT),HL ; AS MAY BE ZEROED POP HL ; RESTORE TXTUNF LD (TXTUNF),HL INC A ; END OF LIST? JR Z,GEOF ; YEP JUMP DEC A ; NO - FIXIT RET ; AND GO BACK ; WE ARE DONE - RESET VARIABLES TO ZERO ; ZERO A-Z GEOF SYSSUK FILL DW VARBGN DW 52 DB 0 ; RESET HOOK VECTOR SYSSUK MOVE DW HKVECT DW 14 DW HOOKER LD A,176 ; RESET VERTICAL OUT (VERBL),A ; BLANK PORT LD A,44 ; ADD HORIZONTAL OUT (HORCB),A ; COLOR BOUNDARY JP INIT0 ; HALT BASIC ENDPRG ; ; 300 To 2000 BAUD LOADER PROGRAM ; (C) 1981 Jay Fenton for Astrovision Inc. ; ---------------------------------------- ; ; NOTE: To assemble this program header file named HVGLIB ; is required. ; ; This program is for the Bally Astrocade game console and ; the AstroBASIC cartridge. ; ; ; End Comments - Changes/Updates (By Adam Trionfo) ; ------------------------------ ; ; Version 1.0 (Dec. 16, 2007) ; ; - Program first re-typed from source-code ; ; - All program lines correspond to the original program. ; ; - All non-standard Z-80 Mnemonics have been changed to ; standard Z-80 Mnemonics. ; ; - There is an assembler warning for line 247 (LD D,E). ; This line still assembles to $53 (which it is supposed ; to). I'm not sure why Zmac is giving this error. ; ; - Checked, by hand, that this program assembles and ; matches, byte-for-byte with the listing by Jay Fenton. ; ; ***** End of Comments *****