home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / SIMTEL / CPMUG / CPMUG032.ARK / TBASICIO.ASM < prev    next >
Assembly Source File  |  1984-04-29  |  19KB  |  707 lines

  1. ;
  2. ; TARBELL CASSETTE BASIC I/O SYSTEM
  3. ; LAST CHANGED 8-23-78
  4. ;
  5. ; THIS INPUT/OUTPUT SOURCE USES CONDITIONAL
  6. ; ASSEMBLIES TO ACTIVATE DIFFERENT PARTS OF
  7. ; THE CODE FOR DIFFERENT PURPOSES.  NOTE THAT
  8. ; SEVERAL EQU'S BELOW ARE SET EITHER TO TRUE
  9. ; (-1) OR FALSE (0).  THESE VALUES ARE THEN
  10. ; USED WITH THE PSUEDO-OPS "IF" AND "ENDIF"
  11. ; TO INHIBIT THE ASSEMBLY OF SECTIONS OF CODE.
  12. ; THIS IS A FEATURE OF THE CP/M ASSEMBLER.
  13. ;
  14. TRUE    EQU  0FFFFH    ;FOR CONDITIONAL ASSEMBLIES.
  15. FALSE    EQU  NOT TRUE
  16. ;
  17. CPM    EQU  TRUE    ;TRUE FOR CP/M DISK SYSTEMS.
  18. DISK    EQU  TRUE    ;TRUE FOR DISK VERSION.
  19. STD    EQU  FALSE    ;TRUE FOR STANDARD CONSOLE.
  20.  
  21. ; PORTS FOR STANDARD I/O SYSTEM.
  22. CONSP    EQU  0        ;CONSOLE STATUS PORT.
  23. CONDP    EQU  1        ;CONSOLE DATA PORT.
  24. CONIM    EQU  01H    ;CONSOLE INPUT MASK.
  25. CONOM    EQU  80H    ;CONSOLE OUTPUT MASK.
  26. LSTSP    EQU  2        ;LISTER STATUS PORT.
  27. LSTDP    EQU  3        ;LISTER DATA PORT.
  28. LSTOM    EQU  080H    ;LISTER OUTPUT MASK.
  29.  
  30. ; PORTS FOR TARBELL CASSETTE I/O.
  31. CASC    EQU  6EH    ;CASSETTE STATUS PORT.
  32. CASD    EQU  6FH    ;CASSETTE DATA PORT.
  33.  
  34. ; CP/M BIOS JUMP VECTOR OFFSETS.
  35. CONST    EQU  3        ;CONSOLE STATUS OFFSET.
  36. CONIN    EQU  6        ;CONSOLE INPUT OFFSET.
  37. CONOT    EQU  9        ;CONSOLE OUTPUT OFFSET.
  38. LIST    EQU  12        ;LIST OUTPUT OFFSET.
  39.  
  40. ; CP/M COMMON LOCATIONS.
  41. BDOS    EQU  5        ;MAIN ENTRY POINT TO BDOS.
  42. FCB    EQU  5CH    ;DEFAULT FILE CONTROL BLOCK.
  43. TBUFF    EQU  80H    ;DEFAULT BUFFER LOCATION.
  44.  
  45. ; ENTRY POINTS INTO TARBELL BASIC INTERPRETER.
  46. BASIC    EQU  0500H    ;START OF TBASIC INTERPRETER.
  47. CHANL    EQU  BASIC+3    ;ADR OF ADR OF CHANNEL TABLE.
  48. TRMNL    EQU  BASIC+5    ;ADR OF ADR OF TERMINAL TABLE.
  49. SSSS    EQU  BASIC+7    ;ADR OF ADR OF END OF MEMORY.
  50. CNVRA    EQU  BASIC+9    ;ADR OF ADR OF NO. OF DIGITS.
  51. FPRA6    EQU  BASIC+11    ;ADR OF ADR OF USR ROUTINE.
  52. MODES    EQU  BASIC+13    ;ADR OF ADR OF MODES TABLE.
  53. FSRC    EQU  BASIC+15    ;ADR OF ADR OF START OF PROGRAM.
  54. ESRC    EQU  BASIC+17    ;ADR OF ADR OF END OF PROGRAM.
  55. ;
  56. ;
  57.     ORG  100H    ;NORMAL LOAD ADDRESS.
  58.     JMP  INIT    ;GO TO INITIALIZATION.
  59. CONI:    JMP  CONINP    ;CONSOLE INPUT ROUTINE.
  60. CONO:    JMP  CONOUT    ;CONSOLE OUTPUT ROUTINE.
  61. SPAR:    NOP!NOP!RET    ;FOR SPARE I/O ROUTINE.
  62. LSTO:    JMP  LSTOUT    ;LISTING OUTPUT ROUTINE.
  63. RDRI:    NOP!NOP!RET    ;FOR READER INPUT ROUTINE.
  64. PUNO:    NOP!NOP!RET    ;FOR PUNCH OUTPUT ROUTINE.
  65. DSKI:    JMP  DSKINP    ;DISK INPUT ROUTINE.
  66. DSKO:    JMP  DSKOUT    ;DISK OUTPUT ROUTINE.
  67. CASI:    JMP  CASINP    ;CASSETTE INPUT ROUTINE.
  68. CASO:    JMP  CASOUT    ;CASSETTE OUTPUT ROUTINE.
  69. USR:    JMP  USRSUB    ;HOP TO USER SUBROUTINE.
  70. ;
  71. INIT:
  72.  
  73.     IF NOT CPM    ;IF NOT CPM, LET BASIC
  74.     LXI  H,1    ;FIGURE END OF MEMORY.
  75.     ENDIF
  76.  
  77.     IF CPM AND NOT DISK    ;IF NOT DISK VERSION,
  78.     LHLD 1        ;GET START OF BIOS.
  79.     ENDIF
  80.  
  81.     IF CPM AND DISK    ;IF DISK VERSION,
  82.     XRA  A        ;SET DISK I/O FLAG = 0.
  83.     STA  DSKFLG
  84.     LHLD 6        ;GET START OF CP/M.
  85.     ENDIF
  86.  
  87.     DCX  H        ;DECREMENT BELOW IT.
  88.     XCHG        ;PUT IN D&E.
  89.     LHLD SSSS    ;SET TOP OF MEMORY.
  90.     MOV  M,E    ;PUT TOP ADR
  91.     INX  H        ;AT SSSS.
  92.     MOV  M,D
  93.     LHLD CNVRA    ;GET ADR OF NO. OF DIGITIS.
  94.     MVI  M,10    ;MAKE IT TEN.
  95.     LXI  H,USR    ;GET ADR OF USER SUBROUTINE.
  96.     XCHG        ;PUT INTO D&E.
  97.     LHLD FPRA6    ;GET LINKING ADDRESS.
  98.     MOV  M,E    ;PUT ADR OF USER ROUTINE
  99.     INX  H
  100.     MOV  M,D    ;AT FPRAA+6 IN BASIC.
  101.     LHLD CHANL    ;GET ADR OF CHANNEL TABLE.
  102.     LXI  D,JADR    ;GET ADR OF JMP ADR TABLE.
  103.     MVI  B,20    ;MOVE ADDRESS FROM THERE
  104.     CALL MOVE    ;TO BASIC'S CHANNEL TABLE.
  105.     LXI  D,IMODES    ;GET ADR OF INITIAL MODES.
  106.     LHLD MODES    ;GET ADR OF MODES TABLE.
  107.     MVI  B,10    ;BYTE COUNT = 10.
  108.     CALL MOVE    ;INITIALIZE THE MODES TABLE.
  109.     LHLD TRMNL    ;GET ADR OF TERMINAL TABLE.
  110.     INX H!INX H!INX H  ;H&L = H&L+3
  111.     MVI  M,72    ;SET CONSOLE TERM WIDTH.
  112.     INX H!INX H    ;H&L = H&L+2.
  113.     MVI  M,7FH    ;SET CONSOLE RUBOUT.
  114.     LXI  D,10    ;SET D&E = 10.
  115.     DAD  D        ;H&L = H&L+10.
  116.     MVI  M,72    ;SET LISTING WIDTH.
  117.     INX  H        ;GET LIST LOC #2.
  118.     MVI  M,0    ;PUT ZERO IN IT.
  119.     INX  H        ;GET LIST LOC #3.
  120.     MVI  M,0BH    ;PUT 0B INTO IT.
  121.     JMP  BASIC    ;HOP INTO TARBELL BASIC.
  122. ;
  123. ; JADR - I/O JUMP ADDRESS TABLE, GETS MOVED
  124. ; INTO BASIC'S CHANNEL TABLE AT INITIALIZATION.
  125. ;
  126. JADR:    DW   CONI    ;CONSOLE INPUT ADDRESS.
  127.     DW   CONO    ;CONSOLE OUTPUT ADDRESS.
  128.     DW   CASI    ;CASSETTE INPUT ADDRESS.
  129.     DW   CASO    ;CASSETTE OUTPUT ADDRESS.
  130.     DW   SPAR    ;SPARE I/O ADDRESS.
  131.     DW   LSTO    ;LISTING OUTPUT ADDRESS.
  132.     DW   RDRI    ;READER INPUT ADDRESS.
  133.     DW   PUNO    ;PUNCH OUTPUT ADDRESS.
  134.     DW   DSKI    ;DISK INPUT ADDRESS.
  135.     DW   DSKO    ;DISK OUTPUT ADDRESS.
  136. ;
  137. ; MOVE - MOVE THE NUMBER OF BYTES SPECIFIED BY
  138. ; REGISTER B, FROM THE ADDRESS IN D&E TO THE
  139. ; ADDRESS IN H&L.
  140. ;
  141. MOVE:    LDAX D        ;GET A BYTE.
  142.     MOV  M,A    ;PUT A BYTE.
  143.     INX  H        ;INCREMENT H&L.
  144.     INX  D        ;INCREMENT D&E.
  145.     DCR  B        ;DECREMENT COUNTER.
  146.     JNZ  MOVE    ;GO TILL COUNTER=0.
  147.     RET        ;RETURN FROM MOVE.
  148. ;
  149. ; IMODES - INITIAL MODES TABLE FOR I/O DEVICES.
  150. ; THIS GETS TRANSFERRED FROM HERE TO BASIC'S 
  151. ; MODES TABLE UPON INITIALIZATION.  AFTER THAT,
  152. ; BASIC'S MODES TABLE MAY BE CHANGED FROM A
  153. ; RUNNING BASIC PROGRAM BY USING THE ASSIGN
  154. ; AND DROP STATEMENTS TO SET & RESET BITS.
  155. ;
  156.  
  157. ;LOG. DEV. # 76543210    ;PHYSICAL DEVICE.
  158.  
  159. IMODES:    DB   00000001B    ;KEYBOARD INPUT.
  160.     DB   00000010B    ;CONSOLE PRINTER.
  161.  
  162.     IF NOT DISK    ;IF NOT DISK VERSION.
  163.     DB   00010100B    ;CASSETTE INPUT.
  164.     DB   00101000B    ;CASSETTE OUTPUT.
  165.     ENDIF
  166.  
  167.     IF   DISK    ;IF DISK VERSION,
  168.     DB   00000000B    ;CASSETTE INPUT.
  169.     DB   00000000B    ;CASSETTE OUTPUT.
  170.     ENDIF
  171.  
  172.     DB   00000000B    ;SPARE INPUT/OUTPUT.
  173.     DB   00000000B    ;LISTING OUTPUT.
  174.     DB   00000000B  ;READER INPUT.
  175.     DB   00000000B    ;PUNCH OUTPUT.
  176.  
  177.     IF   DISK    ;IF DISK VERSION,
  178.     DB   00010100B    ;DISK INPUT.
  179.     DB   00101000B    ;DISK OUTPUT.
  180.     ENDIF
  181.  
  182.     IF NOT DISK    ;IF NOT DISK VERSION,
  183.     DB   00000000B    ;DISK INPUT.
  184.     DB   00000000B    ;DISK OUTPUT.
  185.     ENDIF
  186.  
  187. ;
  188. ; CONOUT - PRINT THE CHARACTER IN REGISTER A
  189. ; ONTO THE CONSOLE OUTPUT DEVICE, USUALLY A
  190. ; TELETYPEWRITER OR CRT TERMINAL.  IF THE
  191. ; CHARACTER IS A CARRIAGE-RETURN, ADD A 
  192. ; LINE-FEED.  IF THE CHARACTER IS A RUBOUT,
  193. ; ECHO A BACKSPACE.
  194. ;
  195. CONOUT:    PUSH H        ;SAVE H&L.
  196.     PUSH D        ;SAVE D&E.
  197.     PUSH B        ;SAVE B&C.
  198.     PUSH PSW    ;SAVE A&PSW.
  199.     CPI  7FH    ;IS IT RUBOUT?
  200.     JNZ  ECHO    ;IF NOT, ECHO.
  201.     MVI  A,08H    ;IF SO, GET BACKSPACE.
  202.  
  203.     IF   CPM    ;IF CP/M I/O,
  204.     CALL IO        ;PRINT CHARACTER IN A.
  205.     DB   CONOT
  206.     MVI  A,20H    ;PRINT SPACE.
  207.     CALL IO
  208.     DB   CONOT
  209.     MVI  A,08H    ;PRINT BACKSPACE.
  210. ECHO:    CALL IO
  211.     DB   CONOT
  212.     ENDIF
  213.  
  214.     IF   STD    ;IF STANDARD I/O,
  215.     CALL CONOTS    ;PRINT CHARACTER IN A.
  216.     MVI  A,20H    ;PRINT SPACE.
  217.     CALL CONOTS
  218.     MVI  A,08H    ;PRINT BACKSPACE AGAIN.
  219. ECHO:    CALL CONOTS
  220.     ENDIF
  221.  
  222.     POP  PSW    ;RESTORE A&PSW.
  223.     POP  B        ;RESTORE B&C.
  224.     POP  D        ;RESTORE D&E.
  225.     POP  H        ;RESTORE H&L.
  226.     RET        ;RETURN FROM CONOUT.
  227.  
  228.     IF   STD    ;IF STANDARD I/O,
  229. CONOTS:    PUSH PSW    ;SAVE REGISTER A & STATUS.
  230. CONOTL:    IN   CONSP    ;READ CONSOLE STATUS.
  231.     ANI  CONOM    ;LOOK AT OUTPUT STATUS BIT.
  232.     JNZ  CONOTL    ;WAIT UNTIL READY.
  233.     POP  PSW    ;GET CHARACTER.
  234.     OUT  CONDP    ;PRINT IT.
  235.     RET        ;RETURN FROM CONOT.
  236.     ENDIF
  237.  
  238. ;
  239. ; CONINP - READ A BYTE FROM THE CONSOLE KEYBOARD INTO
  240. ; REGISTER A.  IF THIS ROUTINE IS ENTERED WITH THE
  241. ; 8080 ZERO FLAG SET, IT IS A CHECK FOR CONTROL-C.
  242. ; IN THIS CASE, A CHECK IS MADE TO SEE IF A CONTROL-C
  243. ; KEY HAS BEEN PUSHED.  IF IT HASN'T, A RETURN IS
  244. ; MADE WITH THE ZERO FLAG CLEARED.  IF IT HAS, A
  245. ; RETURN IS MADE WITH THE ZERO FLAG SET.
  246. ;
  247. CONINP:    JZ   CHKST    ;IF ZERO, MUST BE STATUS CHECK.
  248.  
  249.     IF   CPM    ;IF CP/M I/O,
  250.     CALL IO        ;READ KEYBOARD.
  251.     DB   CONIN
  252.     ENDIF
  253.  
  254.     IF   STD    ;IF STANDARD I/O,
  255.     CALL CONINS    ;READ KEYBOARD.
  256.     ENDIF
  257.  
  258.     RET        ;RETURN FROM CONINP.
  259. CHKST:    PUSH H        ;SAVE H&L.
  260.     PUSH D        ;SAVE D&E.
  261.     PUSH B        ;SAVE B&C.
  262.  
  263.     IF   CPM    ;IF CP/M I/O,
  264.     CALL IO        ;CHECK KEYBOARD STATUS.
  265.     DB   CONST
  266.     ENDIF
  267.  
  268.     IF   STD    ;IF STANDARD I/O,
  269.     CALL CHKSTS    ;CHECK KEYBOARD STATUS.
  270.     ENDIF
  271.  
  272.     POP  B        ;RESTORE B&C.
  273.     POP  D        ;RESTORE D&E.
  274.     POP  H        ;RESTORE H&L.
  275.     CMA        ;COMPLEMENT RESULT.
  276.     ORA  A        ;SET FLAGS.
  277.     RNZ        ;RETURN IF NO KEY PUSH.
  278. CHKST1:
  279.     IF   CPM    ;IF CP/M I/O,
  280.     CALL IO        ;READ KEYBOARD.
  281.     DB   CONIN
  282.     ENDIF
  283.  
  284.     IF   STD    ;IF STANDARD I/O,
  285.     CALL CONINS    ;READ KEYBOARD.
  286.     ENDIF
  287.  
  288.     CPI  3        ;SET ZERO FLAG IF CTL-C.
  289.     RZ        ;RETURN IF CTL-C.
  290.     CPI  13H    ;IS IT A CTL-S?
  291.     JZ   CHKST1    ;IF SO, READ KB AGAIN.
  292.     RET        ;RETURN FROM CONINP.
  293.  
  294.     IF   STD    ;IF STANDARD I/O,
  295. ;
  296. ; CONINS - STANDARD READ FROM KEYBOARD.
  297. ;
  298. CONINS:    IN   CONSP    ;READ CONSOLE STATUS.
  299.     ANI  CONIM    ;LOOK AT INPUT STATUS BIT.
  300.     JNZ  CONINS    ;LOOP UNTIL READY.
  301.     IN   CONDP    ;READ THE CHARCTER.
  302.     ANI  7FH    ;STRIP PARITY BIT OFF.
  303.     RET        ;RETURN FROM CONINS.
  304. ;
  305. ; CHKSTS - STANDARD CONSOLE STATUS ROUTINE.
  306. ;
  307. CHKSTS:    IN   CONSP    ;READ CONSOLE STATUS.
  308.     ANI  CONIM    ;LOOK AT KB READY BIT.
  309.     MVI  A,0    ;SET A=0 FOR RETURN.
  310.     RNZ        ;NOT READY WHEN NOT ZERO.
  311.     CMA        ;IF READY, A=FF.
  312.     RET        ;RETURN FROM CHKSTS.
  313.     ENDIF
  314.  
  315.     IF   CPM    ;IF CP/M INPUT/OUTPUT,
  316. ;
  317. ; IO - PERFORM AN INPUT OR OUTPUT OPERATION USING
  318. ; CP/M'S BIOS (BASIC INPUT/OUTPUT SYSTEM).  THE
  319. ; BYTE FOLLOWING THE CALL TO THIS ROUTINE IS AN
  320. ; OFFSET WHICH IS ADDED TO THE BIOS JUMP VECTOR
  321. ; ADDRESS TO DETERMINE THE CORRECT ENTRY POINT
  322. ; TO BIOS.
  323. ;
  324. IO:    XTHL        ;GET ADDRESS OF OFFSET.
  325.     MOV  E,M    ;PUT OFFSET IN D&E.
  326.     MVI  D,0
  327.     INX  H        ;MAKE RETURN ADDRESS RIGHT.
  328.     XTHL        ;PUT BACK ONTO STACK.
  329.     LHLD 1        ;GET ADDRESS OF IO VECTOR.
  330.     DAD  D        ;ADD OFFSET.
  331.     MOV  C,A    ;OUTPUT GOES IN C.
  332.     PCHL        ;JUMP TO IO ROUTINE.
  333.     ENDIF
  334.  
  335. ;
  336. ; LSTOUT - PRINT THE CHARACTER IN REGISTER A ON THE
  337. ; LISTING DEVICE.  IF IT'S A CARRIAGE-RETURN, ADD
  338. ; A LINE-FEED.
  339. ;
  340. LSTOUT:    PUSH PSW    ;SAVE REG A AND PSW.
  341.     PUSH B        ;SAVE B&C.
  342.  
  343.     IF   CPM    ;IF CP/M I/O,
  344.     CALL IO        ;PRINT CHARACTER.
  345.     DB   LIST
  346.     ENDIF
  347.  
  348.     IF   STD    ;IF STANDARD I/O,
  349.     CALL LSTOUS    ;PRINT CHARACTER.
  350.     ENDIF
  351.  
  352.     POP  B        ;RESTORE B&C.
  353.     POP  PSW    ;RESTORE REG A AND PSW.
  354.     RET        ;RETURN FROM LSTOUT.
  355.  
  356.     IF   STD    ;IF STANDARD I/O,
  357. ;
  358. ; LSTOUS - STANDARD LISTING DEVICE ROUTINE.
  359. ;
  360. LSTOUS:    PUSH PSW    ;SAVE CHARACTER.
  361. LSTOUL:    IN   LSTSP    ;READ STATUS.
  362.     ANI  LSTOM    ;LOOK AT STATUS BIT.
  363.     JNZ  LSTOUL    ;WAIT TILL READY.
  364.     POP  PSW    ;GET CHARACTER BACK.
  365.     PUSH PSW    ;BACK AGAIN.
  366.     CPI  7FH    ;IS IT BACKSPACE?
  367.     JNZ  LSTECH    ;HOP IF NOT.
  368.     MVI  A,'\'    ;PRINT BACKSLASH INSTEAD.
  369. LSTECH:    OUT  LSTDP    ;PRINT CHARACTER.
  370.     POP  PSW    ;RECOVER ORIG. CHAR.
  371.     RET        ;RETURN FROM LSTOUS.
  372.     ENDIF
  373.  
  374. ;
  375. ; CASINP - READ A BYTE FROM CASSETTE RECORDER.
  376. ; BYTE RETURNS IN REGISTER A.  IF THE CARRY
  377. ; FLAG IS SET UPON RETURN FROM THIS ROUTINE,
  378. ; A TAPE READ ERROR HAS OCCURED.
  379. ;
  380. CASINP:    RZ        ;RETURN IF EITHER FLAG SET.
  381.     JNC  CASINC    ;IF CARRY,
  382.     ORA  A        ;CLEAR IT AND QUIT.
  383.     RET
  384. CASINC:    PUSH H        ;SAVE H&L.
  385.     PUSH D        ;SAVE D&E.
  386.     PUSH B        ;SAVE B&C.
  387.     LDA  CASIB    ;GET BYTE COUNT.
  388.     ORA  A        ;IF IT'S NOT ZERO,
  389.     JNZ  CASIM    ;MOVE BYTE FROM BUFFER.
  390.     CALL CTRD    ;READ FROM CASSETTE.
  391. CASIR:    JZ   CASINE    ;NO ERROR IF ZERO SET.
  392.     STC        ;OTHERWISE, SET CARRY,
  393.     JMP  CASIRT    ;RETURN WITH ERROR.
  394. CASINE:    MOV  A,B    ;GET BYTE COUNT.
  395.     LXI  H,IBUF    ;INITIALIZE BUFFER POINTER.
  396.     SHLD CASIHL
  397. CASIM:    LHLD CASIHL    ;LOAD BUFFER POINTER.
  398. CASIL1:    MOV  C,M    ;GET BYTE FROM BUFFER.
  399.     INX  H        ;INCREMENT POINTER.
  400.     SHLD CASIHL    ;SAVE THE POINTER.
  401.     DCR  A        ;DECREMENT BYTE COUNT.
  402.     STA  CASIB    ;SAVE IT.
  403.     MOV  A,C    ;GET DATA BYTE.
  404.     ORA  A        ;CLEAR CARRY.
  405. CASIRT:    POP  B        ;RESTORE B&C.
  406.     POP  D        ;RESTORE D&E.
  407.     POP  H        ;RESTORE H&L.
  408.     RET
  409. ;
  410. ; CASOUT - OUTPUT ONE BYTE TO CASSETTE RECORDER.
  411. ; ON ENTRY, IF REG A=1, INITIALIZE.
  412. ;     IF CARRY SET, END OF TRANSFER.
  413. ;    DATA BYTE IS IN REGISTER A.
  414. ;
  415. CASOUT:    PUSH H        ;SAVE ALL REGISTERS.
  416.     PUSH D
  417.     PUSH B
  418.     PUSH PSW
  419.     JZ   CASOST    ;IF Z=1, MUST BE START.
  420. CASONS:    LHLD CASOHL    ;GET BUFFER POINTER.
  421.     LDA  CASOB    ;GET BYTE COUNT.
  422.     MOV  B,A    ;PUT INTO REG B.
  423.     POP  PSW    ;RESTORE REG A AND PSW.
  424.     PUSH PSW    ;SAVE IT BACK.
  425.     JC   CASOEN    ;IF CARRY, MUST BE END.
  426. CASOL1:    MOV  M,A    ;PUT BYTE INTO BUFFER.
  427.     INX  H        ;INCREMENT POINTER.
  428.     SHLD CASOHL    ;SAVE THE POINTER.
  429.     INR  B        ;INCREMENT BYTE COUNT.
  430.     MOV  A,B    ;SAVE NEW BYTE COUNT.
  431.     STA  CASOB
  432.     CPI  128    ;128 BYTES YET?
  433.     JNZ  REGRES    ;RETURN IF NOT.
  434. CASOEN:    MOV  A,B    ;GET BYTE COUNT.
  435.     ORA  A        ;IF IT'S ZERO,
  436.     JZ   REGRES    ;RETURN.
  437.     LXI  H,OBUF    ;GET ADDRESS OF BUFFER.
  438.     CALL CTWT    ;IF SO, WRITE BUFFER.
  439. CASOST:    LXI  H,OBUF    ;GET ADDRESS OF OUTPUT BUFFER.
  440.     SHLD CASOHL    ;INITIALIZE POINTER WITH IT.
  441.     XRA  A        ;SET BYTE COUNT=0.
  442.     STA  CASOB
  443. REGRES:    POP  PSW    ;RESTORE PSW&A.
  444.     POP  B        ;RESTORE B&C.
  445.     POP  D        ;RESTORE D&E.
  446.     POP  H        ;RESTORE H&L.
  447.     RET        ;RETURN FROM REGRES.
  448. ;
  449. ; DSKINP - READ A BYTE FROM THE CURRENT DISK FILE.
  450. ; BYTE RETURNS IN REGISTER A.  IF THE CARRY FLAG
  451. ; IS SET UPON RETURN FROM THIS ROUTINE, A DISK
  452. ; READ ERROR HAS OCCURED.
  453. ;
  454. DSKINP:
  455.     IF   DISK    ;IF DISK VERSION,
  456.     RZ        ;RETURN IF EITHER FLAG SET.
  457.     JNC DSKINC    ;IF CARRY,
  458.     ORA  A        ;CLEAR IT AND QUIT.
  459.     RET
  460. DSKINC:    PUSH H        ;SAVE H&L.
  461.     PUSH D        ;SAVE D&E.
  462.     PUSH B        ;SAVE B&C.
  463.     LXI  H,DSKFLG    ;GET ADR OF DISK FLAG.
  464.     XRA  A        ;SET A = ZERO.
  465.     CMP  M        ;IS DISK FLAG = 0?
  466.     JNZ  DSKIRB    ;HOP AROUND READ IF NOT.
  467.     MVI  M,0FFH    ; SET DISK FLAG = READ MODE.
  468.     CALL DSKRD    ;READ FIRST BLOCK FROM DISK.
  469.     JC   CASIRT    ;RETURN IF CARRY (ERROR).
  470. DSKIRB:    LHLD DSKHL    ;GET BUFFER POINTER.
  471.     MOV  A,M    ;GET BYTE FROM BUFFER.
  472.     INX  H        ;INCREMENT POINTER.
  473.     SHLD DSKHL    ;SAVE IT.
  474.     LXI  H,DSKCTR    ;GET ADR OF BYTE COUNT.
  475.     ORA  A        ;CLEAR CARRY FLAG!!!!
  476.     INR  M        ;INCREMENT IT.
  477.     JP   CASIRT    ;RETURN IF NOT 128 YET.
  478.     PUSH A        ;SAVE DATA BYTE ON STACK.
  479.     CALL DSKRD    ;READ FROM DISK.
  480.     POP  B        ;GET DATA BYTE BACK FROM
  481.     MOV  A,B    ;STACK WITHOUT CHANGING PSW.
  482.     JMP  CASIRT    ;RESTORE REGISTERS & RETURN.
  483.     ENDIF
  484.  
  485. ;
  486. ; DSKOUT - OUTPUT ONE BYTE TO CURRENT DISK FILE.
  487. ; ON ENTRY, IF REG A=1, INITIALIZE.
  488. ;    IF CARRY SET, END OF TRANSFER.
  489. ;    DATA BYTE IS IN REGISTER A.
  490. ;
  491. DSKOUT:
  492.     IF   DISK    ;IF DISK VERSION,
  493.     RZ        ;RETURN IF START FLAG.
  494.     RC        ;RETURN IF END FLAG.
  495.     PUSH H        ;SAVE ALL REGISTERS.
  496.     PUSH D
  497.     PUSH B
  498.     PUSH PSW
  499. DSKPUT:    LHLD DSKHL    ;GET BUFFER POINTER.
  500.     MOV  M,A    ;PUT BYTE INTO BUFFER.
  501.     INX  H        ;INCREMENT POINTER.
  502.     SHLD DSKHL    ;UPDATE POINTER.
  503.     MVI  A,1    ;SET DISK WRITE MODE.
  504.     STA  DSKFLG
  505.     LXI  H,DSKCTR    ;GET ADR OF BYTE COUNT.
  506.     INR  M        ;INCREMENT BYTE COUNT.
  507.     CM   DSKWT    ;IF 128, WRITE TO DISK.
  508.     JMP  REGRES    ;RESTORE & RETURN.
  509.     ENDIF
  510.  
  511.  
  512.     IF   DISK    ;IF DISK VERSION,
  513. ;
  514. ; USRSUB - THIS IS THE SUBROUTINE THAT GETS
  515. ; CALLED BY THE USR FUNCTION IN TARBELL BASIC.
  516. ; THE ARGUMENT OF THE FUNCTION COMES IN D&E.
  517. ; IF D&E = ZERO, IT MEANS TO CLOSE A FILE.
  518. ; IF D&E = ONE, IT MEANS TO OPEN CURRENT FILE.
  519. ; IF D&E FROM 128 TO 255, GOTO ZERO.
  520. ; IF D&E => 256, D&E CONTAINS THE ADDRESS OF A
  521. ; STRING WHICH IS THE NAME OF THE FILE TO OPEN.
  522. ;
  523. USRSUB:    MOV  A,D    ;CHECK TO SEE IF
  524.     ORA  A        ;IS D=0?
  525.     JNZ  USRS2    ;IF NOT, MUST BE NAME.
  526.     MOV  A,E    ;IS E=0 TOO?
  527.     ORA  A        ;IF SO,
  528.     JZ   DSKCL    ;JUST CLOSE FILE.
  529.     JM   0        ;IF MSB = 1 GOTOT 0.
  530.     DCR  A        ;IF E WAS 1,
  531.     JZ   DSKOP    ;OPEN WITH PRESENT NAME.
  532. USRS2:    PUSH D        ;SAVE D&E.
  533.     LXI  D,BFCB    ;GET ADR OF BLANK FCB.
  534.     LXI  H,FCB    ;GET ADR OF FCB.
  535.     MVI  B,16    ;GET LENGTH OF AREA.
  536.     CALL MOVE    ;SET FCB TO BLANK.
  537.     POP  D        ;RESTORE D&E.
  538.     LXI  H,FCB+1    ;GET ADR OF FCB+1.
  539.     MVI  C,11    ;MAXIMUM OF 11 CHARS.
  540. USRS1:    LDAX D        ;GET CHAR FROM STRING.
  541.     ANI  7FH    ;CLEAR MSB.
  542.     MOV  M,A    ;PUT INTO FCB.
  543.     INX  H        ;INCREMENT POINTERS.
  544.     LDAX D        ;GET CHAR AGAIN.
  545.     INX  D        ;INCREMENT D&E.
  546.     DCR  C        ;DECREMENT COUNTER.
  547.     JZ   DSKOP    ;IF 11 CHARS, OPEN.
  548.     ORA  A        ;IS MSB SET?
  549.     JP   USRS1    ;IF NOT MSB, GET ANOTHER.
  550. ;
  551. ; DSKOP - OPEN THE DISK FILE WHOSE NAME IS IN
  552. ; THE DEFAULT FILE CONTROL BLOCK.
  553. ;
  554. DSKOP:    LDA  DSKFLG    ;GET DISK MODE FLAG.
  555.     ORA  A        ;WAS FILE OPEN?
  556.     CNZ  DSKCL    ;CLOSE IF FILE OPEN.
  557.     CALL DSKRS    ;RESET DISK PTR & CTR.
  558.     MVI  C,15    ;OPEN FILE.
  559.     LXI  D,FCB    ;DEFAULT FCB ADR.
  560.     CALL BDOS    ;DO IT.
  561.     INR  A        ;WAS FILE FOUND?
  562.     MVI  A,0        ;SET NR = 0.
  563.     STA  FCB+32
  564.     RNZ        ;RETURN IF FILE FOUND.
  565.     MVI  C,22    ;OTHERWISE MAKE FILE.
  566.     LXI  D,FCB    ;FILE CTL BLOCK ADR.
  567.     CALL BDOS    ;DO IT.
  568.     MVI  D,0    ;PUT A INTO D&E.
  569.     MOV  E,A
  570.     INR  A        ;WAS THERE ROOM?
  571.     JNZ  DSKOP    ;OPEN IF SO.
  572.     RET        ;RETURN IF NOT.
  573. ;
  574. ; BFCB - BLANK FILE CONTROL BLOCK.
  575. ;
  576. BFCB:    DB   0,'           ',0,0,0,0
  577. ;
  578. ; DSKCL - CLOSE THE DISK FILE WHOSE NAME IS IN
  579. ; THE DEFAULT FILE CONTROL BLOCK.
  580. ;
  581. DSKCL:    LDA  DSKFLG    ;GET DISK FLAG.
  582.     INR  A        ;IF IT WAS = FF,
  583.     JZ   DSKCLR    ;MUST HAVE BEEN READING.
  584.     LHLD DSKHL    ;GET DISK BUFFER PTR.
  585.     MVI  M,1AH    ;PUT IN END-OF-FILE.
  586.     CALL DSKWT    ;WRITE LAST RECORD.
  587.     XRA  A        ;SET DISK MODE INACTIVE.
  588. DSKCLR:    STA  DSKFLG
  589.     MVI  C,16    ;CLOSE FILE CODE.
  590.     LXI  D,FCB    ;DEFAULT FCB ADR.
  591.     CALL BDOS    ;CLOSE IT.
  592.     RET
  593. ;
  594. ; DSKRD - READ A SECTOR FROM THE CURRENT DISK
  595. ; FILE INTO MEMORY AT ADDRESS 0080H.
  596. ;
  597. DSKRD:    CALL DSKRS    ;RESET POINTER & COUNTER.
  598.     MVI  C,20    ;READ NEXT RECORD.
  599.     LXI  D,FCB    ;GET ADR OF FCB.
  600.     CALL BDOS
  601.     ORA  A        ;SET FLAGS.
  602.     RZ         ;RETURN IF NO ERRORS.
  603.     STC        ;SET CARRY IF ERROR.
  604.     RET        ;RETURN FROM DSKRD.
  605. ;
  606. ; DSKWT - WRITE A SECTOR FROM THE BUFFER AT
  607. ; ADDRESS 0080H TO THE CURRENT DISK FILE.
  608. ; ALSO RESET DISK BUFFER POINTER & COUNTER.
  609. ;
  610. DSKWT:    MVI  C,21    ;WRITE NEXT RECORD.
  611.     LXI  D,FCB    ;GET ADR OF FCB.
  612.     CALL BDOS
  613. DSKRS:    LXI  H,TBUFF    ;GET DISK BUFFER ADR.
  614.     SHLD DSKHL    ;INITIALIZE POINTER.
  615.     XRA  A        ;SET BYTE COUNT = 0.
  616.     STA  DSKCTR
  617.     RET
  618.     ENDIF
  619.  
  620.     IF NOT DISK    ;IF NOT DISK VERSION,
  621. USRSUB:    JMP  0        ;JUST HOP TO ZERO.
  622.     ENDIF
  623.  
  624. ;
  625. ; CTWT - WRITE A BLOCK TO CASSETTE.
  626. ;
  627. CTWT:    LXI  D,187*2    ;GET COUNT FOR 2 SECONDS.
  628. DELAY:    MVI  A,3CH    ;WRITE START BYTE.
  629.     CALL CASW
  630.     DCX  D        ;DECREMENT COUNT.
  631.     MOV  A,D    ;IF D&E ARE
  632.     ORA  E        ;NOT YET ZERO,
  633.     JNZ  DELAY    ;KEEP COUNTING DOWN.
  634.     MVI  A,0E6H    ;WRITE SYNC BYTE.
  635.     CALL CASW
  636.     MVI  C,0    ;CLEAR CHECKSUM.
  637.     MVI  A,90H    ;WRITE TYPE BYTE.
  638.     CALL CASW
  639.     MOV  A,B    ;WRITE LENGTH BYTE.
  640.     CALL CASW
  641.     MOV  A,B    ;GET LENGTH BYTE.
  642.     ORA  A        ;IF IT'S ZERO,
  643.     RZ        ;RETURN FROM CTWT.
  644. CTLP:    MOV  A,M    ;WRITE DATA BYTE.
  645.     CALL CASW
  646.     INX  H        ;INCREMENT POINTER.
  647.     DCR  B        ;DECREMENT COUNTER.
  648.     JNZ  CTLP    ;REPEAT.
  649.     MOV  A,C    ;WRITE CHECKSUM.
  650. CASW:    PUSH PSW    ;SAVE DATA ON STACK.
  651. CALP:    IN   CASC    ;READ CASSETTE STATUS.
  652.     ANI  20H    ;LOOK AT BIT 5.
  653.     JNZ  CALP    ;WAIT UNTIL READY.
  654.     POP  PSW    ;RECOVER DATA.
  655.     OUT  CASD    ;WRITE A BYTE.
  656.     ADD  C        ;ADD TO CHECKSUM.
  657.     MOV  C,A
  658.     RET        ;RETURN FROM CASW.
  659. ;
  660. ; CTRD - READ A RECORD FROM CASSETTE.
  661. ;
  662. CTRD:    LXI  H,IBUF    ;GET BUFFER ADDRESS.
  663.     CALL CASW    ;DELAY TO ALLOW LAST
  664.     CALL CASW    ;BYTE TO PASS THROUGH.
  665.     MVI  E,0    ;SET CHECKSUM=0.
  666.     MVI  A,10H    ;SET BIT 4=1.
  667.     OUT  CASC    ;RESET RECEIVER.
  668.     CALL CASR    ;READ TYPE BYTE.
  669.     CALL CASR    ;READ LENGTH BYTE.
  670.     MOV  B,A    ;PUT LENGTH BYTE IN B.
  671.     RZ        ;RETURN IF LENGTH 0.
  672.     MOV  C,A    ;PUT LENGTH IN C TOO.
  673. CRLOP:    CALL CASR    ;READ DATA BYTE.
  674.     MOV  M,A    ;PUT INTO MEMORY.
  675.     INX  H        ;INCREMENT POINTER.
  676.     DCR  C        ;DECREMENT COUNTER.
  677.     JNZ  CRLOP    ;READ ANOTHER BYTE.
  678.     MOV  C,E    ;PUT CHECKSUM IN C.
  679.     CALL CASR    ;READ CHECKSUM.
  680.     SUB  C        ;SUBTRACT FROM A.
  681.     RET        ;RETURN FROM CRLOP.
  682. ;
  683. CASR:    IN   CASC    ;READ CASS. STATUS.
  684.     ANI  10H    ;CHECK BIT 4.
  685.     JNZ  CASR    ;WAIT TILL READY.
  686.     IN   CASD    ;READ DATA.
  687.     PUSH PSW    ;SAVE REG A.
  688.     ADD  E        ;ADD TO CHECKSUM.
  689.     MOV  E,A
  690.     POP  PSW    ;RESTORE A.
  691.     ORA  A        ;SET FLAGS.
  692.     RET        ;RETURN FROM CASR.
  693. ;
  694. ;
  695. ; THIS PART SHOULD BE IN RAM.
  696. ;
  697. DSKFLG:    DS   1        ;0=NONE, 1=WRITE, FF=READ.
  698. DSKHL:    DS   2        ;DISK BUFFER POINTER.
  699. DSKCTR:    DB   0        ;DISK BYTE COUNTER.
  700. CASOHL:    DS   2        ;OUTPUT BUFFER POINTER.
  701. CASOB:    DB   0        ;CASS. OUTPUT BYTE COUNT.
  702. OBUF:    DS   128    ;CASS. OUTPUT BUFFER.
  703. CASIHL:    DS   2        ;INPUT BUFFER POINTER.
  704. CASIB:    DB   0        ;INPUT BYTE COUNT.
  705. IBUF:    DS   128    ;INPUT BUFFER.
  706.     END
  707.