home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / mbug / mbug097.arc / B512T.Z < prev    next >
Text File  |  1979-12-31  |  68KB  |  3,406 lines

  1. ;    *********************************************************
  2. ;    *                            *
  3. ;    *    =========================================    *
  4. ;    *       --- MicroBee Enhanced DRAM BIOS ---        *
  5. ;    *                            *
  6. ;    *      Bios for 128k, 256k & 512k MicroBees.        *
  7. ;    *          (c) 1986 by Peter Broughton.        *
  8. ;    *    =========================================    *
  9. ;    *                            *
  10. ;    *    Derived from 128k BIOS ( ver. 6 )        *
  11. ;    *    (c) Matthew Starr for MicroBee Systems.        *
  12. ;    *                            *
  13. ;    *    Features :                    *
  14. ;    *     Compatable with 128k BIOS version 7,        *
  15. ;    *     32k - 416k Memory drives (M: & N:),        *
  16. ;    *     32k - 128k Disk Cache,                *
  17. ;    *     Preselectable disk types,            *
  18. ;    *     12 128 byte function keys,            *
  19. ;    *     Storage of BDOS, CCP, SHELL in backplane,    *
  20. ;    *     User selectable keyboard driver in backplane,    *
  21. ;    *     System configuration window in backplane.    *
  22. ;    *     Etc., etc...                    *
  23. ;    *                            *
  24. ;    *********************************************************
  25. ;
  26. ;
  27. ;
  28. ;
  29. ;    Structure of code :
  30. ;    1.    Customisation file ( include CUSTOM.OPT ).
  31. ;          - also include standard file CPMCALLS.MAC.
  32. ;    2.    Boot sector ( 512 bytes, max 128 used ).
  33. ;    3.    BDOS ( include BDOS.MAC ).
  34. ;    4.    Visible BIOS ( < F000h ),
  35. ;          - tables, boot, serial, links to later code etc.
  36. ;    ***    From this point code is hidden by screen RAM.
  37. ;    5.    Initial handling of some standard calls,
  38. ;          ( including disk IO ), disk select routine,
  39. ;          RAM disk routines.
  40. ;    6.    Console IO ( include CON512.MAC ),
  41. ;          - screen, keyboard link, serial, parallel IO.
  42. ;    7.    Disk cache ( include DB512.MAC ),
  43. ;          - all disk cache routines
  44. ;    8.    Disk IO ( include FL512.MAC ),
  45. ;          - low level disk IO.
  46. ;    9.    Data storage etc. etc. to end of RAM.
  47. ;    10.    Routines that are moved to address 0 in system page.
  48. ;
  49. ;
  50. ; PJB's nth law of programming:
  51. ;  The number of bugs that will appear when completing a program
  52. ; is inversly proportional to the time you have told people it
  53. ; will take to complete.
  54. ; For an example of this see below:
  55.  
  56.  
  57.     ASEG
  58.     .Z80
  59.     TITLE Microbee 512k CP/M 2.2, Enhanced BIOS.
  60.  
  61.  
  62. ; Approx date of last modification, version num. to indicate
  63. ; released versions only.
  64. version    macro
  65.      db    '2.2'
  66.     endm
  67.  
  68. date    macro
  69.      db    '17th May, 1988'
  70.     endm
  71.  
  72.  
  73. true        equ    -1
  74. false        equ    not true
  75.  
  76. ;    Include file containing customisation options.
  77.     include    CUSTOMT.OPT
  78.  
  79. test_code    equ    false    ; useful for testing (if code in place)
  80.  
  81. name_protect    equ    true
  82.  
  83. scramble    equ    false
  84.  
  85. out_50h        equ    50D3h
  86.  
  87.  
  88.  
  89. ; write value to map port
  90. map    macro    value
  91.      ld    a,value
  92.      out    (map_port),a
  93.     endm
  94.  
  95. ; screen flag testing code
  96. sflag    macro    sc_offs,char,oldmap
  97.     if    test_code
  98.      map    sys_vdr
  99.      ld    a,char
  100.      ld    (8000h+sc_offs),a
  101.      map    oldmap
  102.     endif
  103.     endm
  104.  
  105. psflag    macro    sc_offs,char,oldmap
  106.     if    test_code
  107.      push    af
  108.      map    sys_vdr
  109.      ld    a,char
  110.      ld    (8000h+sc_offs),a
  111.      map    oldmap
  112.      pop    af
  113.     endif
  114.     endm
  115.  
  116.  
  117. ; Disk types ...
  118.  
  119. ds40    macro
  120. ; double sided, 40 track, 386k, Microbee standard 5.25"
  121.     db    xltd-xlt_base
  122.     db    1
  123.     db    3
  124. ;
  125.     dw    40
  126.     db    4
  127.     db    15
  128.     db    1
  129.     dw    194
  130.     dw    127
  131.     db    192,0
  132.     dw    32
  133.     dw    2
  134.     endm
  135.  
  136. ss80    macro
  137. ; single sided, 80 track, 386k, Microbee standard 3.5" CIAB
  138.     db    xltd-xlt_base
  139.     db    2
  140.     db    3
  141. ;
  142.     dw    40
  143.     db    4
  144.     db    15
  145.     db    1
  146.     dw    194
  147.     dw    127
  148.     db    192,0
  149.     dw    32
  150.     dw    2
  151.     endm
  152.  
  153. ds80    macro
  154. ; double sided, 80 track, 776k, MicroBee standard 3.5" Modular
  155.     db    xltc-xlt_base
  156.     db    5
  157.     db    3
  158. ;
  159.     dw    40
  160.     db    5
  161.     db    31
  162.     db    3
  163.     dw    0C2h
  164.     dw    127
  165.     db    80h,0
  166.     dw    32
  167.     dw    4
  168.     endm
  169.  
  170. ds82    macro
  171. ;double sided, 80 track, 782k space, Dreamdisk format
  172.     db    xltd-xlt_base
  173.     db    1
  174.     db    3
  175. ;
  176.     dw    40
  177.     db    4
  178.     db    15
  179.     db    0
  180.     dw    391
  181.     dw    255
  182.     db    0F0h,0
  183.     dw    64
  184.     dw    2
  185.     endm
  186.  
  187. ds84    macro
  188. ; double sided, 80 track, 784k, PJB's format
  189.     db    xltd-xlt_base
  190.     db    1
  191.     db    3
  192. ;
  193.     dw    40
  194.     db    5
  195.     db    31
  196.     db    3
  197.     dw    196
  198.     dw    127
  199.     db    128,0
  200.     dw    32
  201.     dw    2
  202.     endm
  203.  
  204. ds8b    macro
  205. ;double sided, 80 track, 776k space, Beeboard format
  206.     db    xltd-xlt_base
  207.     db    1
  208.     db    3
  209. ;
  210.     dw    40
  211.     db    4
  212.     db    15
  213.     db    0
  214.     dw    389
  215.     dw    127
  216.     db    0C0h,0
  217.     dw    32
  218.     dw    4
  219.     endm
  220.  
  221.  
  222.  
  223.     include    CPMCALLS.MAC
  224.  
  225.  
  226. biosv        equ    0    ;points to BIOS warm start
  227. iobyte        equ    3    ;iobyte
  228. usrdfd        equ    4    ;byte with user_num*16+def_drive
  229. cpmv        equ    5    ;system call vector
  230. viewdrive    equ    8    ;b0-3 are currently viewed drive
  231.  
  232. L0050    equ    50h
  233. DFCB    equ    5Ch
  234. DBUFF    equ    80h
  235. TPA    equ    100h
  236.  
  237. ORGAD    equ    system_start
  238.  
  239. ; Where CP/M is loaded to by 'offload' in the BOOT RAM
  240. boot_pos equ    0A000h
  241.  
  242. ; BOOT ROM location (for bootup only)
  243. boot_rom    equ    0E000H
  244.  
  245. ; system page addresses
  246. check_ram_m    equ    end_sys_r    ; previous pages for m (for check)
  247. check_ram_n    equ    end_sys_r+1    ; previous pages for n
  248. bdos_save_addr    equ    end_sys_r+2    ; where BDOS is saved to
  249.  
  250.  
  251. ;******************************************************************
  252. ;*                                  *
  253. ;*              BOOT    SECTOR              *
  254. ;*                                  *
  255. ;******************************************************************
  256.  
  257.     org    100h    ; not writing a sysgen compatible file,
  258.             ; but a SETSYS compatible file.
  259.  
  260.     .phase    80h
  261.  
  262. ; Boot sector has been modified to boot a double sided disk from a
  263. ; BN54, BN55 or BN56 boot ROM.
  264. ; NB. This only means checking for a BN55, it requires track # 159 for
  265. ;    the first track on side 1, rest require # 79.
  266.  
  267. ; byte to check for BN55
  268. bn55_flag    equ    0EF00h
  269. bn55_val    equ    0
  270.  
  271.     ld    sp,80h
  272.  
  273.     ld    de,0*100H+1    ; track 0 sector 1
  274.     ld    hl,boot_pos
  275.     ld    bc,512*10
  276.     call    boot_rom+39H
  277.     jr    bc_1
  278.  
  279. ; double side boot flag must be at offset 11h for compatability with SETSYS
  280.     if    $ gt 91h
  281.      error    boot flag not in correct position
  282.     else
  283.      ds    $-91h
  284.     endif
  285.  
  286. boot_flag:
  287.     if    boot_ds
  288.      db    79
  289.     else
  290.      db    1
  291.     endif
  292.  
  293. bc_1:
  294. ; next track
  295.     jr    nz,un_boot
  296.  
  297.     ld    de,1*100h+1    ; single sided
  298.     ld    a,(boot_flag)
  299.     cp    1
  300.     jr    z,bc_2
  301.     ld    de,79*100h+1    ; double sided on BN54, BN56
  302.     ld    a,(bn55_flag)
  303.     or    a
  304.     jr    nz,bc_2
  305.     ld    de,159*100h    ; double sided on BN55
  306. bc_2:
  307.     ld    hl,boot_pos+512*10
  308.     ld    bc,512*10    ; +(cpm_end-orgad-512*9)+1
  309.     call    boot_rom+39H    ;offload into RAM
  310.     jp    z,good_boot
  311.  
  312.  
  313. ; print message saying BOOT unsuccessful
  314. un_boot
  315.     ld    c,'Z'-40H
  316.     call    boot_rom+0CH    ;CONOUT
  317.     ld    hl,message
  318.     call    boot_rom+33H    ;flash message, get key
  319.     jp    boot_rom    ;try again
  320.  
  321. message:
  322. ;    db    ' SYSTEM UNREADABLE - PRESS <RETURN> TO TRY AGAIN ',80h
  323.     db    ' BAD SYSTEM ',80h
  324.  
  325.     if    ($-80h) gt 80h
  326.      error    boot part 1 is too big !!!!
  327.     endif
  328.  
  329.     .dephase
  330.  
  331.     .phase    boot_pos+($-100h)
  332.  
  333. good_boot
  334.     di
  335.  
  336.     map    sys_page
  337. ; move system to correct locations
  338.     ld    hl,boot_pos+512
  339.     ld    de,orgad
  340.     ld    bc,cpm_end-orgad
  341.     ldir
  342. ; move stuff into system page
  343.     ld    hl,boot_pos+sys_page_r-100h
  344.     ld    de,0
  345.     ld    bc,end_sys_r
  346.     ldir
  347. ; put bdos into system page
  348.     ld    hl,orgad
  349.     ld    de,bdos_save_addr
  350.     ld    bc,bios-orgad
  351.     ldir
  352.     map    bios_map
  353. ; Cold start BIOS
  354.     jp    boot_accept
  355.  
  356.  
  357. ; INIT ( the ratbags! ) destroys boot sectors > 128 bytes
  358.     if    ($-boot_pos) gt 128    ;512
  359.      error    boot sector too big
  360.      dw    $-boot_pos+zero
  361.     else
  362.      ds    512-($-boot_pos)
  363.     endif
  364.  
  365. boot_length    equ    $-boot_pos
  366.  
  367.     .dephase
  368.  
  369. ;-----------------------------------------------------------------------
  370.  
  371.     .RADIX    16D
  372.  
  373.     .PHASE    ORGAD
  374.  
  375.     include    BDOS.MAC
  376.  
  377. ;----------------------------------------------------------------------
  378.  
  379. ; ****    START OF BIOS
  380.  
  381.     .radix    0AH
  382.  
  383.  
  384. bios_type    equ    7    ;diff. for each radical change
  385.  
  386. bios_type_name    macro
  387.          db    '7'
  388.         endm
  389.  
  390.  
  391. ; Configuration constants
  392. ; see CONFIG block for rest of constants
  393.  
  394. num_drives    equ    tot_dr
  395.  
  396. ; hardware values
  397.  
  398. pioa_data    equ    0
  399. pioa_ctrl    equ    1
  400. piob_data    equ    2
  401. piob_ctrl    equ    3
  402.  
  403. ; 146818 Real time clock addresses if fitted
  404. rtc_addr    equ    4
  405. rtc_read    equ    7
  406. rtc_write    equ    6
  407.  
  408. col_port    equ    8        ;color control, background port
  409. vwait_off    equ    9        ;out anything to this to kill vwait
  410. rom_port    equ    0Bh        ;bit 0 controls rom-read
  411. crtc        equ    0Ch        ;6545 .. 4 ports
  412. beep_port    equ    piob_data
  413. vml        equ    1Ch        ; premium pcg control etc.
  414. ;vml        equ    0        ; Equate to 0 to test for standard
  415. map_port    equ    50h        ;memory map control port
  416. speed_port    equ    9        ;IN here controls CPU speed
  417. speed_value    equ    2        ;'IN' value for fast (A9 high)
  418.  
  419. vdu        equ    8000h        ;character RAM/ CHAR ROM
  420. pcg        equ    8800h        ;PCG ram/ colour
  421. col_ram        equ    8800h        ;where colour ram starts
  422. dden_sel    equ    3        ;bit for DD in dden_byte
  423.  
  424.  
  425. ; status line positions
  426. status_start    equ    vdu+(24*80)+2
  427. pjb_sl        equ    status_start+2
  428. fast_sl        equ    status_start+16    ; 'fast' message
  429. swap_a_m_sl    equ    status_start+23    ; pos of 'A<>M' message
  430. lock_sl        equ    status_start+30    ; pos of lock message
  431. fn_sl        equ    status_start+42    ; 'fn pressed' message
  432. fn_on_sl    equ    status_start+37    ; 'fn active'
  433. clock_sl    equ    status_start+52    ; pos of time on status line
  434.  
  435.  
  436. num_sl_msgs    equ    5    ; number of messages on status line
  437.  
  438. ; status line refreshed after this number of BIOS calls
  439. cycle_max    equ    16
  440.  
  441. ; Start addresses for routines in system page (from .SYS file)
  442. bios_sys_start    equ    5800h
  443. print_s_line    equ    bios_sys_start+6
  444. set_up_s_line    equ    bios_sys_start+9
  445.  
  446. ; .SYS file header values
  447. hdr_pos        equ    8000h        ;examine header here
  448. load_pos    equ    8080h        ;where to initially load to
  449. dbs_start    equ    0        ;must be <= the bios address
  450. dsh_start    equ    2        ;where file loads to
  451. dsh_length    equ    4        ;file length
  452.  
  453.  
  454. ; page 0 addresses
  455. xbs_rst        equ    28h
  456. cpm_fcb        equ    5Ch
  457. fcb_len        equ    16
  458. bdos        equ    5        ;where system call vector goes
  459.  
  460. ; values to write to mapping port ..
  461. normal_map    equ    4        ;screen switched in at F000
  462. bios_map    equ    0Ch        ;screen switched out
  463. vdr_map        equ    14h        ;screen switched in at 8000
  464.  
  465. ; important pages
  466. sys_page    equ    0Dh        ; page for system save etc
  467. md_page_1    equ    0Fh        ; page with m_drive directory
  468. sys_screen    equ    5        ; system page plus screen enabled
  469. sys_vdr        equ    15h        ; ditto at 8000h
  470.  
  471. ; system page addresses
  472. grafix_addr    equ    4000h        ; graphics driver default
  473.  
  474. num_fn_keys    equ    12        ; number of fn keys
  475.  
  476. ; function key store in system page
  477. fn_store    equ    8000h-(num_fn_keys*128)
  478.  
  479. ; extended DPB offsets
  480. dxlt        equ    -3        ;ix offsets for xlt tab offset
  481. dflags        equ    -2        ;b0 if up/down, b1 if 80 track
  482. dsecmsk        equ    -1        ;AND sector mask
  483.  
  484.  
  485. ; Misc
  486. wrual        equ    2        ;write to unalloc from CP/M
  487.  
  488. ; ASCII codes
  489. cr        equ    0Dh
  490. lf        equ    0Ah
  491. tb        equ    9
  492. cls        equ    1Ah
  493. xon        equ    11h        ;Xon code (start xmission)
  494. xoff        equ    13h        ;Xoff code (stop xmission)
  495.  
  496. ;    .list
  497. ; BIOS jump table...
  498.  
  499. bios:    jp    boot_accept    ;Post cold boot
  500. wboote:    jp    wboot        ;Warm boot
  501.  
  502. instat:    jp    v2        ;Console status
  503. conin:    jp    v3        ;Read KBD
  504. bconout:jp    vconout        ;Write cons char in C
  505.  
  506. prntr:    jp    vlistout    ;Print char in C
  507.  
  508. puncho:    jp    v6        ;PUNCH out (1200bd output)
  509. punchi:    jp    v7        ;READER in (1200bd input)
  510.  
  511. ; disk routines
  512. home:    jp    v8        ;Restore to trk 0
  513. seldsk:    jp    v9        ;Select disk (can be logical disk)
  514. settrk:    jp    v10        ;Seek track [C]
  515. setsec:    jp    v11        ;Set sec [C]
  516. bsetdma:jp    v12        ;Set "DMA" address
  517. read:    jp    v13        ;Read a CP/M sector
  518. write:    jp    v14        ;Write a CP/M sector
  519.     jp    vlistst        ;printer ready check
  520. l5430:    jp    v16        ;sectran
  521. ;
  522.     defb    bios_type
  523.  
  524.  
  525. ; default 6545 table, reloaded on warm boot
  526. crtc_tab
  527.     defb    108-1,80,89,37H,28-1,5
  528. ; this value is used as an ON/OFF flag for the status line
  529. s_line
  530.     if    status_line
  531.      db    25
  532.     else
  533.      db    24
  534.     endif
  535.     defb    26,48h,10,10+20h,10,20H,0,0,0
  536.  
  537.     if    preset_disks
  538.  
  539. ; DPH's for preset disk types
  540. dpbase:    dw    0,0,0,0,dirbuf,disk_A+3,csv0,alv0
  541.     dw    0,0,0,0,dirbuf,disk_B+3,csv1,alv1
  542.     dw    0,0,0,0,dirbuf,disk_C+3,csv2,alv2
  543.     dw    0,0,0,0,dirbuf,disk_D+3,csv3,alv3
  544.  
  545.     else
  546.  
  547. ; DPH's for non preset types
  548. dpbase:    dw    0,0,0,0,dirbuf,0,csv0,alv0
  549.     dw    0,0,0,0,dirbuf,0,csv1,alv1
  550.     dw    0,0,0,0,dirbuf,0,csv2,alv2
  551.     dw    0,0,0,0,dirbuf,0,csv3,alv3
  552.  
  553.     endif
  554.  
  555.  
  556. dpb_base    equ    $+3
  557.  
  558.     disk_type_def        ; puts in selected dpb's
  559.  
  560.  
  561. ; spare data room for custom format setup
  562.     db    xlte-xlt_base    ;sector xlate
  563.     db    0        ;"cylinder" and "don't correct" flag
  564.     db    0        ;sector mask
  565. ;
  566. spare_dpb:dw    0        ;sectors per cylinder
  567.     db    0        ;block shift factor
  568.     db    0        ;block mask
  569.     db    0        ;extent mask
  570.     dw    0        ;blocks per diskette
  571.     dw    0        ;# directory entries
  572.     db    0        ;alloc 0
  573.     db    0        ;alloc 1
  574.     dw    0        ;dir check vector size
  575.     dw    0        ;system track offset
  576.  
  577.  
  578. ; Sector translation tables
  579. xlt_base equ    $
  580. ; spare room for up to 54 sector long xlt table
  581. xlte:    db    01,02,03,04,05,06,07,08,09
  582.     db    10,11,12,13,14,15,16,17,18
  583.     db    19,20,21,22,23,24,25,26,27
  584.     db    28,29,30,31,32,33,34,35,36
  585.     db    37,38,39,40,41,42,43,44,45
  586.     db    46,47,48,49,50,51,52,53,54
  587. ;
  588. ; The positions of xltc & xltd must not be changed
  589. ; strange modification of xltd for standard 3.5" ds
  590. xltc:    db    22,25,28
  591.     db    21,24,27,30
  592.     db    23,26,29
  593. ;
  594. ; "shifted" 3 sector skew for 10 sectors designed to maximize
  595. ; the time between steps
  596. xltd:    db    2,5,8
  597.     db    1,4,7,10
  598.     db    3,6,9
  599.  
  600.  
  601. ;    .list
  602. ; Data which is changed by INIT for varying requirements ..
  603. sh_wanted
  604.     defb    init_sh        ;=0 for CCP, =1 for shell
  605. col_mode
  606.     defb    init_col_mode    ;color mode port value
  607. col_char
  608.     defb    init_col    ;color character value
  609. snum_drives
  610.     defb    tot_dr        ;number of drives starting at A:
  611. snum_floppies
  612.     defb    tot_dr        ;number of above which are floppies
  613. pr_baud
  614.     defb    2    ;printer baud rate code - 1200 baud default
  615. send_lf
  616.     defb    1    ;zero if linefeeds are to be filtered
  617. ; changed by INIT for serial/ parallel printer selection ..
  618. i_iobyte
  619.     defb    81h    ;initial IOBYTE - parallel
  620. use_xonxoff
  621.     defb    0    ;nz if xon/xoff used for serial port
  622. submit_flag
  623.     defb    0    ;nz if submit in progress (or is that process?)
  624.  
  625.     defs    5    ;expansion
  626.  
  627. ; RS232 comm. parameters which set format
  628. num_data    defb    8        ;number of data bits
  629. parity        defb    1        ;1=no par, 2=odd, 3=even
  630. ; +1 in next gives mid to late sampling; +0 early to mid
  631. ; parity is ignored but read through
  632. r_num        defb    4*(1+8)+0    ;4*(nstrt+ndata)+0
  633. totalq        defb    (1+8+0+1)*4    ;(nstrt+ndata+npar+nstop)*4
  634. adj_fact    defb    13-1-8-0    ;13-nstrt-ndata-npar
  635.  
  636.  
  637. ; default settings for options in Bshell companion programs
  638. xfer_options
  639.     defb    0,0,0,0,0,0,0,0
  640. init_options
  641.     defb    0,0            ;these are actually used
  642. others
  643.     defb    0,0,0,0,0,0,0,0
  644.     defb    0,0,0,0,0,0,0,0
  645.     defb    0,0
  646.  
  647. ; map of which drives are 80 track ones
  648. ; this isn't actually used
  649. tk80_drives
  650. ; It's now used to indicate 'cache-able' drives (set by user)
  651. ; 0FFh = don't cache
  652. cache_map
  653.     db    0,0,0,0
  654.  
  655. ; Stuff for ZCPR
  656.     defw    free_128_bytes
  657.     defb    128
  658.     defb    0
  659. ; 128 bytes for ZCPR and Bshell to hold multiple commands
  660. ; **    STARTUP command buffer
  661. free_128_bytes
  662.     ds    128,0
  663.  
  664.  
  665. ; align to 2 byte boundary ..
  666.     defs    ($ and 1)
  667. pioa_vect    defw    par_int        ;pio a int vector
  668. piob_vect    defw    int_rtn        ;pio b int vector
  669.         defw    0        ;some spares
  670.         defw    0
  671.         defw    0
  672.         defw    0
  673. ; may need to make some space here for 8530 VIS INT vector
  674. ; ...
  675.  
  676. dtr_max        equ    (end_queue-RS_queue)-5
  677.  
  678. r_ptr        defw    end_queue-RS_queue    ;q_base index -
  679.                         ; last posn read from
  680. w_ptr        defw    end_queue-RS_queue    ;q_base index -
  681.                         ; last posn. written to
  682. q_base        defw    RS_queue        ;holds addr. of start of queue
  683. q_max        defw    end_queue-RS_queue    ;max index onto queue
  684.                         ; (1 less than size)
  685. dtr_limit    defw    dtr_max            ;# safe chars left in buffer
  686. ; RS232 timing (setup by set_baud)
  687. simult        defw    l1200    ;address of txrx controller (l300/l1200)
  688.  
  689.  
  690. ; M-drive data
  691. md_DPH
  692.     DW    0,0,0,0,DIRBUF,md_DPB,CSV3,ALVM
  693. ;
  694.     DB    0        ;128 byte physical sectors
  695.  
  696. md_DPB:    dw    32        ;128 byte sectors per 16k track
  697.     db    4        ;Shift factor for 2k blocks
  698.     db    15        ;Block mask
  699.     db    1        ;Extent mask
  700.     dw    md_pages*16-1    ;Largest block number - patchable
  701.     if    md_pages lt 8
  702.      dw    63        ;Max directory entry (if < 256k)
  703.      db    80h        ;Blank allocation map (1 block = 2k)
  704.     else
  705.      dw    127        ;Max directory entries (if >= 256k)
  706.      db    0C0h        ;Blank allocation map (2 blocks = 4k)
  707.     endif
  708.     db    0        ;
  709.     dw    0        ;Check dir length
  710.     dw    0        ;System tracks
  711.  
  712.  
  713. ; 16 bit flag indicating it is PJB's BIOS
  714. bios_flag
  715.     dw    0AA55h
  716.  
  717. ; type of system bios is assembled for
  718. bios_id
  719.     if    telecomputer
  720.      db    7
  721.     else
  722.      db    3
  723.     endif
  724.  
  725. ; Space for 16 preset values etc.
  726.  
  727. ; non zero to map logical A onto physical M
  728. swap_a_with_m
  729.     db    0
  730. is_premium
  731.     db    false        ; initial value only
  732. ; force formatting of ram disk on cold boot
  733. force_format
  734.     db    format_m
  735. ; graphics driver start address, can be changed by graphics installation
  736. ;  program
  737. gr_addr
  738.     dw    0
  739. ; function keys active
  740. fn_active
  741.     db    true
  742. ; where WINDOW.SYS ends up
  743. window_addr
  744.     dw    0
  745. click_length
  746.     db    7
  747. click_tone
  748.     db    22
  749. pages_for_md
  750.     db    md_pages
  751. dbuff_pages
  752.     db    db_pages
  753. pages_for_nd
  754.     db    nd_pages
  755. col_stat
  756.     db    stat_col
  757. max_pages
  758.     db    total_pages
  759. user_page
  760.     db    0        ;default value indicating no user program
  761.  
  762.     ds    16-($-swap_a_with_m)
  763.  
  764. ; these are FCB's for shell, CCP, window and fn key def's file
  765. sh_fcb
  766.     db    1        ;drive A
  767.     db    'SHELL   SYS'
  768.     db    0,0,0,0        ;ex, s1, s2, rc
  769.  
  770. ccp_fcb
  771.     db    1
  772.     db    'CCP     SYS'
  773.     db    0,0,0,0
  774.  
  775. window_fcb:
  776.     db    1
  777.     db    'WINDOW  SYS'
  778.     db    0,0,0,0
  779.  
  780. fn_key_fcb
  781.     db    1
  782.     db    'DEFAULT FK '
  783.     db    0,0,0,0
  784.  
  785. ; space for definition of cursor keys etc.
  786. curs_key_tab
  787.     db    'E'-40h,0,'X'-40h,'S'-40h,'_'    ,'Q'-40h,'D'-40h,0
  788.     db    'R'-40h,0,'C'-40h,'A'-40h,'J'-40h,'K'-40h,'F'-40h,0
  789.  
  790. ; required by window program etc.
  791. window_needs:
  792.     dw    scn_in
  793.     dw    get_rtc
  794.     dw    put_rtc
  795. in_fnstr
  796.     db    false
  797. fn_ptr
  798.     dw    0    
  799.     dw    ptr_out
  800. linpos
  801.     db    0        ; cursor line
  802. colpos
  803.     db    0        ; cursor column
  804. cursor
  805.     dw    vdu        ; cursor address
  806.     dw    is_closed    ; check for key pressed
  807. al_rev
  808.     db    false        ; caps lock
  809. fast_cpu
  810.     db    fast_speed    ; run at 6.75 MHz
  811. no_clock
  812.     db    false        ; set up by code
  813. restore_db_pages
  814.     db    db_pages    ; So disable cache program can re-enable
  815. user_addr
  816.     dw    0        ; Address of user program
  817.     dw    mem_page    ; Address of mem_page routine
  818.  
  819.     ds    32-($-window_needs)
  820.  
  821. keyboard_fcb:
  822.     db    1
  823.     db    'BIOS    SYS'
  824.     db    0,0,0,0
  825.  
  826. ; N-drive data
  827. Nd_DPH
  828.     DW    0,0,0,0,DIRBUF,nd_DPB,CSV3,ALVM+(md_pages*2)
  829. ;
  830.     DB    0        ;128 byte physical sectors
  831.  
  832. nd_DPB:    dw    32        ;128 byte sectors per 4k track
  833.     db    4        ;Shift factor for 2k blocks
  834.     db    15        ;Block mask
  835.     db    1        ;Extent mask
  836.     dw    nd_pages*16-1    ;Largest block number - patchable
  837.     if    nd_pages lt 8
  838.      dw    63        ;Max directory entry (if < 256k)
  839.      db    80h        ;Blank allocation map (1 block = 2k)
  840.     else
  841.      dw    127        ;Max directory entries (if >= 256k)
  842.      db    0C0h        ;Blank allocation map (2 blocks = 4k)
  843.     endif
  844.     db    0        ;
  845.     dw    0        ;Check dir length
  846.     dw    md_pages*8    ;System tracks
  847.  
  848. sl_table
  849.     dw    sl_pointers
  850. sl_messages
  851.     dw    sl_msgs
  852.  
  853. ;-------------------------------------------------------
  854.  
  855. ; BDOS scratch which needs to be referenced while the rest
  856. ; of the BIOS is swapped out
  857. dirbuf
  858. ; dirbuf is shared with COLD BOOT code ..
  859.  
  860.  
  861.     if    name_protect
  862. start_check
  863.     db    0FFh,11h,22h,00h
  864.     endif
  865.  
  866.  
  867. boot_accept
  868.     ld    sp,boot_stack
  869.  
  870. ; bring this stuff down from CONIO.Z
  871.     ld    hl,iotabl    ;set up PIO
  872.  
  873.     if    scramble
  874.      ld    a,high decrypt
  875.      ld    (jp_decrypt+2),a
  876.     endif
  877.  
  878. ; initialization of PIO
  879. ; requires hl=pointer to dgos type IO initialization table
  880.     {
  881.         ld    a,(hl)
  882.         or    a
  883.         #if    z,brk
  884.         ld    b,a
  885.         inc    hl
  886.         ld    c,(hl)
  887.         inc    hl
  888.         otir
  889.         #cont
  890.     }
  891.  
  892. ; baud rate set to 1200 (set to correct value in go_cpm)
  893.  
  894.     call    pio_clr        ;unconfuse PIO with reti
  895.  
  896.     im    2
  897.     ld    a,pioa_vect shr 8
  898.     ld    i,a
  899.  
  900.     xor    a
  901.     ld    (usrdfd),a    ;set boot-up disk to A0
  902.     ld    (viewdrive),a    ;clear initial viewed drive
  903.  
  904. ; set IOBYTE to initial value
  905.     ld    a,(i_iobyte)
  906.     ld    (iobyte),a
  907.  
  908.     map    sys_vdr
  909.  
  910.     call    check_premium
  911.  
  912.     if    scramble
  913.      call    jp_decrypt
  914.     endif
  915.  
  916.     sflag    0,'1',sys_vdr
  917.  
  918.     call    check_ramdisks
  919.  
  920.     sflag    0,'5',sys_vdr
  921.  
  922. ; initialise disk buffer (if enabled)
  923.     call    db_init
  924.  
  925. ; print boot up message
  926.     ld    de,smsg        ;opening message
  927.     ld    c,pristr
  928.     call    bdosin
  929.  
  930.     ei
  931.  
  932. ; now go onto common routines
  933.  
  934.     jp    gocpm
  935.  
  936.  
  937.  
  938. smsg
  939.     db    cls,lf,tb,'Microbee '
  940.     if    mem_128
  941.      db    '128'
  942.     else
  943.      db    '512'
  944.     endif
  945.     db    'k CP/M 2.2, BIOS v'
  946.     bios_type_name
  947.     db    '.',cr,lf,lf
  948.     db    tb,'Enhanced BIOS (c) '
  949. my_name:
  950.     db    'Peter Broughton.',cr,lf,tb,'Version '
  951.     version
  952.     if    not telecomputer
  953. smsg_premium
  954.      db    'P'        ; changed by check code
  955.     else
  956.      db    'T'
  957.     endif
  958.     if    scramble
  959.      db    'S'
  960.     endif
  961.     db    ', '
  962.     date
  963.     db    '.',cr,lf,lf
  964.     if    name_protect
  965.     db    'This disk belongs to '
  966. user_name:
  967.     db    '!@#'
  968.     ds    30-($-user_name)
  969.     db    '.',cr,lf,lf
  970.     endif
  971.     db    '$'
  972.  
  973. ; I/O initialisation table
  974. iotabl
  975. ; set up port A as a parallel output port
  976.     defb    3,pioa_ctrl
  977.     defb    pioa_vect and 0FFh    ; parallel port o/p vector
  978.     defb    0Fh,83h
  979. ; set up port B for correct directions, enable serial ints
  980.     defb    5,piob_ctrl
  981.     defb    piob_vect and 0FFh
  982.     defb    0FFh            ; bit mode
  983. piob_dir
  984. ;    if    new_keyboard
  985. ;     db    09Ah            ; b7,b4,b3,b0 & b1 for keyboard
  986. ;    else
  987.      db    099h            ; b7;b4;b3;b0 inputs
  988. ;    endif
  989.     defb    80h+37h,255-10h        ; b7=1 of first -> interrupt (on)
  990.     defb    1,piob_data
  991.     defb    20h    ;24h        ; initial port B output (DTR=1)
  992.     defb    0
  993.  
  994.  
  995.  
  996.     if    name_protect
  997. end_check
  998.     db    0FFh,33h,44h
  999.     endif
  1000.  
  1001.  
  1002. ; checksum vectors
  1003.     if    dreamdisk_available
  1004. csv_size    equ    64
  1005.     else
  1006. csv_size    equ    32
  1007.     endif
  1008.  
  1009. csv0    equ    dirbuf+128    ;32 reqd for DD 512 bytes/sector format
  1010. csv1    equ    csv0+csv_size    ; or 64 required for dreamdisk fmt
  1011. csv2    equ    csv1+csv_size
  1012.  
  1013. ; move $ on to correct position for csv3
  1014.     if    ($-dirbuf) lt 128+(3*csv_size)
  1015.      ds    (128+(3*csv_size))-($-dirbuf)
  1016.     endif
  1017.  
  1018. csv3:    defs    csv_size
  1019.  
  1020. ; COLD and WARM boot stack - csv3 not used at BOOT-UP
  1021. boot_stack
  1022.  
  1023. ; allocation vector space
  1024. ; may be shared with code to load in .SYS files ( except for alv0 )
  1025.     if    dreamdisk_available
  1026. alv_size    equ    50    ; enough space for ds 80 track with 2k blocks
  1027.     else
  1028. alv_size    equ    25
  1029.     endif
  1030.  
  1031. alv0    equ    $
  1032. alv1    equ    alv0+alv_size
  1033. alv2    equ    alv1+alv_size
  1034. alv3    equ    alv2+alv_size
  1035. alvm    equ    alv3+alv_size
  1036. end_alv    equ    alvm+(((32/2)/8)*13)    ;=26 bytes
  1037.  
  1038.     if    scramble
  1039. decrypt:
  1040.     ld    hl,(start_check)
  1041.     ld    de,start_check+4-11FFh
  1042.     add    hl,de
  1043.     ld    de,end_check-start_check-4
  1044.     ld    c,0
  1045. dcr1:
  1046.     ld    a,l
  1047.     add    a,(hl)
  1048.     and    7
  1049.     ld    b,a
  1050.     inc    hl
  1051.     ld    a,(hl)
  1052. dcr2:
  1053.     rrca
  1054.     djnz    dcr2
  1055.     add    a,c
  1056.     ld    c,a
  1057.     dec    de
  1058.     ld    a,d
  1059.     or    e
  1060.     jr    nz,dcr1
  1061.  
  1062.     ld    hl,encrypt_start
  1063.     ld    de,end_encrypt+4-encrypt_start
  1064.     ld    b,0
  1065. dcr3:
  1066.     ld    a,b
  1067.     add    a,c
  1068.     ld    b,a
  1069.     xor    (hl)
  1070.     xor    l
  1071.     ld    (hl),a
  1072.     inc    hl
  1073.     dec    de
  1074.     ld    a,d
  1075.     or    e
  1076.     jr    nz,dcr3
  1077.     ret
  1078.  
  1079.     endif
  1080.  
  1081.     if    $ lt alv1
  1082.      ds    alv1-$
  1083.     endif
  1084.  
  1085. ; load in .SYS files according to FCB's in configuration block
  1086. load_sys_files:
  1087.     map    bios_map
  1088.     syscall    resdis
  1089. ; loop to load in all files
  1090.     ld    a,5        ; five files
  1091.     ld    hl,sh_fcb    ; first FCB
  1092.     ld    iy,sh_loaded    ; first data pos
  1093. sys_load_loop:
  1094.     ld    (temp_1),a
  1095.     push    iy
  1096.     push    hl
  1097. ; copy file name into message
  1098.     inc    hl
  1099.     ld    de,loading_name
  1100.     ld    bc,8
  1101.     ldir
  1102.     inc    de
  1103.     ld    c,3
  1104.     ldir
  1105.     ld    de,loading_mes
  1106.     syscall    pristr
  1107.     pop    hl
  1108.     push    hl
  1109.  
  1110. ; get .SYS file from A: drive.
  1111. ; requires : hl -> FCB
  1112.     ld    de,cpm_fcb
  1113. ; move this FCB to a working one
  1114.     ld    bc,fcb_len
  1115.     ldir
  1116.     xor    a
  1117.     ld    (cpm_fcb+32),a    ;clear CR
  1118.     ld    de,cpm_fcb
  1119.     syscall    opefil
  1120.     inc    a
  1121.     jp    z,sys_not_loaded
  1122.  
  1123. ; read in header block
  1124.     ld    de,hdr_pos
  1125.     syscall    setdma
  1126.     ld    de,cpm_fcb
  1127.     syscall    reaseq
  1128.     or    a
  1129.     jp    nz,sys_not_loaded
  1130.  
  1131. ; is the bios start value low enough ?
  1132.     ld    hl,(hdr_pos+dbs_start)
  1133.     ld    de,bios+3
  1134.     and    a
  1135.     sbc    hl,de        ;get NC if bios < sh_bios
  1136.     jp    nc,sys_not_loaded
  1137.  
  1138.     ld    hl,load_pos
  1139. ; read rest of file
  1140.     {
  1141. ; hl = where to put it
  1142.         ex    de,hl
  1143.         push    de
  1144.         syscall    setdma
  1145.         ld    de,cpm_fcb
  1146.         syscall    reaseq
  1147.         or    a        ;finished?
  1148.         pop    de
  1149.         #if    nz,brk
  1150.         ld    hl,128        ;point to next position
  1151.         add    hl,de
  1152.         #cont
  1153.     }
  1154.  
  1155.     ld    hl,load_pos
  1156.     ld    bc,(hdr_pos+dsh_length)
  1157.     map    sys_page
  1158.     ld    a,(temp_1)        ; is this WINDOW.SYS
  1159.     cp    4            ; or DEFAULT.FK
  1160.     jr    nc,not_window
  1161. ; move WINDOW.SYS or DEFAULT.FK to correct position
  1162.     ld    de,(hdr_pos+dsh_start)
  1163.     push    de
  1164.     ldir
  1165.     pop    hl
  1166.     cp    3
  1167.     jr    z,is_window
  1168.     cp    1        ; is KEYBOARD.SYS ?
  1169.     jr    z,loaded
  1170. ; if .FK then load cursor key defs.
  1171.     ld    hl,hdr_pos+40h
  1172.     ld    de,curs_key_tab
  1173.     ld    c,16        ; b already 0
  1174.     ldir
  1175.     jr    loaded
  1176. is_window:
  1177. ; if window then load start address
  1178.     ld    (window_addr),hl
  1179.     jr    loaded
  1180. not_window:
  1181. ; is SHELL or CCP so move into first available address in system page
  1182.     ld    de,(sys_avail)
  1183.     push    de
  1184.     ld    (iy+3),c
  1185.     ld    (iy+4),b
  1186.     ldir
  1187. ; if it exceeded available memory then reject it
  1188.     ld    h,d
  1189.     ld    l,e
  1190.     ld    bc,bios_sys_start
  1191.     or    a
  1192.     sbc    hl,bc
  1193.     pop    hl            ; hl -> address in system page
  1194.     ld    (iy+5),l
  1195.     ld    (iy+6),h
  1196.     jr    nc,sys_not_loaded
  1197.     ld    (sys_avail),de        ; next available address
  1198.     ld    hl,(hdr_pos+dsh_start)    ; run position
  1199.     ld    (iy+1),l
  1200.     ld    (iy+2),h
  1201.  
  1202. loaded:
  1203.     ld    (iy+0),true        ; it is actually there
  1204.     ld    de,ld_mes_end
  1205.     jr    cont_loop
  1206.  
  1207. ; file was not there or an error occured
  1208. sys_not_loaded
  1209.     ld    de,not_loaded_mes
  1210.     ld    (iy+0),false        ; file not loaded
  1211.  
  1212.  
  1213. ; continuation of loop
  1214. cont_loop:
  1215.     map    bios_map
  1216. ; print CR, LF or 'not loaded'
  1217.     syscall    pristr
  1218.     pop    hl
  1219.     ld    bc,16
  1220.     add    hl,bc        ; next FCB
  1221.     ld    c,7
  1222.     pop    iy
  1223.     add    iy,bc        ; next data section
  1224.     ld    a,(temp_1)    ; counter
  1225.     cp    4
  1226.     jr    nc,next_not_fk
  1227. ; no 'loaded' variable for KEYBOARD.SYS or .FK file so use dummy position
  1228.     ld    iy,save_p
  1229. next_not_fk:
  1230.     cp    2    ; if next KEYBOARD then move to correct fcb
  1231.     jr    nz,next_not_kbd
  1232.     ld    hl,keyboard_fcb
  1233. next_not_kbd:
  1234.     dec    a
  1235.     jp    nz,sys_load_loop
  1236.  
  1237.  
  1238.     ld    de,ld_mes_end    ; cr & lf
  1239.     syscall    pristr
  1240.     ld    de,ld_mes_end    ; cr & lf
  1241.     syscall    pristr
  1242.     map    bios_map
  1243.  
  1244.  
  1245. ; now delete call to this routine so it is only called once
  1246.  
  1247.     pop    hl
  1248.     xor    a
  1249.     dec    hl
  1250.     ld    (hl),a
  1251.     dec    hl
  1252.     ld    (hl),a
  1253.     dec    hl
  1254.     ld    (hl),a
  1255.  
  1256. ; enable keyboard, previously this is disabled to stop the user
  1257. ; interrupting the cold boot routines
  1258. ; Actually the keyboard driver probably wasn't there anyway !
  1259.     ld    (disable_kbd),a
  1260.  
  1261. ; Return from this routine
  1262.     jp    (hl)
  1263.  
  1264. loading_mes:
  1265.     db    'Loading '
  1266. loading_name:
  1267.     db    'FILENAME.EXT ... $'
  1268. not_loaded_mes:
  1269.     db    'not loaded.'
  1270. ld_mes_end:
  1271.     db    cr,lf,'$'
  1272.  
  1273.  
  1274. ; make sure sufficent space for alv's
  1275.     if    $ lt end_alv
  1276.      ds    end_alv-$
  1277.     endif
  1278.  
  1279.  
  1280. ;    Warm boot
  1281. WBOOT
  1282.     map    sys_page
  1283.     ld    sp,boot_stack
  1284.     ld    hl,3
  1285.     ld    (offs_start),hl    ;on warm boot, go in 3 bytes after
  1286.  
  1287. ; Get BDOS from system page, system page must already be enabled
  1288.     call    bdos_from_bp
  1289.  
  1290. ; and into common routines..
  1291.  
  1292. ; Common code used after COLD or WARM boot
  1293. gocpm
  1294. ; call common routines
  1295.     map    bios_map
  1296.     call    common_boot
  1297.  
  1298. ; Load in .SYS files
  1299. ; this call is deleted by last part of load_sys_files subroutine
  1300.     call    load_sys_files
  1301.  
  1302. ; Call to set up status line, must be done after loading system files
  1303.     map    sys_vdr
  1304.     call    set_up_s_line
  1305.  
  1306. ; now get selected user interface from system page
  1307. ; and get hl --> address of start
  1308. ; sys_vdr must still be enabled as this is in system page
  1309.     call    load_user_int
  1310.  
  1311. ; Now jump to user interface
  1312.     map    normal_map
  1313.     ld    a,(usrdfd)    ;Get last default disk
  1314.     ld    c,a        ;CCP req this in C
  1315.     jp    (hl)
  1316.  
  1317.  
  1318.  
  1319. ; execute extended BIOS function
  1320. x_bios_calls
  1321.     push    ix        ;save ix
  1322.     ld    (save_sp),sp
  1323.     ld    sp,bios_stack
  1324.     push    af
  1325.     map    sys_page    ; VDU MUST be out, switch in address table
  1326. ;    map    bios_map
  1327.     pop    af
  1328. ; rest of routine is now behind screen
  1329.     jp    call_xbios
  1330.  
  1331.  
  1332. ; BIOS entry points vector through here
  1333. v2:    call    accept
  1334.     dw    const        ;Console status
  1335. v3:    call    accept
  1336.     dw    mchinw        ;Read KBD
  1337.  
  1338. vconout
  1339.     ld    a,(iobyte)
  1340. com_out
  1341.     and    3
  1342.     dec    a
  1343.     jp    z,govdu
  1344.     call    accept
  1345.     dw    ptr_out        ;handles parallel AND serial
  1346.  
  1347. vlistout
  1348.     ld    a,(iobyte)
  1349.     rlca
  1350.     rlca
  1351.     jr    com_out
  1352.  
  1353. v6:    call    accept
  1354.     dw    pun_out        ;PUNCH out (serial output)
  1355. v7:    call    accept
  1356.     dw    pun_in        ;READER in (serial input)
  1357. ; disk routines
  1358. v8:    call    accept
  1359.     dw    d_home        ;Restore to trk 0
  1360. v9:    call    accept
  1361.     dw    d_seldsk    ;Select disk (can be logical disk)
  1362. v10:    call    accept
  1363.     dw    d_stk        ;Seek track [C]
  1364. v11:    call    accept
  1365.     dw    d_ssc        ;Set sec [C]
  1366. v12:    call    accept
  1367.     dw    d_sdm        ;Set "DMA" address
  1368. v13:    call    accept
  1369.     dw    d_read        ;Read a CP/M sector
  1370. v14:    call    accept
  1371.     dw    d_write        ;Write a CP/M sector
  1372.  
  1373. vlistst
  1374.     call    accept
  1375.     dw    all_listst
  1376.  
  1377. v16:    call    accept
  1378.     dw    sectran
  1379.  
  1380.  
  1381.  
  1382. accept
  1383. ; turn off the video so we don't execute it.
  1384.     push    af
  1385.     map    bios_map
  1386.     pop    af
  1387.  
  1388.     ex    (sp),ix        ;get return address/ save ix
  1389.     ld    (save_sp),sp
  1390.     ld    sp,bios_stack    ;local stack to avoid bank sw crash
  1391.     push    hl        ;save hl
  1392.     call    display_time
  1393.     ld    l,(ix+0)    ;get address of routine
  1394.     ld    h,(ix+1)
  1395.     ex    (sp),hl        ;put address on stack/ get hl back
  1396.     ret            ;perform BIOS function
  1397. ; .. and return to here ..
  1398. ; bios_map must be enabled here
  1399. recover
  1400.     ld    sp,(save_sp)    ;get old stack back
  1401.     pop    ix        ;get ix back
  1402.     push    af
  1403.     map    normal_map    ;turn video back on
  1404.     pop    af
  1405.     ret
  1406.  
  1407. ; Intermediate stage before recover if wrong page is in
  1408. recover_bmap
  1409.     push    af
  1410.     map    bios_map
  1411.     pop    af
  1412.     ret
  1413.  
  1414. ; a faster bank swapping routine for the VDU driver,
  1415. ; which puts the VDU at 8000h
  1416. govdu
  1417.     ld    (save_sp),sp
  1418. ; use local stack in case user stack is at 8000h-8FFFh ..
  1419.     ld    sp,bios_stack
  1420.     map    bios_map
  1421.     call    display_time
  1422.     map    vdr_map
  1423.     jp    vduout
  1424. ; which then jumps to here
  1425. retvdu
  1426.     map    normal_map
  1427.     ld    sp,(save_sp)
  1428.     ret
  1429.  
  1430. ; do a BDOS call from the BIOS
  1431. bdos_func
  1432.     call    bdos
  1433.     push    af
  1434.     map    bios_map
  1435.     pop    af
  1436.     ret
  1437.  
  1438. ; link to premium graphics driver in backplane
  1439. link_graphics
  1440.     push    hl
  1441.     ld    hl,(gr_addr)
  1442.     ld    a,h
  1443.     or    l
  1444.     jr    z,no_grfx
  1445.     ld    (grfx_jp),hl
  1446.     ld    hl,recover_bmap
  1447.     ex    (sp),hl        ; Restore HL, put return address on stack
  1448.     map    sys_screen    ; system page with screen at 0F000h
  1449. grfx_jp    equ    $+1
  1450.     call    4000h        ; Jump to graphics program
  1451.     map    bios_map
  1452.     ret
  1453.  
  1454. no_grfx:
  1455.     pop    hl
  1456.     or    -1
  1457.     ret
  1458.  
  1459.  
  1460. chk_break
  1461. ; given char to save in c, store it on the queue
  1462. ; but shift right if only 7 bits of data (8 bits including
  1463. ; start bit) were read
  1464.     ld    a,(num_data)
  1465.     cp    7
  1466.     jr    nz,st2
  1467.     srl    c        ;since only 7 data bits
  1468. st2
  1469.     call    will_fit
  1470.     ret    z        ;full, so no more can fit
  1471.     ld    (w_ptr),de
  1472.     ld    (ix+0),c
  1473.     in    a,(piob_data)
  1474. ; now negate DTR if the buffer is too full
  1475.     {
  1476.         ld    hl,(dtr_limit)
  1477.         dec    hl
  1478.         ld    (dtr_limit),hl
  1479.         bit    7,h
  1480.         #if    z,brk
  1481. ; negate DTR if less than 4 chars left in buffer
  1482.         res    ser_dtr,a
  1483.         out    (piob_data),a
  1484.     }
  1485.  
  1486. ; we now know that a character was got, so if still spacing,
  1487. ; wait for a bit time (this means a parity bit)
  1488. ; Therefore, breaking the input line will not affect operation
  1489. ; of anything except that an extra stop bit time is added onto each
  1490. ; character transmitted
  1491.     bit    ser_in,a
  1492.     ret    z        ;it is already marking (stop bit)
  1493. ; we may be reading through a parity bit, so wait a bit time ..
  1494.     ld    de,0*256+4
  1495. ; and follow on to jp_simul ..
  1496.  
  1497.  
  1498. ; set up for txrx call; ix=(simult), (flag)=-1, b=(piob_data) ..
  1499. jp_simul
  1500.     out    (vwait_off),a    ;stop video waiting
  1501.     ld    ix,(simult)    ;address of io routine
  1502.     ld    a,-1
  1503.     ld    (flag),a    ;set for no char recvd
  1504.     in    a,(piob_data)
  1505.     ld    b,a
  1506.     res    ser_out,b    ;base for output
  1507.  
  1508. ; and follow on to txrx ..
  1509.  
  1510. ; the routine which handles one quarter bit time ..
  1511. ; this was written so that each path in the program has the
  1512. ; same time (except for start bit detection)
  1513. ; (orig 146 T-states for txrx alone)
  1514. ; the delay routine must delay for (3.375e+6) / Fbr / 4 - 162  Tstates
  1515. ; excluding its final jump to CONT
  1516. txrx
  1517.     ld    a,d    ;finished tx ing?
  1518.     or    a
  1519.     jr    z,nsend1
  1520.     and    3    ;sending quarter?
  1521.     jr    nz,nsend2
  1522.     add    hl,hl    ;shift hl up one
  1523.     ld    a,h
  1524.     and    +(1 shl ser_out)
  1525.     or    b    ;b=the old pio B data with ser_out 0
  1526.     out    (piob_data),a
  1527. tecov2
  1528.     dec    d    ;decrement tx counter
  1529. tecov1
  1530.     ld    a,e    ;started rcving yet?
  1531.     or    a
  1532.     jr    z,notyet
  1533.     and    3    ;receive quarter?
  1534.     jr    nz,norcv2
  1535.     in    a,(piob_data)
  1536.     and    +(1 shl ser_in)
  1537.     sub    1
  1538.     rr    c
  1539. rxcov1
  1540.     dec    e
  1541. rxcov2
  1542.     jp    (ix)
  1543. cont
  1544.     ld    a,d        ;any rxing or txing to go?
  1545.     or    e
  1546.     jp    nz,txrx
  1547.     ret
  1548. ;
  1549. nsend2
  1550.     or    a
  1551.     or    a
  1552.     or    a
  1553.     or    a
  1554.     or    a
  1555.     jr    tecov2
  1556. ;
  1557. nsend1
  1558.     ex    (sp),hl
  1559.     ex    (sp),hl
  1560.     jr    tecov1
  1561. ;
  1562. norcv2
  1563.     or    a
  1564.     or    a
  1565.     or    a
  1566.     or    a
  1567.     jr    rxcov1
  1568. ;
  1569. notyet
  1570.     in    a,(piob_data)
  1571.     bit    ser_in,a
  1572.     jr    z,mark
  1573. ;
  1574. ; note this path is longer, but it only happens once at start bit
  1575.     ld    a,(r_num)
  1576.     ld    e,a
  1577.     xor    a
  1578.     ld    (flag),a
  1579.     jp    (ix)        ;(was ret)
  1580. ;
  1581. mark
  1582.     ld    a,0
  1583.     jp    rxcov2
  1584.  
  1585.  
  1586.  
  1587. ; Timing routines for each baud rate 300, 600, 1200, 2400, 4800
  1588.  
  1589. ;l110 hahaha
  1590.  
  1591. l300
  1592.     ld    a,165
  1593.     {
  1594.         dec    a
  1595.         #if    nz,cont
  1596.     }
  1597.     jr    cont
  1598.  
  1599. l600
  1600.     ld    a,77
  1601.     {
  1602.         dec    a
  1603.         #if    nz,cont
  1604.     }
  1605.     jr    cont
  1606.  
  1607. l1200
  1608.     ld    a,33
  1609.     {
  1610.         dec    a
  1611.         #if    nz,cont
  1612.     }
  1613.     jr    cont
  1614.  
  1615. l2400
  1616.     ld    a,11
  1617.     {
  1618.         dec    a
  1619.         #if    nz,cont
  1620.     }
  1621.     jr    cont
  1622.  
  1623. l4800
  1624.     or    a
  1625.     jp    cont
  1626.  
  1627.  
  1628.  
  1629.  
  1630. ; interrupt routine which receives an asynchronous character
  1631. int_rtn
  1632.     ld    (ssave_sp),sp
  1633.     ld    sp,int_sp
  1634.     push    af
  1635.     push    bc
  1636.     push    de
  1637.     push    hl
  1638.     push    ix
  1639. ;; was it a false interrupt (i.e. pending but now irrelevant?)
  1640. ;in    a,(piob_data)
  1641. ;and    1 shl ser_in        ;ignore old interrupts
  1642. ;call    nz,will_fit        ;if good int., is buffer full?
  1643. ;jr    z,abort
  1644.     ld    d,0            ;set for no transmit
  1645.     ld    a,(r_num)
  1646.     ld    e,a
  1647. ; Adjust e:=e-2 for 4800bd or e:=e+1 for others
  1648.     inc    e
  1649.     {
  1650.         ld    a,(simult)    ;low byte
  1651.         cp    l4800 and 0FFh
  1652.         #if    nz,break    ;compensate for long lead in time
  1653.         dec    e        ;to sample early to mid
  1654.         dec    e        ;and not sample start bit (which is OK)
  1655.         dec    e
  1656.     }
  1657. ; set up some things, then call simult routine ..
  1658.     call    jp_simul
  1659. ; store character, and wait for parity bit to be gone ..
  1660.     call    chk_break
  1661. ;
  1662. abort
  1663.     pop    ix
  1664.     pop    hl
  1665.     pop    de
  1666.     pop    bc
  1667.     pop    af
  1668.     ld    sp,(ssave_sp)
  1669.     ei
  1670. pio_clr
  1671.     reti
  1672.  
  1673.  
  1674. ; given de as an RS buffer index, give the next index in the
  1675. ; circular queue and return address in ix
  1676. next_RS
  1677.     push    af
  1678.     dec    de
  1679.     ld    a,d
  1680.     or    e
  1681.     jr    nz,cal_ix
  1682.     ld    de,(q_max)
  1683. cal_ix
  1684.     ld    ix,(q_base)
  1685.     add    ix,de
  1686.     pop    af
  1687.     ret
  1688.  
  1689.  
  1690. ; return de=next w_ptr and nz if there is room
  1691. will_fit
  1692.     ld    hl,(r_ptr)
  1693.     ld    de,(w_ptr)
  1694.     call    next_RS
  1695.     and    a
  1696.     sbc    hl,de
  1697.     ret
  1698.  
  1699.  
  1700.  
  1701.  
  1702. ; save acc in memory to avoid an extra stack level
  1703. par_int
  1704.     ld    (ssave_sp),a
  1705.     ld    a,0
  1706.     ld    (par_flag),a
  1707.     ld    a,(ssave_sp)
  1708.     ei
  1709.     reti
  1710.  
  1711. par_flag    defb    0    ;nz if printer has NOT ACKed yet
  1712. ssave_sp    defs    2    ;for saving SP when int. comes along
  1713. save_sp        defs    2    ;save main stack in BIOS routines
  1714.  
  1715. ; these defs belong to conio.z
  1716. ; 10 levels of stack (need 9)
  1717.         defs    20
  1718. int_sp                ;temp stack for int. RS232 input
  1719. RS_queue    defs    129    ;where incoming RS232 chars are stored
  1720. end_queue            ;last byte avail to RS232 buffer
  1721.  
  1722.  
  1723.     defs    2*32
  1724. bios_stack
  1725.     defw    recover        ;final return address
  1726.  
  1727. map_save
  1728.     db    bios_map
  1729.  
  1730. ; *******************************************************
  1731. ; * All code and data beyond this point may be occluded *
  1732. ; * by the VDU at F000 when "out" of the BIOS        *
  1733. ; *******************************************************
  1734.  
  1735.  
  1736.     if $ gt 0F000h
  1737.      error    critical code above F000h
  1738.      dw    $-0F000h+zero
  1739.     endif
  1740.  
  1741. ; Continuation of routine to call XBIOS functions
  1742. call_xbios:
  1743.     push    hl
  1744.     push    de
  1745.     ld    e,a        ;function number
  1746.     sla    e
  1747.     ld    d,0
  1748.     ld    hl,func_tab
  1749.     add    hl,de        ;hl=table address
  1750.     ld    e,(hl)
  1751.     inc    hl
  1752.     ld    d,(hl)
  1753.     ex    de,hl        ;hl=function address
  1754.     pop    de
  1755.     ex    (sp),hl        ;put hl on stack/ pop hl
  1756.     push    af
  1757.     map    bios_map
  1758.     pop    af
  1759.  
  1760.     cp    func_max+1
  1761.     ret    c        ;execute function if valid
  1762.     pop    ix        ;ignore function address
  1763. ; a call to an 'unused' xbios function will end up here
  1764. dud_ret    
  1765.     or    -1        ;error return - no such function
  1766.     ret            ;go to recover
  1767.  
  1768.  
  1769.  
  1770. ; XBIOS Function 0,1 : Set CCP mode
  1771. set_mode
  1772.     ld    (sh_wanted),a
  1773.  
  1774. ; At this stage the pointers to the extended command line should be restored
  1775. ; to their correct values
  1776.     push    hl
  1777.     ld    hl,free_128_bytes
  1778.     ld    (free_128_bytes-4),hl
  1779.     ld    hl,128
  1780.     ld    (free_128_bytes-2),hl
  1781.     pop    hl
  1782.  
  1783.     ret
  1784.  
  1785. ; The next 2 functions allow a program to check for legal
  1786. ; drives BEFORE calling the BDOS, thus stopping fatal
  1787. ; "select" errors ..
  1788. ; Function 2 : return number of drives starting at A
  1789. ret_drives
  1790.     ld    a,(snum_drives)
  1791.     ret
  1792.  
  1793. ; Function 3 : return 1 if M drive implemented, 0 if not
  1794. ret_mdrive
  1795.     ld    a,1
  1796.     ret
  1797.  
  1798. ; Function 4 : return interrupt vector table base
  1799. ret_ivec_base
  1800.     ld    hl,pioa_vect
  1801.     ret
  1802.  
  1803. ; Function 5 : return ptr in hl to 128 bytes free
  1804. ret_128_byte_block
  1805.     ld    hl,free_128_bytes
  1806.     xor    a        ;set Z flag - you can have it
  1807.     ret
  1808.  
  1809. ; Function 6 : purge all buffering for drive [c]
  1810. ; (elsewhere)
  1811.  
  1812. ; Function 7 : purge all directory buffers for drive [c]
  1813. ; (elsewhere)
  1814.  
  1815. ; Function 8 : return number of floppies in system (follow hards)
  1816. num_floppies
  1817.     ld    a,(snum_floppies)
  1818.     ret
  1819.  
  1820. ; Function 9 : tell BIOS to reselect drive on next access
  1821. ext_access
  1822.     ld    a,-1
  1823.     ld    (log_disk),a    ;so match fails
  1824.     ret
  1825.  
  1826. ; Function 10 : set serial port baud rate to [c] until next warm boot
  1827. xbs_baud
  1828.     ld    a,c
  1829.     jp    set_baud
  1830.  
  1831. ; Function 11 : receive serial character if available
  1832. ; return Z if character in A, NZ if none available
  1833. ; (RS_in is elsewhere)
  1834.  
  1835. ; Function 12 : send serial RS232 character in C
  1836. send_RSc
  1837.     ld    a,c
  1838.     jp    RS_out
  1839.  
  1840. ; Function 13 : set desired disk error mode in [c]:
  1841. ; [c] = FF -> normal CP/M mode - bomb out if an error occurs
  1842. ; [c] =  0 -> ignore errors (then use function 14 to detect them)
  1843. error_mode
  1844.     ld    a,c
  1845.     ld    (derr_mode),a
  1846.     ret
  1847.  
  1848. ; Function 14 : return status of last disk operation in [a]
  1849. ; Z  -> all OK
  1850. ; NZ -> physical error occured
  1851. ret_status
  1852.     ld    a,(erflag)
  1853.     ret
  1854.  
  1855. ; Function 15 : Test status of key (in CON512.MAC)
  1856. ;key_pressed
  1857.  
  1858. ; Function 16 : Set programmable key buffer according to Microbee's definition
  1859. ;set_mb_fkeys
  1860.  
  1861. ; Function 17 : Read programmable key buffer
  1862. get_mb_fkeys
  1863. ; zero fill as if all are empty (zero length)
  1864.     push    bc
  1865.     ld    b,12        ; 12 fkeys
  1866.     {
  1867.      ld    (hl),0
  1868.      #djnz
  1869.     }
  1870.     ld    hl,1024        ; Maximum available space, hahahaha !!!
  1871.     pop    bc
  1872. set_mb_fkeys
  1873.     xor    a
  1874.     ret
  1875.  
  1876.  
  1877. ; Function 24 : call graphics driver (elsewhere)
  1878.  
  1879.  
  1880. ; Function 25 : Call user program.
  1881. link_user
  1882.     push    hl
  1883.     ld    a,(user_page)
  1884.     or    a
  1885.     jp    z,no_grfx
  1886.     call    mem_page    ; Enable user's page (+ screen at 8000h ??)
  1887.     ld    hl,(user_addr)
  1888.     inc    hl        ; Entry point for XBIOS call at +3
  1889.     inc    hl
  1890.     inc    hl
  1891.     ld    (user_jp),hl
  1892.     ld    hl,recover_bmap
  1893.     ex    (sp),hl        ; Restore HL / put return address on stack
  1894. user_jp    equ    $+1
  1895.     jp    0        ; Jump to user program
  1896.     
  1897.  
  1898. ; Function 26 : get data from the RTC chip (maybe over a network)
  1899. ; this retries to ensure that no updates occurred during the read
  1900. ; without disabling interrupts for too long
  1901. ; Requires: HL = data pointer
  1902. ;         E = starting LOGICAL register (see ahead)
  1903. ;         B = number of registers to read
  1904. ; Returns: A, HL, DE registers corrupted
  1905. get_rtc
  1906.     call    rtc_pars
  1907.     {
  1908.         call    read_clock
  1909.         call    verify_clock
  1910.         #if    nz,cont
  1911.     }
  1912.     ret
  1913.  
  1914.  
  1915. ; Function 27 : put data to the RTC chip (maybe over a network)
  1916. ; this retries to ensure we don't get updated at the wrong time
  1917. ; Requires: HL = data pointer
  1918. ;         E = starting LOGICAL register (see ahead)
  1919. ;         B = number of registers to write
  1920. ; Returns:  A, HL, DE registers corrupted
  1921. put_rtc
  1922.     call    rtc_pars
  1923.     {
  1924.         call    write_clock
  1925.         call    verify_clock
  1926.         #if    nz,cont
  1927.     }
  1928.     ret
  1929.  
  1930.  
  1931. ; support subroutines for get_rtc and put_rtc ..
  1932. ; RTC_PARS:
  1933. ; Requires: HL = data address
  1934. ;        B  = number of registers to operate on
  1935. ;        E  = LOGICAL starting register
  1936. ; Returns:  HL = pointer to RTC address list (xlat table+offset)
  1937. ;        DE = data address
  1938. ;        B  = number of registers to operate upon
  1939. rtc_pars
  1940.     push    hl
  1941.     ld    hl,rtc_xlat
  1942.     ld    d,0
  1943.     add    hl,de        ;addresses pointer
  1944.     pop    de        ;data pointer
  1945.     ret
  1946.  
  1947.  
  1948. ; The RTC mapping table gives the following logical register numbers
  1949. ; 0    Year of century
  1950. ; 1    Month
  1951. ; 2    Date
  1952. ; 3    Weekday
  1953. ; 4    Hours
  1954. ; 5    Minutes
  1955. ; 6    Seconds
  1956. ; 7     Alarm hours
  1957. ; 8    Alarm minutes
  1958. ; 9    Alarm seconds
  1959. ; A-D    RTC Registers A-D
  1960. ;
  1961. rtc_xlat
  1962.     db    9,8,7,6,4,2,0,5,3,1,10,11,12,13
  1963.  
  1964.  
  1965. ; READ_CLOCK: read B bytes from the RTC with addresses in the
  1966. ; table at (hl) and put the data at (de)
  1967. ; All regs preserved except A
  1968. read_clock
  1969.     push    bc
  1970.     push    de
  1971.     push    hl
  1972.     {
  1973. ; Sync to the UIP bit with interrupts disabled, and then restore
  1974. ; after the operation has been done
  1975.         call    rtc_sync    ;sync with DI
  1976.         ld    a,(hl)
  1977.         out    (rtc_addr),a
  1978.         in    a,(rtc_read)
  1979.         ei
  1980.         ld    (de),a
  1981.         inc    hl
  1982.         inc    de
  1983.         #djnz
  1984.     }
  1985. com_pop
  1986.     pop    hl
  1987.     pop    de
  1988.     pop    bc
  1989.     ret
  1990.  
  1991.  
  1992. ; WRITE_CLOCK: as for READ_CLOCK, but write the data to the RTC
  1993. write_clock
  1994.     push    bc
  1995.     push    de
  1996.     push    hl
  1997.     {
  1998.         call    rtc_sync
  1999.         ld    a,(hl)
  2000.         out    (rtc_addr),a
  2001.         ld    a,(de)
  2002.         out    (rtc_write),a
  2003.         ei
  2004.         inc    hl
  2005.         inc    de
  2006.         #djnz
  2007.     }
  2008.     jr    com_pop
  2009.  
  2010.  
  2011. ; VERIFY_CLOCK: return Z if the data at (de) matches the data in
  2012. ; the RTC registers pointed to by (hl) for B bytes
  2013. verify_clock
  2014.     push    bc
  2015.     push    de
  2016.     push    hl
  2017.     {
  2018.         call    rtc_sync
  2019.         ld    a,(hl)
  2020.         out    (rtc_addr),a
  2021.         in    a,(rtc_read)
  2022.         ei
  2023.         ld    c,a
  2024.         ld    a,(de)
  2025.         cp    c
  2026.         #if    nz,brk
  2027.         inc    hl
  2028.         inc    de
  2029.         #djnz
  2030.     }
  2031.     jr    com_pop
  2032.  
  2033.  
  2034. ; RTC_SYNC: Wait for Update in progress bit to go to 0, and
  2035. ; return with interrupts disabled to allow one register operation
  2036. ; Returns: AF destroyed
  2037. rtc_sync
  2038.     {
  2039.         ei
  2040.         nop            ;allow interrupt window
  2041.         ld    a,10
  2042.         di
  2043.         out    (rtc_addr),a
  2044.         in    a,(rtc_read)
  2045.         bit    7,a
  2046.         #if    nz,cont
  2047.     }
  2048.     ret
  2049.  
  2050.  
  2051.     if    scramble
  2052.  
  2053. jp_decrypt:
  2054.     ret
  2055.     nop
  2056.     nop
  2057.  
  2058. encrypt_start:
  2059.     db    98h,76h,54h,32h
  2060.     endif
  2061.  
  2062.  
  2063. ; select page number in A using table
  2064. mem_page
  2065.     push    hl
  2066.     push    de
  2067.     if    mem_128
  2068.      and    3        ; max allowed is 128k
  2069.     else
  2070.      if    telecomputer
  2071.       and    7        ; max allowed is 256k
  2072.      else
  2073.       and    15        ; max allowed is 512k
  2074.      endif
  2075.     endif
  2076.     ld    hl,page_table
  2077.     ld    e,a
  2078.     ld    d,0
  2079.     add    hl,de
  2080.     ld    a,(hl)
  2081.     pop    de
  2082.     pop    hl
  2083.     out    (map_port),a
  2084.     ret
  2085.  
  2086. ; values corresponding to pages 0 .. max (15)
  2087. ; may be modified for different memory configuration
  2088. ; eg. 256k, 320k
  2089. page_table
  2090. ;    if    mem_128
  2091. ;     db    14h,15h,16h,17h        ; forced to be 128k only system
  2092. ;    else
  2093. ;     if    telecomputer
  2094. ;      db    14h,15h,16h,17h        ; Telecomputer seems to use bit 5
  2095. ;      db    34h,35h,36h,37h
  2096. ;     else
  2097. ;      db    14h,15h,16h,17h        ; 'Standard' 512k system
  2098. ;      db    54h,55h,56h,57h        ; with screen in at 8000h
  2099. ;      db    94h,95h,96h,97h
  2100. ;      db    0D4h,0D5h,0D6h,0D7h
  2101. ;     endif
  2102. ;    endif
  2103.     if    mem_128
  2104.      db    0Ch,0Dh,0Eh,0Fh        ; forced to be 128k only system
  2105.     else
  2106.      if    telecomputer
  2107.       db    0Ch,0Dh,0Eh,0Fh        ; Telecomputer seems to use bit 5
  2108.       db    2Ch,2Dh,2Eh,2Fh
  2109.      else
  2110.       db    0Ch,0Dh,0Eh,0Fh        ; 'Standard' 512k system
  2111.       db    4Ch,4Dh,4Eh,4Fh
  2112.       db    8Ch,8Dh,8Eh,8Fh
  2113.       db    0CCh,0CDh,0CEh,0CFh
  2114.      endif
  2115.     endif
  2116.  
  2117.  
  2118. ; boot routines that can be stuck behind screen to cut down
  2119. ; code size before F000h
  2120. common_boot
  2121. ; Set CPU speed
  2122.     ld    a,(fast_cpu)    ;True (FF) for fast
  2123.     and    speed_value    ;Set appropriate bit
  2124.     in    a,(speed_port)    ;Set hardware
  2125.  
  2126. ; put system linkages at 0000h, 0005h and 0028h
  2127. ; set BIOS warm start and BIOS pointer
  2128. ;    map    bios_map
  2129.     ld    a,0C3H        ;JP opcode
  2130.     ld    (biosv),a
  2131.     ld    hl,wboote
  2132.     ld    (biosv+1),hl
  2133. ; set up system call entry point
  2134.     ld    (cpmv),a    ;JP at 5
  2135.     ld    hl,bdosin
  2136.     ld    (cpmv+1),hl
  2137. ; set up restart for extended BIOS calls
  2138.     ld    (xbs_rst),a
  2139.     ld    hl,x_bios_calls
  2140.     ld    (xbs_rst+1),hl
  2141.  
  2142. ; make BIOS look at drive before using it
  2143. ;;;;    call    ext_access
  2144.  
  2145. ; set baud rate
  2146.     ld    a,(pr_baud)
  2147.     call    set_baud
  2148.  
  2149. ; reset deblocking flags
  2150.     xor    a        ;block/deblock initialization
  2151.     ld    (hstact),a    ;set host inactive
  2152.     ld    (unacnt),a    ;set for no unall. left
  2153.  
  2154. ; initialise 6545-1/6845E
  2155.     ld    hl,crtc_tab+15
  2156.     call    crtc_fill    ;set up 6545 as desired (patchable)
  2157.  
  2158.     map    sys_vdr
  2159.  
  2160.     call    copy_inv    ;set up inverses
  2161.  
  2162.     ret
  2163.  
  2164. ; Call to check validity of ram disks and format if invalid
  2165. ; system page must be enabled at this point
  2166. check_ramdisks
  2167. ; Format M: if force_format is true
  2168. ; or if previous size is different to current size
  2169. ; Must also format N: if M: size is different
  2170.     sflag    0,'2',sys_vdr
  2171.     ld    ix,check_ram_m        ; previous value for M:, +1 = N:
  2172.     ld    iy,pages_for_md        ; +2 = pages for N:
  2173.     ld    a,(iy)
  2174.     cp    (ix)
  2175.     ld    (ix),a
  2176.     jr    nz,fmt_m_n
  2177.     ld    a,(force_format)
  2178.     or    a
  2179.     call    nz,fmt_m
  2180. ; Format N: if previous size is different
  2181.     sflag    0,'3',sys_vdr
  2182.     ld    a,(iy+2)
  2183.     cp    (ix+1)
  2184.     ret    z
  2185. fmt_n:
  2186.     ld    a,(iy+2)    ; is N: enabled ?
  2187.     ld    (ix+1),a    ; this must be updated here
  2188.     or    a
  2189.     ret    z
  2190.     ld    a,(iy)        ; find first N drive page
  2191.     add    a,3
  2192.     call    mem_page
  2193.     call    do_fmt
  2194.     ld    a,'N'
  2195.     ld    (9),a
  2196.     ret
  2197.  
  2198. fmt_m_n:
  2199.     call    fmt_n
  2200.     sflag    0,'4',sys_vdr
  2201. fmt_m:
  2202.     map    md_page_1
  2203.     call    do_fmt
  2204.     ld    a,'M'
  2205.     ld    (9),a
  2206.     map    sys_page
  2207.     ret
  2208.  
  2209. do_fmt:
  2210.     ld    hl,0
  2211.     ld    de,1
  2212.     ld    bc,256*32-1    ; 256 directory entries is plenty
  2213.     ld    (hl),0E5h
  2214.     ldir
  2215.     ld    hl,md_name    ; put label into ram disk
  2216.     ld    de,0
  2217.     ld    c,16
  2218.     ldir
  2219.     xor    a
  2220.     ld    b,16
  2221. d_f1:
  2222.     ld    (de),a
  2223.     inc    de
  2224.     djnz    d_f1
  2225.     ret
  2226.  
  2227. ; directory label for RAM disk ( '-RAMDISK.M: ' set to $SYS )
  2228. md_name
  2229.     db    0,'-RAMDISKM',':'+80h,' ',0,0,0,0
  2230.  
  2231.  
  2232. ; on every nth call to this subroutine 
  2233. ;  and if status line enabled
  2234. ;    call status update routine (in system page, from bios file)
  2235. ; all used registers must be saved
  2236. display_time
  2237.     push    hl
  2238.     ld    hl,time_cycle
  2239.     dec    (hl)
  2240.     jr    nz,dt_ret
  2241.     ld    (hl),cycle_max
  2242.     push    af
  2243.     ld    a,(s_line)
  2244.     cp    25
  2245.     jr    nz,dt_ret1
  2246.     map    sys_vdr
  2247.     call    print_s_line
  2248.     map    bios_map
  2249. dt_ret1:
  2250.     pop    af
  2251. dt_ret:
  2252.     pop    hl
  2253.     ret
  2254.  
  2255.  
  2256. ; PRINTER and PUNCH routines
  2257. ; allow for most printers ..
  2258. ptr_out
  2259.     ld    a,(send_lf)
  2260.     or    a
  2261.     #if    nz,nxt
  2262.     ld    a,c
  2263. ; if send_lf=0, ignore linefeeds
  2264.     cp    lf
  2265.     ret    z        ;ignore linefeeds
  2266. #mark
  2267.     ld    a,(iobyte)
  2268.     bit    6,a
  2269.     ld    a,c
  2270.     jp    z,bpar_out    ;PARALLEL printer
  2271.  
  2272. ; must be SERIAL, so if not Xon/Xoff, just send it
  2273. ; also entry point for PUNCH output
  2274. pun_out
  2275.     ld    a,(use_xonxoff)
  2276.     or    a
  2277.     ld    a,c
  2278.     jp    z,RS_out
  2279.  
  2280. ; Xon/Xoff serial ..
  2281.     {
  2282.         call    set_se        ;update status
  2283.         ld    a,(x_flag)
  2284.         or    a
  2285.         #if    z,cont        ;wait for ^Q to continue
  2286.     }
  2287.     ld    a,c
  2288.     jp    RS_out        ;send byte
  2289.  
  2290. ; assume speed is already set, and check for Xon, Xoff
  2291. set_se
  2292.     push    af
  2293.     call    RS_in        ;RS232 check and input
  2294.     #if    nz,nxt        ;no char was received
  2295.     res    7,a
  2296.     sub    xoff
  2297.     ld    (x_flag),a    ;nz if O.K. to send
  2298. #mark
  2299.     pop    af
  2300.     ret
  2301.  
  2302.  
  2303. ; RS232 input routine to acc.
  2304. pun_in
  2305.     {
  2306.         call    RS_in        ;RS232 check and input
  2307.         #if    nz,cont
  2308.     }
  2309.     res    7,a
  2310.     ret
  2311.  
  2312.  
  2313. ; Common LIST status routine
  2314. all_listst
  2315.     ld    a,(iobyte)
  2316.     and    0C0h
  2317.     cp    80h        ;PARALLEL printer?
  2318.     jp    z,p_listst
  2319.     cp    0C0h        ;serial mode?
  2320.     ld    a,0FFh
  2321.     ret    nz        ;VDU is always ready
  2322.  
  2323. ; serial status - either XON/XOFF or CTS based
  2324.     ld    a,(use_xonxoff)
  2325.     or    a
  2326.     jp    z,s_listst    ;use CTS based status
  2327. ; Use Xon/Xoff status
  2328. xlistst
  2329.     call    set_se        ;update status
  2330.     ld    a,(x_flag)
  2331.     or    a
  2332.     ret    z        ;not ready to print
  2333.     cpl            ;to 0FFH -> ready to print
  2334.     ret
  2335.  
  2336.  
  2337.  
  2338.  
  2339. ; Select drive and return hl= DPH address
  2340. ; given bc=drive number, bit 0 of e=1 if not new unit
  2341. d_seldsk
  2342. ; Swap A: and M:/N: if required
  2343.     ld    hl,swap_a_with_m    ; = 'M'-'A' or 'N'-'A'
  2344.     ld    a,c
  2345.     or    a        ; cp  'A'-'A'
  2346.     jr    z,ds_is_a
  2347.     cp    (hl)
  2348.     jr    nz,no_m_swap
  2349. ds_is_a
  2350.     xor    (hl)
  2351.     ld    c,a
  2352.  
  2353. no_m_swap
  2354.     ld    (sekdsk),a    ;for deblocking routines
  2355.  
  2356.     ld    hl,md_dph    ;request for M: ?
  2357.     cp    'M'-'A'
  2358.     ret    z
  2359.  
  2360.     ld    hl,nd_dph    ;request for N: ?
  2361.     cp    'N'-'A'
  2362.     jr    nz,not_n
  2363.     ld    a,(pages_for_nd)    ;is it there ?
  2364.     or    a
  2365.     jr    z,sel_err
  2366. ;    jp    z,sel_err
  2367.     ret
  2368.  
  2369. not_n
  2370.     ld    hl,snum_drives
  2371.     cp    (hl)        ;drive A,B,C or D?
  2372.     jr    c,valid_drive
  2373.  
  2374.     cp    'L'-'A'
  2375.     jr    nz,sel_err
  2376.     ld    a,(hl)        ;Only allow L: if < 4 drives
  2377.     cp    4
  2378.     jr    z,sel_err
  2379.     ld    a,'D'-'A'    ;drive L -> D
  2380.     ld    (sekdsk),a    ;sekdsk as well
  2381.     ld    c,a        ;reg c as well
  2382.  
  2383. valid_drive
  2384.     ld    h,0
  2385.     ld    l,c
  2386.     add    hl,hl
  2387.     add    hl,hl
  2388.     add    hl,hl
  2389.     add    hl,hl        ;hl=drive_num*16
  2390.     ld    a,e
  2391.     ld    de,dpbase    ;Index into DPBASE
  2392.     add    hl,de
  2393.     rrca            ;test the new unit bit
  2394.     ret    c        ;old unit, so don't worry
  2395. ; a new unit has been selected, so check its format
  2396.     push    hl        ;save start of this DPH
  2397.  
  2398. ; purge everything buffered for drive c since disk has changed
  2399.     call    purge_c
  2400.  
  2401.     ld    a,c        ;drive number
  2402.     call    log_select    ;select that drive (hard)
  2403.     #if    nz,nxt        ;error - no disk in drive etc.
  2404. ;
  2405.  
  2406. ; All the following denstiy select stuff is irrelevant if ...
  2407.     if    not preset_disks
  2408.  
  2409.     ld    hl,dden_byte    ;=08H if double density, 0 if not
  2410.     ld    a,(sec_length)    ;00=128; 01=256; 02=512
  2411.     rlca            ;*2
  2412.     bit    dden_sel,(hl)
  2413.     jr    z,sd_sel    ;if single density format
  2414.     dec    a
  2415. sd_sel
  2416.     #if    m,next        ;error - 128 byte double density !
  2417.     cp    4
  2418.     #if    nc,nxt        ;error - 512 single density or 1024 !
  2419. ; now multiply by 18 (length of DPB+xlt_word+mask_byte)
  2420.     rlca            ;*2
  2421.     ld    l,a
  2422.     rlca            ;*4
  2423.     rlca            ;*8
  2424.     rlca            ;*16
  2425.     add    a,l        ;*18
  2426.     ld    l,a
  2427.     ld    h,0
  2428.     ld    de,dpb_base    ;first DPB in list
  2429.     add    hl,de        ;hl points to correct DPB
  2430.     push    hl
  2431.     ld    a,c        ;sekdsk (disk being selected)
  2432.     call    dpfnd        ;hl=1+posn of DPB ptr in DPH
  2433. ; de=old contents of DPB pointer, has this been set to user def'd?
  2434.     ld    a,e
  2435.     pop    de
  2436.     {
  2437.      cp    low spare_dpb    ;lower byte of spare dpb address?
  2438.      #if    z,brk        ;if so, leave it alone
  2439. ; set DPB pointer in DPH to point to correct DPB for this disk
  2440.      ld    (hl),d
  2441.      dec    hl
  2442.      ld    (hl),e
  2443.     }
  2444.     endif
  2445.  
  2446.     pop    hl        ;pop off start of relevant DPH
  2447.     ret
  2448. #mark
  2449. ; Select error !
  2450.     pop    hl
  2451. sel_err
  2452.     ld    hl,usrdfd    ;reboot to A0:
  2453.     ld    (hl),0
  2454.     ld    hl,0        ;tell CP/M its an error
  2455.     ret
  2456.  
  2457.  
  2458. ; Sector translate table routine (skewing done in h_setup)
  2459. sectran
  2460.     ld    h,b        ;return exactly what we are given
  2461.     ld    l,c
  2462.     ret
  2463.  
  2464.  
  2465. ; select the drive in a (maybe logically)
  2466. ; return z if no errors (a is undefined)
  2467. ;    or nz and a<>0 if an error occurs
  2468. ; a "logical" disk is selected if the number of the disk
  2469. ; asked for is greater than the last physical drive in
  2470. ; the system
  2471. ; Destroys C
  2472. log_select
  2473.     ld    c,a
  2474.     ld    a,(log_disk)    ;previously selected disk
  2475.     sub    c
  2476.     ret    z        ;same as before, return z,0
  2477.     ld    a,c
  2478.     ld    (log_disk),a    ;same as required
  2479. ;
  2480.     or    a
  2481.     jr    z,drive_a    ;if drive A is selected
  2482.  
  2483. ; compare with number of drives set by INIT
  2484.     push    hl
  2485.     ld    hl,snum_drives
  2486.     cp    (hl)
  2487.     pop    hl
  2488.  
  2489.     jr    c,log_fn    ;select physical disk
  2490. ; select a logical (virtual) disk
  2491. do_swap
  2492.     ld    a,(active)    ;(active)=-1 -> log. disk in A
  2493.     or    a
  2494.     jr    nz,sel_a    ;already swapped
  2495. sel_tog
  2496.     cpl            ;active <-> non-active
  2497.     ld    (active),a
  2498.     ld    a,c
  2499.  
  2500. ; if not drive A, replace with drive L
  2501.     or    a
  2502.     #if    z,nxt
  2503.     ld    a,'L'-'A'    ;logical drive !
  2504. #mark
  2505.  
  2506.     add    a,'A'        ;put drive name into message
  2507.     ld    (name_mnt),a
  2508.     push    hl
  2509.     push    bc
  2510.     ld    hl,mnt_mess
  2511.     call    flash        ;FLASH
  2512. ; purge all buffers for drive a since disk has been changed
  2513.     ld    c,0
  2514.     call    purge_c
  2515.  
  2516.     pop    bc
  2517.     pop    hl
  2518. sel_a
  2519.     xor    a        ;use drive A
  2520. log_fn
  2521.     jp    sel_floppy
  2522. ;
  2523. ; drive A has been selected, so if necc., swap
  2524. ; and clear (active)
  2525. drive_a
  2526.     ld    a,(active)
  2527.     or    a
  2528.     jr    z,sel_a        ;not active
  2529.     jr    sel_tog        ;has wrong disk in drive A, so swap
  2530. ;
  2531. ;
  2532. d_sdm
  2533.     ld    (dmaadr),bc
  2534.     ret
  2535. ;
  2536. d_ssc
  2537.     ld    a,c
  2538.     ld    (seksec),a
  2539.     ret
  2540. ;
  2541. d_home
  2542.     ld    c,0
  2543. d_stk
  2544.     ld    a,c
  2545.     ld    (sektrk),a
  2546.     ret
  2547. ;
  2548. ;
  2549. ; Deblocked read and write a CP/M record (128 bytes)
  2550. d_read
  2551.     push    ix        ;used to access DPB bits
  2552.     call    ix_tab        ;point ix to relevant DPB
  2553.     ld    a,wrual        ;treat read as unallocated
  2554.     ld    (wrtype),a
  2555.     ld    (readop),a    ;set for read operation
  2556.     jr    alloc
  2557. ;
  2558. d_write
  2559.     push    ix
  2560.     call    ix_tab        ;point ix to relevant DPB
  2561.     xor    a        ;set for write operation
  2562.     ld    (readop),a
  2563.     ld    a,c        ;write type from CP/M
  2564.     ld    (wrtype),a
  2565.     cp    wrual        ;unallocated write (first of block)
  2566.     jr    nz,chkuna
  2567. ; this is the first record of an unallocated block, so
  2568. ; remember where it is in case we are writing sequentially
  2569.     ld    hl,(sekdsk)    ;disk and track number
  2570.     ld    (unadsk),hl
  2571.     ld    a,(seksec)    ;sector number
  2572.     ld    (unasec),a
  2573. ; now find out how many CP/M records in a "block", the fundamental
  2574. ; allocation unit (1024 for small disks, 2048 for large)
  2575. ; this is so that we know when the unallocated block is all
  2576. ; gone (assuming sequential writes)
  2577.     ld    a,(ix+3)    ;BLM
  2578.     inc    a
  2579.     ld    (unacnt),a
  2580. ; check to see whether the current record being written is the
  2581. ; next in a sequential series of writes
  2582. chkuna
  2583.     ld    hl,unacnt
  2584.     xor    a
  2585.     cp    (hl)        ;any left ?
  2586.     jr    z,alloc        ;if not, then preread (allocated)
  2587.     dec    (hl)        ;decrement # remaining
  2588. ; now see if this is the CORRECT record for seq. writing of a block
  2589.     ld    hl,(unadsk)
  2590.     call    comp        ;compare (unadsk) with (sekdsk)
  2591.     jr    nz,alloc    ;not the next record
  2592.     ld    hl,unasec    ;compare (unasec) with (seksec)
  2593.     ld    a,(seksec)
  2594.     cp    (hl)
  2595.     jr    nz,alloc    ;not the next record
  2596. ; now step unatrk/unasec to next record so that we can tell whether
  2597. ; the next record to be written after this one is the next of the block
  2598.     inc    (hl)
  2599.     ld    a,(hl)
  2600.     cp    (ix+0)        ;# CP/M records per track
  2601.     jr    c,noovf        ;stays on the same track
  2602.     ld    (hl),0        ;start with first sector
  2603.     dec    hl        ;point to track number
  2604.     inc    (hl)        ;next track inwards
  2605. ; no pre-read is required, so set rsflag=0
  2606. noovf
  2607.     xor    a
  2608.     jr    alloc1
  2609. ;
  2610. ; not an unallocated record, so requires pre-read ..
  2611. alloc
  2612.     xor    a        ;a=0
  2613.     ld    (unacnt),a    ;kill current sequence
  2614.     inc    a        ;a=1
  2615. alloc1
  2616.     ld    (rsflag),a
  2617. ;
  2618. ; rwoper:
  2619.     xor    a
  2620.     ld    (erflag),a    ;reset error flag (no errors yet)
  2621. ; now calculate (unskewed) host sector number
  2622.     ld    a,(seksec)    ;CP/M record number
  2623.     rlca            ;once left
  2624.     ld    e,(ix+dsecmsk)
  2625.     {
  2626.      srl    a        ;then right to kill unwanted bits
  2627.      rrc    e
  2628.      #if    c,cont        ;continue until mask shifted out
  2629.     }
  2630.     ld    (sekhst),a
  2631. ;
  2632.     ld    hl,hstact
  2633.     ld    a,(hl)        ;see if already active
  2634.     ld    (hl),1        ;set it to active anyway
  2635.     or    a        ;was it already?
  2636.     jr    z,filhst    ;if it wasn't, may need to fill
  2637. ; host buffer is active, but is it the same as seek buffer ?
  2638.     ld    hl,(hstdsk)    ;disk # and track #
  2639.     call    comp        ;compare (hstdsk) with (sekdsk)
  2640.     jr    nz,nomatch
  2641.     ld    hl,hstsec
  2642.     ld    a,(sekhst)    ;physical but unskewed sector #
  2643.     cp    (hl)
  2644.     jr    z,match        ;host buffer is the same as before
  2645. nomatch
  2646.     call    hst_flush    ;write out old host buffer if necc.
  2647. ; now set host buffer to suit "sek" sector
  2648. filhst
  2649.     ld    hl,(sekdsk)    ;desired disk, track
  2650.     ld    (hstdsk),hl
  2651.     ld    a,(sekhst)    ;physical (unskewed) sector #
  2652.     ld    (hstsec),a
  2653. ; now pre-read (or just read) if neccessary
  2654.     ld    a,(rsflag)
  2655.     or    a
  2656.     call    nz,readhst
  2657.     xor    a
  2658.     ld    (hstwrt),a    ;kill pending write flag
  2659. ; copy data to or from buffer
  2660. match
  2661.     ld    a,(seksec)    ;CP/M record number
  2662.     and    (ix+dsecmsk)    ;keep ls bits to index into buffer
  2663.     ld    h,a
  2664.     ld    l,0
  2665.     srl    h
  2666.     rr    l        ;hl=offset into buffer for record
  2667.     ld    de,hstbuf
  2668.     add    hl,de        ;hl=start of record in buffer
  2669.     ld    de,(dmaadr)    ;where in main memory to get/put
  2670. ; now if it is a write, swap hl,de and mark the pending write
  2671.     ld    a,(readop)
  2672.     or    a
  2673.     #if    nz,nxt        ;READing
  2674.     ex    de,hl        ;swap so moving into buffer
  2675.     inc    a
  2676.     ld    (hstwrt),a    ;(hstwrt)=1
  2677. #mark
  2678.     ld    bc,128        ;length of CP/M record
  2679.     ldir            ;nice quick transfer
  2680. ; now flush buffer immediately if a directory write
  2681.     ld    a,(wrtype)
  2682.     dec    a        ;directory write?
  2683.     #if    nz,nxt        ;if not a directory write
  2684.     ld    a,(erflag)    ;=1 if any errors occurred
  2685.     or    a
  2686.     #if    nz,nxt        ;don't try to write if bad read
  2687.     ld    (hstwrt),a    ;buffer written
  2688.     call    writehst
  2689. #mark
  2690.     ld    a,(erflag)    ;return error code to CP/M
  2691.     ld    hl,derr_mode
  2692.     and    (hl)        ;mask off errors maybe
  2693.     pop    ix
  2694.     ret
  2695.  
  2696.  
  2697. ; flush the host buffer if necc.
  2698. ; All regs except [a] preserved
  2699. hst_flush
  2700.     push    bc
  2701.     push    de
  2702.     push    hl
  2703.  
  2704.     ld    a,(hstwrt)
  2705.     or    a
  2706.     call    nz,writehst
  2707.     xor    a
  2708.     ld    (hstwrt),a
  2709.  
  2710.     pop    hl
  2711.     pop    de
  2712.     pop    bc
  2713.     ret
  2714.  
  2715.  
  2716. ; write host sector with
  2717. ; (hstdsk)= disk drive number to use (0-15)
  2718. ; (hstsec)= unskewed physical sector number (0-17)
  2719. ; (hsttrk)= track number (0-79)
  2720. writehst
  2721.     ld    a,(hstdsk)
  2722.     cp    'M'-'A'        ;M: or N: ?
  2723.     jp    nc,md_write
  2724.     call    fl_write    ;do physical write (write-thru)
  2725.     call    db_sector_type
  2726.     jr    nz,ret_bmap    ; can't be buffered
  2727.     jp    db_disk_write
  2728.  
  2729.  
  2730. fl_write
  2731.     call    hsetup
  2732.     {
  2733.         call    z,wr_floppy    ;write tk-d, sec-e, adr-hl
  2734.         #if    z,brk
  2735.         in    a,(status)
  2736.         bit    6,a        ;protect fault ?
  2737.         ld    a,1        ;CP/M wants a one
  2738.         #if    z,brk        ;if not bomb out
  2739. ; prompt with message and wait for RETURN
  2740.         ld    a,(log_disk)
  2741.         add    a,'A'
  2742.         ld    (wp_name),a    ;store name of WPed drive
  2743.         ld    hl,wp_mess
  2744.         call    flash
  2745.         call    hsetup        ;try to write once more
  2746.         call    z,wr_floppy
  2747.     }
  2748. ret_err
  2749.     ld    hl,erflag
  2750.     or    (hl)        ;OR in the error
  2751.     ld    (hl),a
  2752.     jr    ret_bmap
  2753.  
  2754.  
  2755. fl_read
  2756.     push    bc
  2757.     call    hsetup
  2758.     call    z,rd_floppy    ;read tk-d, sec-e, adr-hl
  2759.     pop    bc
  2760.     jr    ret_err
  2761.  
  2762.  
  2763. ; read host sector, parameters as for write
  2764. readhst
  2765.     ld    a,(hstdsk)
  2766.     cp    'M'-'A'        ; M: or N: ?
  2767.     jp    nc,md_read
  2768.     call    db_sector_type
  2769.     jr    nz,fl_read        ; can't be buffered
  2770.     call    db_disk_preread        ; get it from buffer if available
  2771.     ret    z            ; yes it was so don't read from disk
  2772.     call    fl_read            ; otherwise get it from disk
  2773.     jp    z,db_disk_postread    ; only buffer if no error
  2774. ret_bmap:
  2775.     map    bios_map        ; This is oh so important !!
  2776.     ret
  2777.  
  2778.  
  2779. ; return :
  2780. ;     d=(hsttrk) with b7=1 for side 1
  2781. ;     e=skewed (hstsec)
  2782. ;     hl=hstbuf and Z flag set, a=0
  2783. ; OR NZ, a=1 if cannot select required drive
  2784. ; destroys bc
  2785. hsetup
  2786.     ld    a,(hstdsk)
  2787.     call    log_select    ;select logical (or physical disk)
  2788.     ld    a,1        ;standard error return value
  2789.     ret    nz        ;hardware error
  2790.     push    ix        ;save ix for (secdsk)
  2791. ;
  2792.     ld    a,(hstdsk)
  2793.     call    x_tab        ;ix=dpb for drive (hst_dsk)
  2794. ; put track number in d so can select other side for "cylinder" disks
  2795.     ld    a,(hsttrk)    ;desired track
  2796.     bit    1,(ix+dflags)
  2797.     jr    nz,calc_sec    ;don't modify tk number at all
  2798.     bit    0,(ix+dflags)
  2799.     jr    z,old_format
  2800. ; use bottom bit to select side number (cylinder format)
  2801.     rrca
  2802. ;
  2803. calc_sec
  2804.     ld    d,a
  2805.     ld    a,(hstsec)    ;logical sector number (shifted)
  2806.     add    a,(ix+dxlt)    ;add on start for this xlt table
  2807.     ld    c,a
  2808.     ld    b,0
  2809.     ld    hl,xlt_base
  2810.     add    hl,bc
  2811. ;
  2812.     ld    e,(hl)        ;get skewed sector number
  2813.     ld    hl,hstbuf    ;where to put/get data
  2814.     xor    a        ;indicate no errors
  2815.     pop    ix
  2816.     ret
  2817. ;
  2818. ; handle formats which go in on side 0 first, and then
  2819. ; come back out on side 1
  2820. old_format
  2821.     cp    40
  2822.     jr    c,calc_sec    ;track number 0..39
  2823. ; range 40..79, so reduce it to 0..39 and set b7 for side 1
  2824.     ld    d,a
  2825.     ld    a,79
  2826.     sub    d
  2827.     set    7,a        ;indicate other side
  2828.     jr    calc_sec
  2829. ;
  2830. ;
  2831. ; compare hl with (sekdsk)
  2832. comp
  2833.     ld    de,(sekdsk)
  2834.     and    a
  2835.     sbc    hl,de
  2836.     ret
  2837. ;
  2838. ; find address of DPB (and xlt table address and secmsk)
  2839. ; for the drive in a
  2840. ; return address of DPH ptr + 1 in hl and DPB address in de
  2841. dpfnd
  2842.     ld    hl,Md_DPH+10
  2843.     cp    'M'-'A'
  2844.     jr    z,dpf_got
  2845.     ld    hl,Nd_DPH+10
  2846.     cp    'N'-'A'
  2847.     jr    z,dpf_got
  2848.     ld    h,0
  2849.     ld    l,a
  2850.     add    hl,hl
  2851.     add    hl,hl
  2852.     add    hl,hl
  2853.     add    hl,hl        ;hl*drive_num*16
  2854.     ld    de,dpbase+10
  2855.     add    hl,de        ;hl=posn of DPB ptr in DPH
  2856. dpf_got
  2857.     ld    e,(hl)
  2858.     inc    hl
  2859.     ld    d,(hl)
  2860.     ret
  2861. ;
  2862. ; return ix pointing to the DPB etc for (sekdsk) drive
  2863. ; destroy af
  2864. ix_tab
  2865.     ld    a,(sekdsk)
  2866. x_tab
  2867.     push    hl
  2868.     push    de
  2869.  
  2870.     call    dpfnd
  2871.     push    de
  2872.     pop    ix
  2873.  
  2874.     pop    de
  2875.     pop    hl
  2876.     ret
  2877.  
  2878. ; Read sector from either ramdisk
  2879. md_read
  2880. ; select correct page and get addr in de, hl=hstbuf, bc=512
  2881.     call    md_addr
  2882.     ex    de,hl
  2883.     ldir
  2884.     out    (map_port),a    ; revert to bios map
  2885.     xor    a        ; no error occured
  2886.     ret
  2887.  
  2888. ; Write sector to either ramdisk
  2889. md_write
  2890.     call    md_addr
  2891.     ldir
  2892.     out    (map_port),a    ; revert to bios map
  2893.     ret
  2894.  
  2895.  
  2896. ; get addresses for block move to host buffer
  2897. ; returns: de = position in 0-7FFF of sector
  2898. ;       hl = hstbuf
  2899. ;       bc = mdrive sector size
  2900. ;       a  = bios_map
  2901. md_addr
  2902.     ld    a,(hstsec)
  2903.     ld    e,0
  2904.     srl    a
  2905.     rr    e
  2906.     ld    d,a
  2907.     ld    a,(hsttrk)
  2908.     rrca
  2909.     rrca
  2910.     rrca
  2911.     ld    b,a
  2912.     rrca
  2913.     and    70h
  2914.     add    a,d
  2915.     ld    d,a
  2916.     ld    a,b
  2917.     add    a,3
  2918.     call    mem_page
  2919.     ld    hl,hstbuf
  2920.     ld    bc,128
  2921.     ld    a,bios_map
  2922.     ret
  2923.  
  2924.  
  2925.  
  2926.  
  2927.  
  2928. ; I/O include files :
  2929.  
  2930. ; console IO
  2931.     include     CON512T.MAC
  2932.  
  2933. ; disk cache
  2934.     include        DB512.MAC
  2935.  
  2936.     if    scramble
  2937. end_encrypt:
  2938.     db    12h,34h,56h,78h
  2939.     endif
  2940.  
  2941. ; floppy disk IO
  2942.     include        FL512.MAC
  2943.  
  2944. ;;%%%%%%%%%%%
  2945. ;; purge all directory entries for drive [c]
  2946. ;; this is used before the BDOS delete/rename function is performed
  2947. ;; to ensure that we don't write bad data on a changed disk
  2948. ;; this also kills the deblocking buffer
  2949. ;; All regs preserved except a
  2950. ;purgedir_c
  2951. ;;*    ld    a,flop_dir_trk    ;purge all less/equal to this number
  2952. ;;*    #nxt
  2953. ;; purge all entries for drive [c]
  2954. ;; this is used during seldsk to ensure that the reboot
  2955. ;; actually gets new data from the new disk
  2956. ;; All regs preserved except a
  2957. ;;   bank 1 map set
  2958. ;purge_c
  2959. ;;*    ld    a,255        ;all sectors will be purged
  2960. ;;*#mark
  2961. ;    call    hst_flush
  2962. ;    xor    a
  2963. ;    ld    (hstact),a
  2964. ;    ret
  2965. ;;%%%%%%%%%%%%
  2966.  
  2967.  
  2968. mnt_mess
  2969.     defm    ' INSERT "DISK '
  2970. name_mnt
  2971.     defm    'M:" INTO DRIVE A, THEN PRESS <RETURN> ',80H
  2972.  
  2973. wp_mess
  2974.     defm    ' DISK '
  2975. wp_name
  2976.     defm    'M: IS WRITE PROTECTED - PRESS <RETURN> TO TRY AGAIN ',80H
  2977.  
  2978.  
  2979. ; Non-critical preset BIOS scratch ..
  2980. log_disk
  2981.     db    0        ;disk currently selected
  2982. active
  2983.     db    0        ;0 -> logical disk not active
  2984. x_flag
  2985.     db    0FFh        ;nz -> can send initially
  2986.  
  2987. offs_start
  2988.     dw    0        ; offset for jumping to user interface
  2989.  
  2990. ; first available address in system page (for shell, ccp)
  2991. sys_avail
  2992.     dw    bios-orgad+bdos_save_addr
  2993.  
  2994. derr_mode
  2995.     db    0FFh        ;0 to ignore disk error returns
  2996.  
  2997. time_cycle
  2998.     db    cycle_max    ; update status line after n'th BIOS call
  2999.  
  3000. ; The B##### SOD who wrote the 128k system has just caused me about three
  3001. ; weeks of fruitless searching for an elusive bug. All because the B######
  3002. ; put this label in the 'ds' section (implies uninitialised) when it MUST
  3003. ; be initialised. If not then it can cause the BIOS to attempt to write to
  3004. ; a random disk/track/sector.
  3005. ; Fixed - 14/1/88
  3006. hstwrt
  3007.     db    0        ;=1 if host buffer has pending write
  3008.  
  3009. cpm_end    equ    $        ;end marker for boot and reboot
  3010.  
  3011. ; Non-critical uninitialised BIOS scratch ..
  3012.  
  3013. ; DO NOT alter the relative postions of the following labels
  3014. sh_loaded    equ    $        ; nz if shell loaded
  3015.  
  3016. sh_start    equ    sh_loaded+1    ;where shell should go
  3017.  
  3018. sh_length    equ    sh_start+2    ;length of shell
  3019.  
  3020. sh_save_start    equ    sh_length+2    ;address of saved shell
  3021.  
  3022. ccp_loaded    equ    sh_save_start+2        ; ditto for CCP
  3023.  
  3024. ccp_start    equ    ccp_loaded+1
  3025.  
  3026. ccp_length    equ    ccp_start+2
  3027.  
  3028. ccp_save_start    equ    ccp_length+2
  3029.  
  3030. window_loaded    equ    ccp_save_start+2    ; nz if WINDOW.SYS loaded
  3031.  
  3032. temp_1        equ    window_loaded+1    ; 2 bytes for any temp value
  3033. temp_2        equ    temp_1+1
  3034.  
  3035. flag        equ    temp_2+1    ;indicates RS232 input during last o/p
  3036. ;
  3037. ;    BDOS scratch
  3038. dmaadr    equ    flag+1        ;last address to transfer record to
  3039. ;
  3040. sekdsk    equ    dmaadr+2    ;seek disk number (0-3)
  3041. sektrk    equ    sekdsk+1    ;seek track number
  3042. seksec    equ    sektrk+1    ;seek sector number
  3043. ; do not rearrange the order of these ..
  3044. hstdsk    equ    seksec+1    ;host disk number (args to hstread/hstwrite)
  3045. hsttrk    equ    hstdsk+1    ;host track number
  3046. hstsec    equ    hsttrk+1    ;host sector number
  3047. ;
  3048. sekhst    equ    hstsec+1    ;(seksec) shr secshf
  3049. hstact    equ    sekhst+1    ;=1 if host buffer active
  3050. ; hstwrt must be initialised !!
  3051. ;hstwrt    equ    hstact+1    ;=1 if host buffer has pending write
  3052. ;
  3053. unacnt    equ    hstact+1    ;unalloc record count
  3054. unadsk    equ    unacnt+1    ;next unalloc record's disk
  3055. unatrk    equ    unadsk+1    ;next unalloc record's track
  3056. unasec    equ    unatrk+1    ;next unalloc record's sector
  3057. ;
  3058. erflag    equ    unasec+1    ;=1 if an error occurred
  3059. rsflag    equ    erflag+1    ;=1 if host sector must be read
  3060. readop    equ    rsflag+1    ;=1 if read operation
  3061. wrtype    equ    readop+1    ;write type from CP/M
  3062.  
  3063. ; This seems to be necessary to assemble - Why ??
  3064. ; Z80.COM seems to be adding refs to it.
  3065. total_errs    equ    wrtype+1
  3066.  
  3067. last_equ    equ    total_errs+2
  3068.  
  3069. ; Host buffer (512 bytes)
  3070. hstbuf        equ    0FE00h
  3071.  
  3072. ; somewhere to flash to
  3073. save_p        equ    hstbuf-60
  3074.  
  3075.     if    last_equ gt save_p
  3076.      error    too big for memory !!!
  3077.      dw    last_equ-save_p+zero
  3078.     endif
  3079.  
  3080.     .dephase
  3081.  
  3082. sys_page_r    equ    $
  3083.  
  3084.     .phase    0
  3085.  
  3086. ; Start of routines that are shoved down into the system page to stop
  3087. ; those annoying memory overflow errors
  3088.  
  3089. ; Check if this is a premium
  3090. ; also perform a few other cold boot functions
  3091. check_premium:
  3092.     if    not telecomputer
  3093. ; Find if premium : check if more than 1 PCG page
  3094.      ld    hl,pcg
  3095.      ld    a,81h        ;PCG 1
  3096.      out    (vml),a
  3097.      ld    a,(hl)        ;Get a test byte
  3098.      cpl            ;Complement it ("What lovely bits you have!")
  3099.      ld    c,a        ;Remember it
  3100.      ld    a,80h        ;PCG 0
  3101.      out    (vml),a
  3102.      ld    (hl),c        ;Write new test value in PCG 0
  3103.      ld    a,81h
  3104.      out    (vml),a        ;PCG 1
  3105.      ld    a,c        ;Get new test value
  3106.      sub    (hl)        ;if PCG 1 changed then not premium
  3107.      jr    z,not_prem
  3108.     
  3109. is_prem:
  3110.      ld    a,true
  3111.      ld    (is_premium),a
  3112. not_prem:
  3113.      and    'P'
  3114.      ld    (smsg_premium),a
  3115.  
  3116.      xor    a
  3117.      out    (vml),a
  3118. ;     out    (crtc),a
  3119.     
  3120.     endif
  3121.  
  3122.     if    scramble
  3123.      ld    hl,0C3h+((low decrypt)*256)
  3124.      ld    (jp_decrypt),hl
  3125.     endif
  3126.  
  3127. ; Put end char at start of function key strings.
  3128.     ld    hl,fn_store
  3129.     ld    b,num_fn_keys
  3130.     ld    de,80h
  3131. {
  3132.     ld    (hl),fn_str_end
  3133.     add    hl,de
  3134.     #djnz
  3135. }
  3136. ; Place RET's at locations in system page, so calls fail before BIOS.SYS loaded
  3137.     ld    hl,bios_sys_start
  3138.     ld    b,+(3*20)
  3139. {
  3140.     ld    (hl),0C9h
  3141.     inc    hl
  3142.     #djnz
  3143. }
  3144.  
  3145. ; Clear status line
  3146.     ld    hl,vdu+(24*80)
  3147.     ld    b,80
  3148. {
  3149.     ld    (hl),' '
  3150.     inc    hl
  3151.     #djnz
  3152. }
  3153.  
  3154.     ret
  3155.  
  3156.  
  3157. ; Copy inverses from ROM to PCG
  3158. copy_inv:    
  3159. ;    push    af
  3160. ;    push    bc
  3161. ;    push    de
  3162. ;    push    hl
  3163.  
  3164. ; fill in colour ram with desired value and fix inverses
  3165.     ld    a,40H        ;turn on colour ram
  3166.     out    (col_port),a
  3167.  
  3168. c_b_3:
  3169.     ld    hl,col_ram
  3170.     ld    a,(col_char)
  3171.     {
  3172.         ld    (hl),a
  3173.         inc    hl
  3174.         bit    3,h
  3175.         #if    nz,cont
  3176.     }
  3177. ; Set up status line colour
  3178.     ld    a,(col_stat)
  3179.     ld    hl,status_start-2+800h
  3180.     ld    b,80
  3181.     {
  3182.         ld    (hl),a
  3183.         inc    hl
  3184.         #djnz
  3185.     }
  3186.  
  3187.     ld    a,(col_mode)    ;low intensity background (patchable)
  3188.     out    (col_port),a    ;give it zero -> select PCG
  3189.  
  3190. ; If premium then enable and zero attribute RAM
  3191.     if    not telecomputer
  3192.     ld    ix,is_premium
  3193.     bit    0,(ix)
  3194.     jr    z,c_b_1
  3195.     endif
  3196.     ld    a,90h
  3197.     out    (vml),a
  3198.     ld    hl,vdu
  3199.     {
  3200.         ld    (hl),0
  3201.         inc    hl
  3202.         bit    3,h
  3203.         #if    z,cont
  3204.     }
  3205. ; this is done later
  3206. ;    ld    a,80h
  3207. ;    out    (vml),a
  3208.  
  3209. c_b_1:
  3210.  
  3211.     ld    a,1
  3212.     out    (rom_port),a    ; rom-read=1
  3213.     if    not telecomputer
  3214.     bit    0,(ix)
  3215.     jr    z,c_i_1        ; not premium
  3216.     endif
  3217. ; is premium so load PCG 1 with bold
  3218.     ld    a,81h
  3219.     out    (vml),a
  3220.     ld    hl,vdu
  3221.     ld    de,pcg
  3222. copy1_bold:
  3223.     ld    a,(hl)
  3224.     sla    a
  3225.     or    (hl)
  3226.     ld    (de),a
  3227.     inc    hl
  3228.     inc    de
  3229.     bit    3,h
  3230.     jr    z,copy1_bold
  3231.     ld    a,80h        ; PCG 0 and leave graphics etc. enabled
  3232.     out    (vml),a
  3233. c_i_1:
  3234.     ld    hl,vdu        ; now inverse
  3235.     ld    de,pcg
  3236. copy1_inv:    
  3237.     ld    a,(hl)
  3238.     cpl            ; inverse character
  3239.     ld    (de),a
  3240.     inc    hl
  3241.     inc    de
  3242.     bit    3,h
  3243.     jr    z,copy1_inv
  3244.     xor    a
  3245.     out    (rom_port),a    ; back to display
  3246. ;    pop    hl
  3247. ;    pop    de
  3248. ;    pop    bc
  3249. ;    pop    af
  3250.     ret
  3251.  
  3252.  
  3253.  
  3254. ; table of pointers etc. for updating status line
  3255. sl_pointers:
  3256. ; 'fn key'
  3257.     dw    in_fnstr        ; pointer to value
  3258.     db    fn_mes-sl_msgs        ; offset of message
  3259.     db    fn_sl-status_start    ; offset on status line
  3260.     db    len_fn_mes        ; length of message
  3261. ; 'lock'
  3262.     dw    al_rev
  3263.     db    lock_mes-sl_msgs
  3264.     db    lock_sl-status_start
  3265.     db    len_lock_mes
  3266. ; 'fn active'
  3267.     dw    fn_active
  3268.     db    fn_on_mes-sl_msgs
  3269.     db    fn_on_sl-status_start
  3270.     db    len_fn_on_mes
  3271. ; 'a<>m'
  3272.     dw    swap_a_with_m
  3273.     db    swap_a_m_mes-sl_msgs
  3274.     db    swap_a_m_sl-status_start
  3275.     db    len_swap_a_m_mes
  3276. ; 'fast'
  3277.     dw    fast_cpu
  3278.     db    fast_mes-sl_msgs
  3279.     db    fast_sl-status_start
  3280.     db    len_fast_mes
  3281.  
  3282.  
  3283. ; status line messages
  3284. sl_msgs:
  3285.  
  3286. fast_mes:
  3287.     db    'FAST'
  3288. len_fast_mes        equ    $-fast_mes
  3289.  
  3290. swap_a_m_mes:
  3291.     db    'A<>M'
  3292. len_swap_a_m_mes    equ    $-swap_a_m_mes
  3293.  
  3294. lock_mes:
  3295.     db    'LOCK'
  3296. len_lock_mes    equ    $-lock_mes
  3297.  
  3298. fn_on_mes:
  3299.     db    'FKEY'
  3300. len_fn_on_mes    equ    $-fn_on_mes
  3301.  
  3302. fn_mes:
  3303.     db    'PRESSED'
  3304. len_fn_mes    equ    $-fn_mes
  3305.  
  3306. ; get shell / CCP out of system page
  3307. load_user_int
  3308. ;;    map    sys_page
  3309.     ld    hl,sh_wanted    ;0 for CCP, 1 for shell
  3310.     ld    a,(hl)
  3311. load_user_int_1
  3312.     or    a
  3313.     jr    z,l_u2
  3314.     ld    a,(sh_loaded)
  3315.     or    a
  3316.     jr    z,not_in_mem
  3317.     ld    hl,(sh_save_start)
  3318.     ld    de,(sh_start)
  3319.     push    de
  3320.     ld    bc,(sh_length)
  3321.     jr    l_u1
  3322. l_u2:
  3323.     ld    a,(ccp_loaded)
  3324.     or    a
  3325.     jr    z,not_in_mem
  3326.     ld    hl,(ccp_save_start)
  3327.     ld    de,(ccp_start)
  3328.     push    de
  3329.     ld    bc,(ccp_length)
  3330. l_u1:
  3331.     ldir
  3332.     pop    hl        ; hl --> start of shell/ccp
  3333.     ld    de,(offs_start)
  3334.     add    hl,de
  3335.     ret
  3336.  
  3337.  
  3338. ; wanted shell or ccp but it isn't in memory
  3339. not_in_mem:
  3340.     ld    a,(hl)
  3341.     xor    1
  3342.     ld    (hl),a
  3343.     jr    load_user_int_1
  3344.  
  3345. ; get bdos from system page
  3346. bdos_from_bp
  3347.     ld    hl,bdos_save_addr
  3348.     ld    de,orgad
  3349.     ld    bc,bios-orgad
  3350.     ldir
  3351.     ret
  3352.  
  3353. ; Extended BIOS function call table ..
  3354. func_tab
  3355.     dw    set_mode        ;0  - set CCP
  3356.     dw    set_mode        ;1  - set shell
  3357.     dw    ret_drives        ;2  - # drives to a
  3358.     dw    ret_mdrive        ;3  - if Mdrive, a=1, else 0
  3359.     dw    ret_ivec_base        ;4  - hl = ivec base
  3360.     dw    ret_128_byte_block    ;5  - hl points to 128 bytes free
  3361.     dw    purge_c            ;6  - purge all buffers for drive c
  3362.     dw    purgedir_c        ;7  - purge dir for drive c
  3363.     dw    num_floppies        ;8  - returns number of floppies
  3364.     dw    ext_access        ;9  - inform BIOS to reselect drive
  3365.     dw    xbs_baud        ;10 - set baud rate to c (0..)
  3366.     dw    RS_in            ;11 - get RS232 char if available
  3367.     dw    send_RSc        ;12 - send RS232 char in C
  3368.     dw    error_mode        ;13 - set disk error mode (0=ignore)
  3369.     dw    ret_status        ;14 - return status of disk operation
  3370.     dw    key_pressed        ;15 - check if key is down
  3371.     dw    set_mb_fkeys        ;16 - set Microbee style fkeys
  3372.     dw    get_mb_fkeys        ;17 - get ditto.  Haha - ignored!!!!
  3373.     dw    dud_ret            ;18
  3374.     dw    dud_ret            ;19
  3375.     dw    link_graphics        ;20 - link to graphics driver
  3376.     dw    dud_ret            ;21
  3377.     dw    dud_ret            ;22
  3378.     dw    dud_ret            ;23
  3379.     dw    link_graphics        ;24 - link to graphics driver
  3380.     dw    link_user        ;25 - link to user program
  3381.     dw    get_rtc            ;26 - fetch data from RTC chip
  3382.     dw    put_rtc            ;27 - put data to the RTC chip
  3383.  
  3384. func_end
  3385.  
  3386. ; maximum function number allowed
  3387. func_max    equ    (func_end-func_tab)/2-1
  3388.  
  3389.  
  3390.  
  3391. end_sys_r    equ    $
  3392.  
  3393.     .dephase
  3394.  
  3395.     if    ($-100h) gt (10240)
  3396.      error    too big to fit on system tracks !!!
  3397.      dw    zero+$-100h
  3398.     endif
  3399.  
  3400.     if    ($-100h) lt 10240
  3401. ; pad out code to occupy 10k for compatibility with SETSYS.
  3402.      ds    10240-($-100h)
  3403.     endif
  3404.  
  3405.     end
  3406.